// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Application Deployment Options

== Overview

Apache Ignite.NET consists of .NET assemblies and Java jar files. The .NET assemblies are referenced by your project and
are copied to an output folder during the build automatically. The JAR files should be copied manually.
Ignite.NET discovers them via the `IgniteHome` or `JvmClasspath` settings.

This page introduces several most-commonly used deployment options of Ignite.NET nodes.

== Full Binary Package Deployment

* Copy the https://ignite.apache.org[whole Ignite distribution package, window=_blank] along with your application
* Set the `IGNITE_HOME` environment variable or `IgniteConfiguration.IgniteHome` setting to point to that folder

== NuGet Deployment

The post-build event is updated automatically during the Ignite.NET NuGet package installation to copy jar files to
`Libs` folder in the output directory (see link:quick-start/dotnet[Getting Started]).
Make sure to include that `Libs` folder when distributing your binaries.

Make sure `IGNITE_HOME` is not set globally. Normally you don't need to set `IGNITE_HOME` with NuGet, except for
ASP.NET deployments (see below).

[tabs]
--
tab:Post-Build Event[]
[source,shell]
----
if not exist "$(TargetDir)Libs" md "$(TargetDir)Libs"
xcopy /s /y "$(SolutionDir)packages\Apache.Ignite.1.6.0\Libs\*.*" "$(TargetDir)Libs"
----
--

== Custom Deployment

The JAR files are located in the `libs` folder of the binary distribution and NuGet package.
The minimum set of jars for Ignite.NET is:

* `ignite-core-{VER}.jar`
* `cache-api-1.0.0.jar`
* `ignite-indexing` folder (if SQL queries are used)
* `ignite-spring` folder (if a Spring XML configuration is used)

=== Deploying JARs to a default location:

* Copy the JAR files to the `Libs` folder next to Apache.Ignite.Core.dll
* Do not set the `IgniteConfiguration.JvmClasspath`, `IgniteConfiguration.IgniteHome` properties and `IGNITE_HOME` environment variable

=== Deploying jar files to an arbitrary location:

* Copy the JAR files somewhere
* Set the `IgniteConfiguration.JvmClasspath` property to a semicolon-separated string of paths for each jar file
* Do not set the `IGNITE_HOME` environment variable and `IgniteConfiguration.IgniteHome` property

[tabs]
--
tab:IgniteConfiguration.JvmClasspath Example[]
[source,shell]
----
c:\ignite-jars\ignite-core-1.5.0.final.jar;c:\ignite-jars\cache-api-1.0.0.jar
----
--

== ASP.NET Deployment

`JvmClasspath` or `IgniteHome` have to be explicitly set when using Ignite in a web environment (IIS and IIS Express),
because DDL files are copied to temporary folders, and Ignite can not locate JAR files automatically.

You can set `IgniteHome` like this in ASP.NET environment:

[tabs]
--
tab:C#[]
[source,csharp]
----
Ignition.Start(new IgniteConfiguration
{
    IgniteHome = HttpContext.Current.Server.MapPath(@"~\bin\")
});
----
--

Alternatively, `IGNITE_HOME` can be set globally. Add this line at the top of the `Application_Start` method in `Global.asax.cs`:

[tabs]
--
tab:C#[]
[source,csharp]
----
Environment.SetEnvironmentVariable("IGNITE_HOME", HttpContext.Current.Server.MapPath(@"~\bin\"));
----
--

Finally, you can use the following method to populate `JvmClasspath`:
[tabs]
--
tab:C#[]
[source,csharp]
----
static string GetDefaultWebClasspath()
{
    var dir = HttpContext.Current.Server.MapPath(@"~\bin\libs");

    return string.Join(";", Directory.GetFiles(dir, "*.jar"));
}
----
--

== IIS Application Pool Lifecycle, AppDomains, and Ignite.NET

There is a known problem with IIS. When a web application is restarted due to code changes or a manual restart,
the application pool process remains alive, while AppDomain gets recycled.

Ignite.NET automatically stops when AppDomain is unloaded. However, a new domain may be started when old one is still
unloading. So the node from the old domain can have an `IgniteConfiguration.IgniteInstanceName` conflict with a node from the new domain.

To fix this issue make sure to either assign a unique `IgniteInstanceName`, or set
`IgniteConfiguration.AutoGenerateIgniteInstanceName` property to `true`.

[tabs]
--
tab:Use in C#[]
[source,csharp]
----
var cfg = new IgniteConfiguration { AutoGenerateIgniteInstanceName = true };
----
tab:web.config[]
[source,xml]
----
<igniteConfiguration autoGenerateIgniteInstanceName="true">
  ...
</igniteConfiguration>
----
--

Refer to the http://stackoverflow.com/questions/42961879/how-do-i-retrieve-a-started-ignite-instance-when-a-website-restart-occurs-in-iis/[following StackOverflow discussion, window=_blank]
for more details.
