IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer
authorPavel Tupitsyn <ptupitsyn@apache.org>
Tue, 14 Nov 2017 14:17:56 +0000 (17:17 +0300)
committerPavel Tupitsyn <ptupitsyn@apache.org>
Tue, 14 Nov 2017 14:17:56 +0000 (17:17 +0300)
This closes #2985

47 files changed:
modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs [deleted file]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs [moved from modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IUnmanagedTarget.cs with 62% similarity]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs [moved from modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs with 67% similarity]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs [new file with mode: 0644]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs [moved from modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedContext.cs with 60% similarity]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs [deleted file]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs [deleted file]
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1 [deleted file]
modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj
modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj
modules/platforms/dotnet/Apache.Ignite.ndproj
modules/platforms/dotnet/Apache.Ignite.sln
modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs
modules/platforms/dotnet/DEVNOTES.txt

index 4508776..ade81cc 100644 (file)
@@ -25,7 +25,7 @@
     <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
     <DebugType>full</DebugType>
     <PlatformTarget>AnyCPU</PlatformTarget>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>Apache.Ignite.AspNet.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -39,6 +39,7 @@
     <CodeAnalysisRuleSet>Apache.Ignite.AspNet.ruleset</CodeAnalysisRuleSet>
     <DocumentationFile>bin\Release\Apache.Ignite.AspNet.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <PropertyGroup>
     <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
index 6c7e2b8..2ef6db1 100644 (file)
     <Compile Include="Common\IgniteGuidTest.cs" />
     <Compile Include="Deployment\RuntimeDependencyFunc.cs" />
     <Compile Include="EventsTestLocalListeners.cs" />
+    <Compile Include="Process\ListDataReader.cs" />
     <Compile Include="Log\ConcurrentMemoryTarget.cs" />
     <Compile Include="Log\DefaultLoggerTest.cs" />
     <Compile Include="Log\Log4NetLoggerTest.cs" />
     <Compile Include="Log\NLogLoggerTest.cs" />
+    <Compile Include="MultiAppDomainTest.cs" />
     <Compile Include="Plugin\Cache\CacheJavaPluginConfiguration.cs" />
     <Compile Include="Plugin\Cache\CacheJavaPluginTest.cs" />
     <Compile Include="Plugin\PluginTest.cs" />
index b5d8367..9593777 100644 (file)
@@ -81,10 +81,17 @@ namespace Apache.Ignite.Core.Tests.Cache
                             Name = "myMemPolicy",
                             InitialSize = 77 * 1024 * 1024,
                             MaxSize = 99 * 1024 * 1024
+                        },
+                        new MemoryPolicyConfiguration
+                        {
+                            Name = MemoryConfiguration.DefaultDefaultMemoryPolicyName,
+                            InitialSize = 55 * 1024 * 1024,
+                            MaxSize = 88 * 1024 * 1024
                         }
                     }
                 },
 #pragma warning restore 618
+                DataStorageConfiguration = null,
                 SpringConfigUrl = "Config\\cache-default.xml"
             };
 
index 7ccee94..67319f4 100644 (file)
@@ -102,6 +102,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         {
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
+                DataStorageConfiguration = null,
                 MemoryConfiguration = new MemoryConfiguration
                 {
                     DefaultMemoryPolicyName = MemoryPolicyWithMetrics,
index a6b9b3b..63a9f47 100644 (file)
@@ -60,7 +60,8 @@ namespace Apache.Ignite.Core.Tests.Cache
                     WalStorePath = Path.Combine(_tempDir, "WalStore"),
                     WalArchivePath = Path.Combine(_tempDir, "WalArchive"),
                     MetricsEnabled = true
-                }
+                },
+                DataStorageConfiguration = null
             };
 
             const string cacheName = "persistentCache";
@@ -116,7 +117,8 @@ namespace Apache.Ignite.Core.Tests.Cache
         {
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
-                PersistentStoreConfiguration = new PersistentStoreConfiguration()
+                PersistentStoreConfiguration = new PersistentStoreConfiguration(),
+                DataStorageConfiguration = null
             };
 
             // Default config, inactive by default (IsActiveOnStart is ignored when persistence is enabled).
index a0d54e4..cc86db7 100644 (file)
@@ -61,6 +61,8 @@ namespace Apache.Ignite.Core.Tests.Compute
 
             File.WriteAllText(path, text);
 
+            Assert.IsTrue(File.Exists(path));
+
             return path;
         }
     }
index 3ab5ed3..ed556b4 100644 (file)
@@ -52,10 +52,10 @@ namespace Apache.Ignite.Core.Tests
             _stdErr = Console.Error;
 
             _outSb = new StringBuilder();
-            Console.SetOut(new StringWriter(_outSb));
+            Console.SetOut(new MyStringWriter(_outSb));
 
             _errSb = new StringBuilder();
-            Console.SetError(new StringWriter(_errSb));
+            Console.SetError(new MyStringWriter(_errSb));
         }
 
         /// <summary>
@@ -64,8 +64,12 @@ namespace Apache.Ignite.Core.Tests
         [TearDown]
         public void TearDown()
         {
+            MyStringWriter.Throw = false;
+
             Console.SetOut(_stdOut);
             Console.SetError(_stdErr);
+
+            Ignition.StopAll(true);
         }
 
         /// <summary>
@@ -81,6 +85,18 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
+        /// Tests the exception in console writer.
+        /// </summary>
+        [Test]
+        public void TestExceptionInWriterPropagatesToJavaAndBack()
+        {
+            MyStringWriter.Throw = true;
+
+            var ex = Assert.Throws<IgniteException>(() => Ignition.Start(TestUtils.GetTestConfiguration()));
+            Assert.AreEqual("foo", ex.Message);
+        }
+
+        /// <summary>
         /// Tests startup error in Java.
         /// </summary>
         [Test]
@@ -145,8 +161,11 @@ namespace Apache.Ignite.Core.Tests
                     LoaderOptimization = LoaderOptimization.MultiDomainHost
                 });
 
+                var type = typeof(IgniteRunner);
+                Assert.IsNotNull(type.FullName);
+
                 var runner = (IIgniteRunner)childDomain.CreateInstanceAndUnwrap(
-                    typeof(IgniteRunner).Assembly.FullName, typeof(IgniteRunner).FullName);
+                    type.Assembly.FullName, type.FullName);
 
                 runner.Run();
             }
@@ -174,5 +193,25 @@ namespace Apache.Ignite.Core.Tests
                 // Will be stopped automatically on domain unload.
             }
         }
+
+        private class MyStringWriter : StringWriter
+        {
+            public static bool Throw { get; set; }
+
+            public MyStringWriter(StringBuilder sb) : base(sb)
+            {
+                // No-op.
+            }
+
+            public override void Write(string value)
+            {
+                if (Throw)
+                {
+                    throw new Exception("foo");
+                }
+
+                base.Write(value);
+            }
+        }
     }
 }
index 1d80c60..eb329af 100644 (file)
@@ -32,6 +32,9 @@ namespace Apache.Ignite.Core.Tests
     /// </summary>
     public class DeploymentTest
     {
+        /** */
+        private string _tempFolder;
+
         /// <summary>
         /// Tests the custom deployment where IGNITE_HOME can't be resolved, and there is a user-defined classpath.
         /// </summary>
@@ -39,35 +42,12 @@ namespace Apache.Ignite.Core.Tests
         public void TestCustomDeployment()
         {
             // Create temp folder
-            var folder = IgniteUtils.GetTempDirectoryName();
-
-            // Copy jars
-            var home = IgniteHome.Resolve(null);
-
-            var jarNames = new[] {@"\ignite-core-", @"\cache-api-1.0.0.jar", @"\modules\spring\" };
-
-            var jars = Directory.GetFiles(home, "*.jar", SearchOption.AllDirectories)
-                .Where(jarPath => jarNames.Any(jarPath.Contains)).ToArray();
-
-            Assert.Greater(jars.Length, 3);
-
-            foreach (var jar in jars)
-            {
-                var fileName = Path.GetFileName(jar);
-                Assert.IsNotNull(fileName);
-                File.Copy(jar, Path.Combine(folder, fileName), true);
-            }
+            var folder = _tempFolder;
+            DeployTo(folder);
 
             // Build classpath
             var classpath = string.Join(";", Directory.GetFiles(folder).Select(Path.GetFileName));
 
-            // Copy .NET binaries
-            foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, GetType().Assembly})
-            {
-                Assert.IsNotNull(asm.Location);
-                File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
-            }
-
             // Copy config
             var springPath = Path.GetFullPath("config\\compute\\compute-grid2.xml");
             var springFile = Path.GetFileName(springPath);
@@ -88,38 +68,97 @@ namespace Apache.Ignite.Core.Tests
 
             Assert.IsNotNull(proc);
 
-            try
-            {
-                VerifyNodeStarted(exePath);
-            }
-            finally
+            VerifyNodeStarted(exePath);
+        }
+
+        /// <summary>
+        /// Tests missing JARs.
+        /// </summary>
+        [Test]
+        public void TestMissingJarsCauseProperException()
+        {
+            // Create temp folder
+            var folder = _tempFolder;
+            DeployTo(folder);
+
+            // Build classpath
+            var classpath = string.Join(";",
+                Directory.GetFiles(folder).Where(x => !x.Contains("ignite-core-")).Select(Path.GetFileName));
+
+            // Start a node and check the exception.
+            var exePath = Path.Combine(folder, "Apache.Ignite.exe");
+            var reader = new ListDataReader();
+
+            var proc = IgniteProcess.Start(exePath, string.Empty, args: new[]
             {
-                proc.Kill();
-
-                Assert.IsTrue(
-                    TestUtils.WaitForCondition(() =>
-                    {
-                        try
-                        {
-                            Directory.Delete(folder, true);
-                            return true;
-                        }
-                        catch (Exception)
-                        {
-                            return false;
-                        }
-                    }, 1000), "Failed to remove temp directory: " + folder);
-            }
+                "-jvmClasspath=" + classpath,
+                "-J-ea",
+                "-J-Xms512m",
+                "-J-Xmx512m"
+            }, outReader: reader);
+
+            // Wait for process to fail.
+            Assert.IsNotNull(proc);
+            Assert.IsTrue(proc.WaitForExit(10000));
+            Assert.IsTrue(proc.HasExited);
+            Assert.AreEqual(-1, proc.ExitCode);
+
+            // Check error message.
+            Assert.AreEqual("ERROR: Apache.Ignite.Core.Common.IgniteException: Java class is not found " +
+                            "(did you set IGNITE_HOME environment variable?): " +
+                            "org/apache/ignite/internal/processors/platform/PlatformIgnition",
+                reader.GetOutput().First());
         }
 
         /// <summary>
-        /// Fixture tear down.
+        /// Sets up the test.
         /// </summary>
-        [TestFixtureTearDown]
-        public void TestFixtureTearDown()
+        [SetUp]
+        public void SetUp()
+        {
+            _tempFolder = IgniteUtils.GetTempDirectoryName();
+        }
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
         {
             Ignition.StopAll(true);
             IgniteProcess.KillAll();
+
+            Directory.Delete(_tempFolder, true);
+        }
+
+        /// <summary>
+        /// Deploys binaries to specified folder
+        /// </summary>
+        private void DeployTo(string folder)
+        {
+            // Copy jars.
+            var home = IgniteHome.Resolve(null);
+
+            var jarNames = new[] {@"\ignite-core-", @"\cache-api-1.0.0.jar", @"\modules\spring\"};
+
+            var jars = Directory.GetFiles(home, "*.jar", SearchOption.AllDirectories)
+                .Where(jarPath => jarNames.Any(jarPath.Contains)).ToArray();
+
+            Assert.Greater(jars.Length, 3);
+
+            foreach (var jar in jars)
+            {
+                var fileName = Path.GetFileName(jar);
+                Assert.IsNotNull(fileName);
+                File.Copy(jar, Path.Combine(folder, fileName), true);
+            }
+
+            // Copy .NET binaries
+            foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, GetType().Assembly})
+            {
+                Assert.IsNotNull(asm.Location);
+                File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
+            }
         }
 
         /// <summary>
index 8f422f4..b885d28 100644 (file)
@@ -320,10 +320,7 @@ namespace Apache.Ignite.Core.Tests
                 Assert.IsTrue(proc.Join(30000, out exitCode));
                 Assert.AreEqual(-1, exitCode);
 
-                lock (reader.List)
-                {
-                    Assert.AreEqual(err, reader.List.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x)));
-                }
+                Assert.AreEqual(err, reader.GetOutput().FirstOrDefault(x => !string.IsNullOrWhiteSpace(x)));
             };
 
             checkError("blabla", "ERROR: Apache.Ignite.Core.Common.IgniteException: Missing argument value: " +
@@ -477,18 +474,5 @@ namespace Apache.Ignite.Core.Tests
             /// </summary>
             public int JvmMaxMemoryMb { get; set; }
         }
-
-        private class ListDataReader : IIgniteProcessOutputReader
-        {
-            public readonly List<string> List = new List<string>();
-
-            public void OnOutput(System.Diagnostics.Process proc, string data, bool err)
-            {
-                lock (List)
-                {
-                    List.Add(data);
-                }
-            }
-        }
     }
 }
index f68371a..6e09704 100644 (file)
@@ -249,6 +249,7 @@ namespace Apache.Ignite.Core.Tests
             // When Spring XML is used, .NET overrides Spring.
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
+                DataStorageConfiguration = null,
                 SpringConfigUrl = @"config\spring-test.xml",
                 NetworkSendRetryDelay = TimeSpan.FromSeconds(45),
                 MetricsHistorySize = 57
index 529128a..aa292ab 100644 (file)
@@ -229,7 +229,7 @@ namespace Apache.Ignite.Core.Tests
                 JvmClasspath = TestUtils.CreateTestClasspath()
             };
 
-            for (var i = 0; i < 20; i++)
+            for (var i = 0; i < 50; i++)
             {
                 Console.WriteLine("Iteration: " + i);
 
@@ -239,16 +239,12 @@ namespace Apache.Ignite.Core.Tests
 
                 if (i % 2 == 0) // Try to stop ignite from another thread.
                 {
-                    var t = new Thread(() => {
-                        grid.Dispose();
-                    });
-
-                    t.Start();
-
-                    t.Join();
+                    Task.Factory.StartNew(() => grid.Dispose()).Wait();
                 }
                 else
+                {
                     grid.Dispose();
+                }
 
                 GC.Collect(); // At the time of writing java references are cleaned from finalizer, so GC is needed.
             }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs
new file mode 100644 (file)
index 0000000..0157255
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests Ignite behavior in multi-AppDomain scenario.
+    /// Such a scenario occurs within IIS, for example, or within application plugins.
+    /// </summary>
+    [Category(TestUtils.CategoryIntensive)]
+    public class MultiAppDomainTest
+    {
+        /** */
+        public const string CacheName = "cache";
+
+        /** */
+        private readonly List<AppDomain> _domains = new List<AppDomain>();
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
+        {
+            Ignition.StopAll(true);
+
+            UnloadDomains();
+        }
+
+        /// <summary>
+        /// Tests the IIS behavior:
+        /// when application is restarted, new AppDomain is started while old one is still running.
+        /// </summary>
+        [Test]
+        public void TestIisBehavior()
+        {
+            var ignite = Ignition.Start(GetConfig());
+            
+            var cache = ignite.CreateCache<int, int>(new CacheConfiguration
+            {
+                Name =  CacheName,
+                CacheMode = CacheMode.Replicated  // Use Replicated to avoid data loss due to node stop.
+            });
+
+            cache[1] = 1;
+
+            // Check same domain.
+            new DomainRunner().RunTest();
+
+            var type = typeof(DomainRunner);
+            Assert.IsNotNull(type.FullName);
+
+            // Start and stop domains.
+            for (var i = 0; i < 10; i++)
+            {
+                var domain = CreateDomain(i);
+
+                var runner = (DomainRunner) domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
+                runner.RunTest();
+
+                // Verify node start.
+                var expectedNodeCount = Math.Min(i + 3, 7);
+                Assert.AreEqual(expectedNodeCount, ignite.GetCluster().GetNodes().Count);
+
+                // Current AppDomain does not see other instances.
+                Assert.AreEqual(2, Ignition.GetAll().Count);
+
+                if (i > 3)
+                {
+                    var oldDomain = _domains[i - 3];
+                    _domains[i - 3] = null;
+
+                    AppDomain.Unload(oldDomain);
+
+                    // Verify node exit.
+                    TestUtils.WaitForCondition(
+                        () => ignite.GetCluster().GetNodes().Count == expectedNodeCount - 1, 5000);
+                }
+            }
+
+            UnloadDomains();
+
+            // Verify node exit: only two nodes from current domain should be there.
+            TestUtils.WaitForCondition(() => ignite.GetCluster().GetNodes().Count == 2, 5000);
+        }
+
+        /// <summary>
+        /// Creates the domain.
+        /// </summary>
+        private AppDomain CreateDomain(int i)
+        {
+            var domain = AppDomain.CreateDomain("TestIisBehavior-" + i, null, new AppDomainSetup
+            {
+                ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
+                ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
+                ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
+                LoaderOptimization = LoaderOptimization.MultiDomainHost
+            });
+
+            _domains.Add(domain);
+
+            return domain;
+        }
+
+        /// <summary>
+        /// Unloads the domains.
+        /// </summary>
+        private void UnloadDomains()
+        {
+            foreach (var appDomain in _domains)
+            {
+                if (appDomain != null)
+                {
+                    AppDomain.Unload(appDomain);
+                }
+            }
+
+            _domains.Clear();
+        }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        private static IgniteConfiguration GetConfig()
+        {
+            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                AutoGenerateIgniteInstanceName = true
+            };
+        }
+
+        /// <summary>
+        /// Class to instantiate in another domain.
+        /// </summary>
+        private class DomainRunner : MarshalByRefObject
+        {
+            /// <summary>
+            /// Runs the test.
+            /// </summary>
+            public void RunTest()
+            {
+                var cfg = GetConfig();
+
+                // No need to stop: this will happen on domain unload.
+                var ignite = Ignition.Start(cfg);
+                
+                var cache = ignite.GetCache<int, int>(CacheName);
+                Assert.AreEqual(1, cache[1]);
+            }
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs
new file mode 100644 (file)
index 0000000..e201c96
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Process
+{
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Linq;
+
+    /// <summary>
+    /// Reads process output into a list.
+    /// </summary>
+    public class ListDataReader : IIgniteProcessOutputReader
+    {
+        /** Target list. */
+        private readonly List<string> _list = new List<string>();
+
+        /** <inheritdoc /> */
+        public void OnOutput(Process proc, string data, bool err)
+        {
+            lock (_list)
+            {
+                _list.Add(data);
+            }
+        }
+
+        /// <summary>
+        /// Gets the output.
+        /// </summary>
+        public IList<string> GetOutput()
+        {
+            lock (_list)
+            {
+                return _list.ToList();
+            }
+        }
+    }
+}
index 28e7ae8..03e8bf7 100644 (file)
@@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Tests
     using System.Linq;
     using System.Threading;
     using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Configuration;
     using Apache.Ignite.Core.Discovery.Tcp;
     using Apache.Ignite.Core.Discovery.Tcp.Static;
     using Apache.Ignite.Core.Impl;
@@ -63,8 +64,8 @@ namespace Apache.Ignite.Core.Tests
             : new List<string>
             {
                 "-XX:+HeapDumpOnOutOfMemoryError",
-                "-Xms512m",
-                "-Xmx512m",
+                "-Xms64m",
+                "-Xmx99m",
                 "-ea",
                 "-DIGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE=1000",
                 "-DIGNITE_QUIET=true"
@@ -345,7 +346,18 @@ namespace Apache.Ignite.Core.Tests
                 Localhost = "127.0.0.1",
                 JvmOptions = TestJavaOptions(jvmDebug),
                 JvmClasspath = CreateTestClasspath(),
-                IgniteInstanceName = name
+                IgniteInstanceName = name,
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DefaultDataRegionConfiguration = new DataRegionConfiguration
+                    {
+                        Name = DataStorageConfiguration.DefaultDataRegionName,
+                        InitialSize = 128 * 1024 * 1024,
+                        MaxSize = Environment.Is64BitProcess
+                            ? DataRegionConfiguration.DefaultMaxSize
+                            : 256 * 1024 * 1024
+                    }
+                }
             };
         }
 
index 852c071..165a57e 100644 (file)
@@ -69,7 +69,7 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <DocumentationFile>bin\Debug\Apache.Ignite.Core.XML</DocumentationFile>
     <PlatformTarget>AnyCPU</PlatformTarget>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>Apache.Ignite.Core.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
@@ -82,6 +82,7 @@
     <CodeAnalysisRuleSet>Apache.Ignite.Core.ruleset</CodeAnalysisRuleSet>
     <DebugType>none</DebugType>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Compile Include="Impl\IPlatformTargetInternal.cs" />
     <Compile Include="Impl\DataRegionMetrics.cs" />
     <Compile Include="Impl\PersistentStore\PersistentStoreMetrics.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\AppDomains.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\CallbackDelegates.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Callbacks.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\ConsoleWriter.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\EnvDelegates.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Env.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\EnvInterface.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JvmInterface.cs" />
     <Compile Include="Impl\PlatformDisposableTargetAdapter.cs" />
     <Compile Include="Impl\PlatformJniTarget.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\GlobalRef.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\MethodId.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\NativeMethod.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JniResult.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Jvm.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JvmDelegates.cs" />
     <Compile Include="PersistentStore\CheckpointWriteOrder.cs" />
     <Compile Include="PersistentStore\IPersistentStoreMetrics.cs" />
     <Compile Include="PersistentStore\Package-Info.cs" />
     <Compile Include="Impl\Transactions\TransactionImpl.cs" />
     <Compile Include="Impl\Transactions\TransactionMetricsImpl.cs" />
     <Compile Include="Impl\Transactions\TransactionsImpl.cs" />
-    <Compile Include="Impl\Unmanaged\IgniteJniNativeMethods.cs" />
-    <Compile Include="Impl\Unmanaged\IUnmanagedTarget.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedCallbackHandlers.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedCallbackOp.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedCallbacks.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedContext.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedNonReleaseableTarget.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedTarget.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedUtils.cs" />
     <Compile Include="Interop\IPlatformTarget.cs" />
     <Compile Include="Interop\JavaObject.cs" />
     <Compile Include="Transactions\TransactionState.cs" />
     <Compile Include="Transactions\TransactionTimeoutException.cs" />
   </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
-    <EmbeddedResource Include="$(SolutionDir)\x64\Debug\ignite.jni.dll">
-      <Link>resources\debug\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
-    <EmbeddedResource Include="$(SolutionDir)\x64\Release\ignite.jni.dll">
-      <Link>resources\release\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
-    <EmbeddedResource Include="$(SolutionDir)\Win32\Debug\ignite.jni.dll">
-      <Link>resources\debug\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
-    <EmbeddedResource Include="$(SolutionDir)\Win32\Release\ignite.jni.dll">
-      <Link>resources\release\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Platform)' == 'AnyCPU'">
-    <EmbeddedResource Include="$(ProjectDir)..\..\cpp\jni\project\vs\x64\$(Configuration)\ignite.jni.dll">
-      <Link>resources\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-    <EmbeddedResource Include="$(ProjectDir)..\..\cpp\jni\project\vs\Win32\$(Configuration)\ignite.jni.dll" Condition="'$(Configuration)' == 'Release' Or Exists('$(ProjectDir)..\..\cpp\jni\project\vs\Win32\$(Configuration)\ignite.jni.dll')">
-      <Link>resources\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
   <ItemGroup>
     <None Include="Apache.Ignite.Core.ruleset" />
     <None Include="Apache.Ignite.Core.nuspec" />
     <None Include="Apache.Ignite.Core.Schema.nuspec" />
-    <None Include="build-common.ps1" />
     <None Include="NuGet\Uninstall.ps1" />
     <None Include="NuGet\PostBuild.ps1" />
     <None Include="NuGet\Install.ps1" />
     </None>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <PropertyGroup Condition="'$(Platform)' == 'AnyCPU'">
-    <PreBuildEvent>cd "$(ProjectDir)"
-       set COMPLUS_ApplicationMigrationRuntimeActivationConfigPath=$(ProjectDir)
-       PowerShell.exe -executionpolicy remotesigned -File build-common.ps1 -Configuration $(ConfigurationName) -msbuildexe "$(MSBuildBinPath)\msbuild.exe"</PreBuildEvent>
-  </PropertyGroup>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">
index 4e5eae5..bc14fdd 100644 (file)
@@ -40,6 +40,7 @@ namespace Apache.Ignite.Core
     using Apache.Ignite.Core.Impl.Log;
     using Apache.Ignite.Core.Impl.Memory;
     using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Lifecycle;
     using Apache.Ignite.Core.Log;
     using Apache.Ignite.Core.Resource;
@@ -209,7 +210,7 @@ namespace Apache.Ignite.Core
         /// Starts Ignite with given configuration.
         /// </summary>
         /// <returns>Started Ignite.</returns>
-        public static unsafe IIgnite Start(IgniteConfiguration cfg)
+        public static IIgnite Start(IgniteConfiguration cfg)
         {
             IgniteArgumentCheck.NotNull(cfg, "cfg");
 
@@ -228,9 +229,8 @@ namespace Apache.Ignite.Core
                 // 2. Create context.
                 IgniteUtils.LoadDlls(cfg.JvmDllPath, log);
 
-                var cbs = new UnmanagedCallbacks(log);
-
-                IgniteManager.CreateJvmContext(cfg, cbs, log);
+                var cbs = IgniteManager.CreateJvmContext(cfg, log);
+                var env = cbs.Jvm.AttachCurrentThread();
                 log.Debug("JVM started.");
 
                 var gridName = cfg.IgniteInstanceName;
@@ -248,8 +248,7 @@ namespace Apache.Ignite.Core
                 try
                 {
                     // 4. Initiate Ignite start.
-                    UU.IgnitionStart(cbs.Context, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null);
-
+                    UU.IgnitionStart(env, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null, cbs.IgniteId);
 
                     // 5. At this point start routine is finished. We expect STARTUP object to have all necessary data.
                     var node = _startup.Ignite;
@@ -268,7 +267,7 @@ namespace Apache.Ignite.Core
 
                     return node;
                 }
-                catch (Exception)
+                catch (Exception ex)
                 {
                     // 1. Perform keys cleanup.
                     string name = _startup.Name;
@@ -283,7 +282,7 @@ namespace Apache.Ignite.Core
 
                     // 2. Stop Ignite node if it was started.
                     if (interopProc != null)
-                        UU.IgnitionStop(interopProc.Target.Context, gridName, true);
+                        UU.IgnitionStop(gridName, true);
 
                     // 3. Throw error further (use startup error if exists because it is more precise).
                     if (_startup.Error != null)
@@ -293,7 +292,14 @@ namespace Apache.Ignite.Core
                             _startup.Error);
                     }
 
-                    throw;
+                    var jex = ex as JavaException;
+
+                    if (jex == null)
+                    {
+                        throw;
+                    }
+
+                    throw ExceptionUtils.GetException(null, jex);
                 }
                 finally
                 {
@@ -456,7 +462,7 @@ namespace Apache.Ignite.Core
         /// <param name="stream">Stream.</param>
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
             Justification = "PlatformJniTarget is passed further")]
-        internal static void OnStart(IUnmanagedTarget interopProc, IBinaryStream stream)
+        internal static void OnStart(GlobalRef interopProc, IBinaryStream stream)
         {
             try
             {
index b81d04b..0dab997 100644 (file)
@@ -126,10 +126,26 @@ namespace Apache.Ignite.Core.Impl
             BinaryReader reader = null, Exception innerException = null)
         {
             // Set JavaException as immediate inner.
-            innerException = new JavaException(clsName, msg, stackTrace, innerException);
+            var jex = new JavaException(clsName, msg, stackTrace, innerException);
 
+            return GetException(igniteInt, jex, reader);
+        }
+
+        /// <summary>
+        /// Creates exception according to native code class and message.
+        /// </summary>
+        /// <param name="igniteInt">The ignite.</param>
+        /// <param name="innerException">Java exception.</param>
+        /// <param name="reader">Error data reader.</param>
+        /// <returns>Exception.</returns>
+        public static Exception GetException(IIgniteInternal igniteInt, JavaException innerException,
+            BinaryReader reader = null)
+        {
             var ignite = igniteInt == null ? null : igniteInt.GetIgnite();
 
+            var msg = innerException.JavaMessage;
+            var clsName = innerException.JavaClassName;
+
             ExceptionFactory ctor;
 
             if (Exs.TryGetValue(clsName, out ctor))
@@ -157,7 +173,7 @@ namespace Apache.Ignite.Core.Impl
                     "variable?): " + msg, innerException);
 
             if (ClsCachePartialUpdateErr.Equals(clsName, StringComparison.OrdinalIgnoreCase))
-                return ProcessCachePartialUpdateException(igniteInt, msg, stackTrace, reader);
+                return ProcessCachePartialUpdateException(igniteInt, msg, innerException.Message, reader);
 
             // Predefined mapping not found - check plugins.
             if (igniteInt != null && igniteInt.PluginProcessor != null)
index 78b7c74..ae751a4 100644 (file)
@@ -378,7 +378,7 @@ namespace Apache.Ignite.Core.Impl
         /// Internal stop routine.
         /// </summary>
         /// <param name="cancel">Cancel flag.</param>
-        internal unsafe void Stop(bool cancel)
+        internal void Stop(bool cancel)
         {
             var jniTarget = _proc as PlatformJniTarget;
 
@@ -387,7 +387,7 @@ namespace Apache.Ignite.Core.Impl
                 throw new IgniteException("Ignition.Stop is not supported in thin client.");
             }
 
-            UU.IgnitionStop(jniTarget.Target.Context, Name, cancel);
+            UU.IgnitionStop(Name, cancel);
 
             _cbs.Cleanup();
         }
index ee54218..fd067b9 100644 (file)
@@ -22,18 +22,17 @@ namespace Apache.Ignite.Core.Impl
     using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.Linq;
-    using System.Runtime.InteropServices;
     using System.Text;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Memory;
     using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Log;
-    using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
 
     /// <summary>
     /// Native interface manager.
     /// </summary>
-    public static unsafe class IgniteManager
+    internal static class IgniteManager
     {
         /** Java Command line argument: Xms. Case sensitive. */
         private const string CmdJvmMinMemJava = "-Xms";
@@ -44,9 +43,6 @@ namespace Apache.Ignite.Core.Impl
         /** Monitor for DLL load synchronization. */
         private static readonly object SyncRoot = new object();
 
-        /** First created context. */
-        private static void* _ctx;
-
         /** Configuration used on JVM start. */
         private static JvmConfiguration _jvmCfg;
 
@@ -57,10 +53,9 @@ namespace Apache.Ignite.Core.Impl
         /// Create JVM.
         /// </summary>
         /// <param name="cfg">Configuration.</param>
-        /// <param name="cbs">Callbacks.</param>
-        /// <param name="log"></param>
-        /// <returns>Context.</returns>
-        internal static void CreateJvmContext(IgniteConfiguration cfg, UnmanagedCallbacks cbs, ILogger log)
+        /// <param name="log">Logger</param>
+        /// <returns>Callback context.</returns>
+        internal static UnmanagedCallbacks CreateJvmContext(IgniteConfiguration cfg, ILogger log)
         {
             lock (SyncRoot)
             {
@@ -79,16 +74,19 @@ namespace Apache.Ignite.Core.Impl
                 }
 
                 // 2. Create unmanaged pointer.
-                void* ctx = CreateJvm(cfg, cbs);
+                var jvm = CreateJvm(cfg);
+                jvm.EnableJavaConsoleWriter();
 
-                cbs.SetContext(ctx);
+                var cbs = new UnmanagedCallbacks(log, jvm);
+                jvm.RegisterCallbacks(cbs);
 
-                // 3. If this is the first JVM created, preserve it.
-                if (_ctx == null)
+                // 3. If this is the first JVM created, preserve configuration.
+                if (_jvmCfg == null)
                 {
-                    _ctx = ctx;
                     _jvmCfg = jvmCfg;
                 }
+
+                return cbs;
             }
         }
         
@@ -101,63 +99,18 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
-        /// Blocks until JVM stops.
-        /// </summary>
-        public static void DestroyJvm()
-        {
-            lock (SyncRoot)
-            {
-                if (_ctx != null)
-                {
-                    UU.DestroyJvm(_ctx);
-
-                    _ctx = null;
-                }
-            }
-        }
-
-        /// <summary>
         /// Create JVM.
         /// </summary>
         /// <returns>JVM.</returns>
-        private static void* CreateJvm(IgniteConfiguration cfg, UnmanagedCallbacks cbs)
+        private static Jvm CreateJvm(IgniteConfiguration cfg)
         {
             var cp = Classpath.CreateClasspath(cfg);
 
             var jvmOpts = GetMergedJvmOptions(cfg);
-            
-            var opts = new sbyte*[1 + jvmOpts.Count];
 
-            int idx = 0;
-                
-            opts[idx++] = IgniteUtils.StringToUtf8Unmanaged(cp);
+            jvmOpts.Add(cp);
 
-            foreach (string cfgOpt in jvmOpts)
-                opts[idx++] = IgniteUtils.StringToUtf8Unmanaged(cfgOpt);
-
-            try
-            {
-                IntPtr mem = Marshal.AllocHGlobal(opts.Length * 8);
-
-                fixed (sbyte** opts0 = opts)
-                {
-                    PlatformMemoryUtils.CopyMemory(opts0, mem.ToPointer(), opts.Length * 8);
-                }
-
-                try
-                {
-                    return UU.CreateContext(mem.ToPointer(), opts.Length, cbs.CallbacksPointer);
-                }
-                finally
-                {
-                    Marshal.FreeHGlobal(mem);
-                }
-            }
-            finally
-            {
-                foreach (sbyte* opt in opts)
-                    Marshal.FreeHGlobal((IntPtr)opt);
-            }
+            return Jvm.GetOrCreate(jvmOpts);
         }
 
         /// <summary>
index e439208..38eda1b 100644 (file)
@@ -33,7 +33,6 @@ namespace Apache.Ignite.Core.Impl
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Cluster;
     using Apache.Ignite.Core.Impl.Common;
-    using Apache.Ignite.Core.Impl.Unmanaged;
     using Apache.Ignite.Core.Log;
     using Microsoft.Win32;
     using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
@@ -69,9 +68,6 @@ namespace Apache.Ignite.Core.Impl
         /** File: jvm.dll. */
         internal const string FileJvmDll = "jvm.dll";
 
-        /** File: Ignite.Jni.dll. */
-        internal const string FileIgniteJniDll = "ignite.jni.dll";
-        
         /** Prefix for temp directory names. */
         private const string DirIgniteTmp = "Ignite_";
         
@@ -136,9 +132,6 @@ namespace Apache.Ignite.Core.Impl
             // 1. Load JNI dll.
             LoadJvmDll(configJvmDllPath, log);
 
-            // 2. Load GG JNI dll.
-            UnmanagedUtils.Initialize();
-
             _loaded = true;
         }
 
@@ -238,7 +231,7 @@ namespace Apache.Ignite.Core.Impl
         /// Formats the Win32 error.
         /// </summary>
         [ExcludeFromCodeCoverage]
-        public static string FormatWin32Error(int errorCode)
+        private static string FormatWin32Error(int errorCode)
         {
             if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT)
             {
@@ -252,9 +245,7 @@ namespace Apache.Ignite.Core.Impl
             if (errorCode == NativeMethods.ERROR_MOD_NOT_FOUND)
             {
                 return "DLL could not be loaded (126: ERROR_MOD_NOT_FOUND). " +
-                       "This can be caused by missing dependencies. " +
-                       "Make sure that Microsoft Visual C++ 2010 Redistributable Package is installed " +
-                       "(https://www.microsoft.com/en-us/download/details.aspx?id=14632).";
+                       "This can be caused by missing dependencies. ";
             }
 
             return string.Format("{0}: {1}", errorCode, new Win32Exception(errorCode).Message);
@@ -340,75 +331,6 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
-        /// Unpacks an embedded resource into a temporary folder and returns the full path of resulting file.
-        /// </summary>
-        /// <param name="resourceName">Resource name.</param>
-        /// <param name="fileName">Name of the resulting file.</param>
-        /// <returns>
-        /// Path to a temp file with an unpacked resource.
-        /// </returns>
-        public static string UnpackEmbeddedResource(string resourceName, string fileName)
-        {
-            var dllRes = Assembly.GetExecutingAssembly().GetManifestResourceNames()
-                .Single(x => x.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase));
-
-            return WriteResourceToTempFile(dllRes, fileName);
-        }
-
-        /// <summary>
-        /// Writes the resource to temporary file.
-        /// </summary>
-        /// <param name="resource">The resource.</param>
-        /// <param name="name">File name prefix</param>
-        /// <returns>Path to the resulting temp file.</returns>
-        private static string WriteResourceToTempFile(string resource, string name)
-        {
-            // Dll file name should not be changed, so we create a temp folder with random name instead.
-            var file = Path.Combine(GetTempDirectoryName(), name);
-
-            using (var src = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
-            using (var dest = File.OpenWrite(file))
-            {
-                // ReSharper disable once PossibleNullReferenceException
-                src.CopyTo(dest);
-
-                return file;
-            }
-        }
-
-        /// <summary>
-        /// Tries to clean temporary directories created with <see cref="GetTempDirectoryName"/>.
-        /// </summary>
-        internal static void TryCleanTempDirectories()
-        {
-            var dt = DateTime.Now;
-
-            foreach (var dir in Directory.EnumerateDirectories(Path.GetTempPath(), DirIgniteTmp + "*"))
-            {
-                if ((dt - Directory.GetCreationTime(dir)).TotalMinutes < 1)
-                {
-                    // Do not clean up recently created temp directories:
-                    // they may be used by currently starting up nodes.
-                    // This is a workaround for multiple node startup problem, see IGNITE-5730.
-                    continue;
-                }
-
-                try
-                {
-                    Directory.Delete(dir, true);
-                }
-                catch (IOException)
-                {
-                    // Expected
-                }
-                catch (UnauthorizedAccessException)
-                {
-                    // Expected
-                }
-            }
-        }
-
-        /// <summary>
         /// Creates a uniquely named, empty temporary directory on disk and returns the full path of that directory.
         /// </summary>
         /// <returns>The full path of the temporary directory.</returns>
index c7d9ab4..c0fcea4 100644 (file)
@@ -25,11 +25,12 @@ namespace Apache.Ignite.Core.Impl
     using System.Threading;
     using System.Threading.Tasks;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Memory;
-    using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Interop;
     using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
     using BinaryWriter = Apache.Ignite.Core.Impl.Binary.BinaryWriter;
@@ -55,7 +56,7 @@ namespace Apache.Ignite.Core.Impl
             };
         
         /** Unmanaged target. */
-        private readonly IUnmanagedTarget _target;
+        private readonly GlobalRef _target;
 
         /** Marshaller. */
         private readonly Marshaller _marsh;
@@ -65,7 +66,7 @@ namespace Apache.Ignite.Core.Impl
         /// </summary>
         /// <param name="target">Target.</param>
         /// <param name="marsh">Marshaller.</param>
-        public PlatformJniTarget(IUnmanagedTarget target, Marshaller marsh)
+        public PlatformJniTarget(GlobalRef target, Marshaller marsh)
         {
             Debug.Assert(target != null);
             Debug.Assert(marsh != null);
@@ -77,7 +78,7 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the target.
         /// </summary>
-        public IUnmanagedTarget Target
+        public GlobalRef Target
         {
             get { return _target; }
         }
@@ -88,43 +89,71 @@ namespace Apache.Ignite.Core.Impl
         /** <inheritdoc /> */
         public long InStreamOutLong(int type, Action<IBinaryStream> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(stream);
 
-                return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                    return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         public IPlatformTargetInternal InStreamOutObject(int type, Action<IBinaryStream> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(stream);
 
-                var target = UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput());
+                    var target = UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput());
 
-                return target == null ? null : new PlatformJniTarget(target, _marsh);
+                    return target == null ? null : new PlatformJniTarget(target, _marsh);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         public IPlatformTargetInternal OutObjectInternal(int type)
         {
-            return GetPlatformTarget(UU.TargetOutObject(_target, type));
+            try
+            {
+                return GetPlatformTarget(UU.TargetOutObject(_target, type));
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
         }
 
         /** <inheritdoc /> */
         public T OutStream<T>(int type, Func<IBinaryStream, T> readAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                UU.TargetOutStream(_target, type, stream.MemoryPointer);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    UU.TargetOutStream(_target, type, stream.MemoryPointer);
 
-                stream.SynchronizeInput();
+                    stream.SynchronizeInput();
 
-                return readAction(stream);
+                    return readAction(stream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -132,16 +161,23 @@ namespace Apache.Ignite.Core.Impl
         public TR InStreamOutStream<TR>(int type, Action<IBinaryStream> writeAction, 
             Func<IBinaryStream, TR> readAction)
         {
-            using (var outStream = IgniteManager.Memory.Allocate().GetStream())
-            using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(outStream);
+                using (var outStream = IgniteManager.Memory.Allocate().GetStream())
+                using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(outStream);
 
-                UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+                    UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
 
-                inStream.SynchronizeInput();
+                    inStream.SynchronizeInput();
 
-                return readAction(inStream);
+                    return readAction(inStream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -149,33 +185,40 @@ namespace Apache.Ignite.Core.Impl
         public TR InStreamOutLong<TR>(int type, Action<IBinaryStream> outAction, Func<IBinaryStream, long, TR> inAction, 
             Func<IBinaryStream, Exception> readErrorAction)
         {
-            Debug.Assert(readErrorAction != null);
-
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                outAction(stream);
+                Debug.Assert(readErrorAction != null);
 
-                var res = UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    outAction(stream);
 
-                if (res != PlatformTargetAdapter.Error && inAction == null)
-                    return default(TR);  // quick path for void operations
+                    var res = UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
 
-                stream.SynchronizeInput();
+                    if (res != PlatformTargetAdapter.Error && inAction == null)
+                        return default(TR);  // quick path for void operations
 
-                stream.Seek(0, SeekOrigin.Begin);
+                    stream.SynchronizeInput();
 
-                if (res != PlatformTargetAdapter.Error)
-                {
-                    return inAction != null ? inAction(stream, res) : default(TR);
-                }
+                    stream.Seek(0, SeekOrigin.Begin);
 
-                throw readErrorAction(stream);
+                    if (res != PlatformTargetAdapter.Error)
+                    {
+                        return inAction != null ? inAction(stream, res) : default(TR);
+                    }
+
+                    throw readErrorAction(stream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
-        public unsafe TR InObjectStreamOutObjectStream<TR>(int type, Action<IBinaryStream> writeAction, 
+        public TR InObjectStreamOutObjectStream<TR>(int type, Action<IBinaryStream> writeAction, 
             Func<IBinaryStream, IPlatformTargetInternal, TR> readAction, IPlatformTargetInternal arg)
         {
             PlatformMemoryStream outStream = null;
@@ -199,8 +242,8 @@ namespace Apache.Ignite.Core.Impl
                     inPtr = inStream.MemoryPointer;
                 }
 
-                var res = UU.TargetInObjectStreamOutObjectStream(_target, type, 
-                    ((PlatformJniTarget)arg).Target.Target, outPtr, inPtr);
+                var res = UU.TargetInObjectStreamOutObjectStream(_target, type,
+                    ((PlatformJniTarget) arg).Target, outPtr, inPtr);
 
                 if (readAction == null)
                     return default(TR);
@@ -212,6 +255,10 @@ namespace Apache.Ignite.Core.Impl
                 return readAction(inStream, target);
 
             }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
             finally
             {
                 try
@@ -246,7 +293,7 @@ namespace Apache.Ignite.Core.Impl
         /// <param name="convertFunc">The function to read future result from stream.</param>
         /// <returns>Created future.</returns>
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
-        private Future<T> GetFuture<T>(Func<long, int, IUnmanagedTarget> listenAction, bool keepBinary = false,
+        private Future<T> GetFuture<T>(Func<long, int, GlobalRef> listenAction, bool keepBinary = false,
             Func<BinaryReader, T> convertFunc = null)
         {
             var futType = FutureType.Object;
@@ -262,7 +309,7 @@ namespace Apache.Ignite.Core.Impl
 
             var futHnd = _marsh.Ignite.HandleRegistry.Allocate(fut);
 
-            IUnmanagedTarget futTarget;
+            GlobalRef futTarget;
 
             try
             {
@@ -323,22 +370,36 @@ namespace Apache.Ignite.Core.Impl
         /** <inheritdoc /> */
         public long InLongOutLong(int type, long val)
         {
-            return UU.TargetInLongOutLong(_target, type, val);
+            try
+            {
+                return UU.TargetInLongOutLong(_target, type, val);
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
         }
 
         /** <inheritdoc /> */
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public long InStreamOutLong(int type, Action<IBinaryRawWriter> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(stream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                    return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -347,20 +408,27 @@ namespace Apache.Ignite.Core.Impl
         public T InStreamOutStream<T>(int type, Action<IBinaryRawWriter> writeAction, 
             Func<IBinaryRawReader, T> readAction)
         {
-            using (var outStream = IgniteManager.Memory.Allocate().GetStream())
-            using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(outStream);
+                using (var outStream = IgniteManager.Memory.Allocate().GetStream())
+                using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(outStream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+                    UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
 
-                inStream.SynchronizeInput();
+                    inStream.SynchronizeInput();
 
-                return readAction(_marsh.StartUnmarshal(inStream));
+                    return readAction(_marsh.StartUnmarshal(inStream));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -368,20 +436,27 @@ namespace Apache.Ignite.Core.Impl
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public IPlatformTarget InStreamOutObject(int type, Action<IBinaryRawWriter> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(stream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                return GetPlatformTarget(UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput()));
+                    return GetPlatformTarget(UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput()));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
-        public unsafe T InObjectStreamOutObjectStream<T>(int type, IPlatformTarget arg, 
+        public T InObjectStreamOutObjectStream<T>(int type, IPlatformTarget arg, 
             Action<IBinaryRawWriter> writeAction, Func<IBinaryRawReader, IPlatformTarget, T> readAction)
         {
             PlatformMemoryStream outStream = null;
@@ -417,6 +492,10 @@ namespace Apache.Ignite.Core.Impl
                 return readAction(_marsh.StartUnmarshal(inStream), GetPlatformTarget(res));
 
             }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
             finally
             {
                 try
@@ -437,13 +516,20 @@ namespace Apache.Ignite.Core.Impl
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public T OutStream<T>(int type, Func<IBinaryRawReader, T> readAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                UU.TargetOutStream(_target, type, stream.MemoryPointer);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    UU.TargetOutStream(_target, type, stream.MemoryPointer);
 
-                stream.SynchronizeInput();
+                    stream.SynchronizeInput();
 
-                return readAction(_marsh.StartUnmarshal(stream));
+                    return readAction(_marsh.StartUnmarshal(stream));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -476,7 +562,14 @@ namespace Apache.Ignite.Core.Impl
                         FinishMarshal(writer);
                     }
 
-                    UU.TargetInStreamAsync(_target, type, stream.SynchronizeOutput());
+                    try
+                    {
+                        UU.TargetInStreamAsync(_target, type, stream.SynchronizeOutput());
+                    }
+                    catch (JavaException jex)
+                    {
+                        throw ConvertException(jex);
+                    }
                 }
             }, false, convertFunc).Task;
         }
@@ -505,7 +598,14 @@ namespace Apache.Ignite.Core.Impl
                         FinishMarshal(writer);
                     }
 
-                    return UU.TargetInStreamOutObjectAsync(_target, type, stream.SynchronizeOutput());
+                    try
+                    {
+                        return UU.TargetInStreamOutObjectAsync(_target, type, stream.SynchronizeOutput());
+                    }
+                    catch (JavaException jex)
+                    {
+                        throw ConvertException(jex);
+                    }
                 }
             }, false, convertFunc).GetTask(cancellationToken);
         }
@@ -513,7 +613,7 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the platform target.
         /// </summary>
-        private IPlatformTargetInternal GetPlatformTarget(IUnmanagedTarget target)
+        private IPlatformTargetInternal GetPlatformTarget(GlobalRef target)
         {
             return target == null ? null : new PlatformJniTarget(target, _marsh);
         }
@@ -521,9 +621,17 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the target pointer.
         /// </summary>
-        private static unsafe void* GetTargetPtr(IPlatformTarget target)
+        private static GlobalRef GetTargetPtr(IPlatformTarget target)
+        {
+            return target == null ? null : ((PlatformJniTarget) target)._target;
+        }
+
+        /// <summary>
+        /// Converts the exception.
+        /// </summary>
+        private Exception ConvertException(JavaException jex)
         {
-            return target == null ? null : ((PlatformJniTarget) target)._target.Target;
+            return ExceptionUtils.GetException(_marsh.Ignite, jex);
         }
 
         #endregion
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs
deleted file mode 100644 (file)
index f96157c..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System.Runtime.InteropServices;
-    using System.Security;
-
-    /// <summary>
-    /// Ignite JNI native methods.
-    /// </summary>
-    [SuppressUnmanagedCodeSecurity]
-    internal static unsafe class IgniteJniNativeMethods
-    {
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteReallocate")]
-        public static extern int Reallocate(long memPtr, int cap);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteIgnitionStart")]
-        public static extern void IgnitionStart(void* ctx, sbyte* cfgPath, sbyte* gridName, int factoryId, 
-            long dataPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteIgnitionStop")]
-        [return: MarshalAs(UnmanagedType.U1)]
-        public static extern bool IgnitionStop(void* ctx, sbyte* gridName, [MarshalAs(UnmanagedType.U1)] bool cancel);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInLongOutLong")]
-        public static extern long TargetInLongOutLong(void* ctx, void* target, int opType, long val);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutLong")]
-        public static extern long TargetInStreamOutLong(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutStream")]
-        public static extern void TargetInStreamOutStream(void* ctx, void* target, int opType, long inMemPtr,
-            long outMemPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutObject")]
-        public static extern void* TargetInStreamOutObject(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInObjectStreamOutObjectStream")]
-        public static extern void* TargetInObjectStreamOutObjectStream(void* ctx, void* target, int opType,
-            void* arg, long inMemPtr, long outMemPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetOutStream")]
-        public static extern void TargetOutStream(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetOutObject")]
-        public static extern void* TargetOutObject(void* ctx, void* target, int opType);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamAsync")]
-        public static extern void TargetInStreamAsync(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutObjectAsync")]
-        public static extern void* TargetInStreamOutObjectAsync(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteAcquire")]
-        public static extern void* Acquire(void* ctx, void* target);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteRelease")]
-        public static extern void Release(void* target);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteThrowToJava")]
-        public static extern void ThrowToJava(void* ctx, char* msg);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteHandlersSize")]
-        public static extern int HandlersSize();
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteCreateContext")]
-        public static extern void* CreateContext(void* opts, int optsLen, void* cbs);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteDeleteContext")]
-        public static extern void DeleteContext(void* ptr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteDestroyJvm")]
-        public static extern void DestroyJvm(void* ctx);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteSetConsoleHandler")]
-        public static extern void SetConsoleHandler(void* consoleHandler);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteRemoveConsoleHandler")]
-        public static extern int RemoveConsoleHandler(void* consoleHandler);
-    }
-}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
new file mode 100644 (file)
index 0000000..4b87df5
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics;
+    using System.Runtime.InteropServices;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// AppDomain accessor.
+    /// <para />
+    /// Logic is borrowed from internal .NET Framework classes.
+    /// See System.Deployment.Application.NativeMethods.
+    /// </summary>
+    internal static class AppDomains
+    {
+        // ReSharper disable InconsistentNaming
+        // ReSharper disable UnusedMember.Global
+        /** */
+        private static Guid CLSID_CLRMetaHost = new Guid(
+            0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);
+
+        /** */
+        private static Guid IID_CLRMetaHost = new Guid(
+            0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
+
+        /** */
+        private static Guid IID_CLRRuntimeInfo = new Guid(
+            0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
+
+        /** */
+        private static Guid CLSID_CorRuntimeHost = new Guid(
+            0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+        /** */
+        private static Guid IID_CorRuntimeHost = new Guid(
+            0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+        /// <summary>
+        /// Gets the default application domain.
+        /// </summary>
+        public static _AppDomain GetDefaultAppDomain()
+        {
+            object objHost;
+            int hr = NativeMethods.CLRCreateInstance(ref CLSID_CLRMetaHost, ref IID_CLRMetaHost, out objHost);
+
+            if (hr < 0)
+            {
+                throw new IgniteException("Failed to get default AppDomain. Cannot create meta host: " + hr);
+            }
+            
+            var host = (ICLRMetaHost) objHost;
+            var vers = Environment.Version;
+            var versString = string.Format("v{0}.{1}.{2}", vers.Major, vers.Minor, vers.Build);
+            var runtime = (ICLRRuntimeInfo) host.GetRuntime(versString, ref IID_CLRRuntimeInfo);
+            
+            bool started;
+            uint flags;
+            runtime.IsStarted(out started, out flags);
+            Debug.Assert(started);
+
+            var rtHost = (ICorRuntimeHost) runtime.GetInterface(ref CLSID_CorRuntimeHost, ref IID_CorRuntimeHost);
+
+            _AppDomain domain;
+            rtHost.GetDefaultDomain(out domain);
+
+            return domain;
+        }
+
+        [ComImport, Guid("D332DB9E-B9B3-4125-8207-A14884F53216"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICLRMetaHost
+        {
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetRuntime(string version, ref Guid iid);
+        }
+
+        [ComImport, Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICLRRuntimeInfo
+        {
+            void GetVersionString(char[] buffer, int bufferLength);
+            void GetRuntimeDirectory(char[] buffer, int bufferLength);
+            bool IsLoaded(IntPtr hProcess);
+            void LoadErrorString(uint id, char[] buffer, int bufferLength, int lcid);
+            void LoadLibrary(string path, out IntPtr hMdodule);
+            void GetProcAddress(string name, out IntPtr addr);
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetInterface(ref Guid clsid, ref Guid iid);
+            bool IsLoadable();
+            void SetDefaultStartupFlags(uint flags, string configFile);
+            void GetDefaultStartupFlags(out uint flags, char[] configFile, int configFileLength);
+            void BindAsLegacyV2Runtime();
+            void IsStarted(out bool started, out uint flags);
+        }
+
+        [ComImport, Guid("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICorRuntimeHost
+        {
+            void CreateLogicalThreadState();
+            void DeleteLogicalThreadState();
+            void SwitchinLogicalThreadState(IntPtr cookie);
+            void SwitchoutLogicalThreadState(out IntPtr cookie);
+            void LocksHeldByLogicalThread(out int count);
+            void MapFile(IntPtr hFile, out IntPtr address);
+            void GetConfiguration(out IntPtr config);
+            void Start();
+            void Stop();
+            void CreateDomain(string name, object identity, out _AppDomain domain);
+            void GetDefaultDomain(out _AppDomain domain);
+        }
+
+        private static class NativeMethods
+        {
+            [DllImport("mscoree.dll")]
+            public static extern int CLRCreateInstance(ref Guid clsid, ref Guid iid,
+                [MarshalAs(UnmanagedType.Interface)] out object ptr);
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
new file mode 100644 (file)
index 0000000..4eb1d29
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Runtime.InteropServices;
+    using System.Security;
+
+    /// <summary>
+    /// Java -> .NET callback delegates.
+    /// <para />
+    /// Delegates are registered once per JVM.
+    /// Every callback has igniteId argument to identify related Ignite instance
+    /// (this value is passed as EnvPtr to PlatformIgnition.start).
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal static class CallbackDelegates
+    {
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate void LoggerLog(IntPtr env, IntPtr clazz, long igniteId, int level, IntPtr message,
+            IntPtr category, IntPtr error, long memPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long ignteId, int level);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate void ConsoleWrite(IntPtr env, IntPtr clazz, IntPtr message, bool isError);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId, int op, long arg);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz,
+            long igniteId, int op, long arg1, long arg2, long arg3, IntPtr arg);
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
new file mode 100644 (file)
index 0000000..1e2989f
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Collections.Concurrent;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using System.Runtime.InteropServices;
+    using System.Threading;
+    using Apache.Ignite.Core.Impl.Handle;
+    using Apache.Ignite.Core.Log;
+
+    /// <summary>
+    /// Java -> .NET callback dispatcher.
+    /// Instance of this class should only exist once per process, in the default AppDomain.
+    /// </summary>
+    internal sealed class Callbacks : MarshalByRefObject
+    {
+        /** Holds delegates so that GC does not collect them. */
+        // ReSharper disable once CollectionNeverQueried.Local
+        private readonly List<Delegate> _delegates = new List<Delegate>();
+
+        /** Holds Ignite instance-specific callbacks. */
+        private readonly HandleRegistry _callbackRegistry = new HandleRegistry(100);
+
+        /** Console writers. */
+        private readonly ConcurrentDictionary<long, ConsoleWriter> _consoleWriters
+            = new ConcurrentDictionary<long, ConsoleWriter>();
+
+        /** Gets the JVM. */
+        private readonly Jvm _jvm;
+
+        /** Console writer id generator. */
+        private long _consoleWriterId;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Callbacks"/> class.
+        /// </summary>
+        public Callbacks(Env env, Jvm jvm)
+        {
+            Debug.Assert(env != null);
+            Debug.Assert(jvm != null);
+
+            _jvm = jvm;
+            RegisterNatives(env);
+        }
+
+        /** <inheritdoc /> */
+        public override object InitializeLifetimeService()
+        {
+            // Ensure that cross-AppDomain reference lives forever.
+            return null;
+        }
+
+        /// <summary>
+        /// Registers callback handlers.
+        /// </summary>
+        public long RegisterHandlers(UnmanagedCallbacks cbs)
+        {
+            Debug.Assert(cbs != null);
+
+            return _callbackRegistry.AllocateCritical(cbs);
+        }
+
+        /// <summary>
+        /// Releases callback handlers.
+        /// </summary>
+        public void ReleaseHandlers(long igniteId)
+        {
+            _callbackRegistry.Release(igniteId);
+        }
+
+        /// <summary>
+        /// Registers the console writer.
+        /// </summary>
+        public long RegisterConsoleWriter(ConsoleWriter writer)
+        {
+            Debug.Assert(writer != null);
+
+            var id = Interlocked.Increment(ref _consoleWriterId);
+
+            var res = _consoleWriters.TryAdd(id, writer);
+            Debug.Assert(res);
+
+            return id;
+        }
+
+        /// <summary>
+        /// Registers the console writer.
+        /// </summary>
+        public void ReleaseConsoleWriter(long id)
+        {
+            ConsoleWriter writer;
+            var res = _consoleWriters.TryRemove(id, out writer);
+            Debug.Assert(res);
+        }
+
+        /// <summary>
+        /// Registers native callbacks.
+        /// </summary>
+        private void RegisterNatives(Env env)
+        {
+            // Native callbacks are per-jvm.
+            // Every callback (except ConsoleWrite) includes envPtr (third arg) to identify Ignite instance.
+
+            using (var callbackUtils = env.FindClass(
+                "org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils"))
+            {
+                // Any signature works, but wrong one will cause segfault eventually.
+                var methods = new[]
+                {
+                    GetNativeMethod("loggerLog", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
+                        (CallbackDelegates.LoggerLog) LoggerLog),
+
+                    GetNativeMethod("loggerIsLevelEnabled", "(JI)Z",
+                        (CallbackDelegates.LoggerIsLevelEnabled) LoggerIsLevelEnabled),
+
+                    GetNativeMethod("consoleWrite", "(Ljava/lang/String;Z)V",
+                        (CallbackDelegates.ConsoleWrite) ConsoleWrite),
+
+                    GetNativeMethod("inLongOutLong", "(JIJ)J", (CallbackDelegates.InLongOutLong) InLongOutLong),
+
+                    GetNativeMethod("inLongLongLongObjectOutLong", "(JIJJJLjava/lang/Object;)J",
+                        (CallbackDelegates.InLongLongLongObjectOutLong) InLongLongLongObjectOutLong)
+                };
+
+                try
+                {
+                    env.RegisterNatives(callbackUtils, methods);
+                }
+                finally
+                {
+                    foreach (var nativeMethod in methods)
+                    {
+                        Marshal.FreeHGlobal(nativeMethod.Name);
+                        Marshal.FreeHGlobal(nativeMethod.Signature);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the native method.
+        /// </summary>
+        private unsafe NativeMethod GetNativeMethod(string name, string sig, Delegate d)
+        {
+            _delegates.Add(d);
+
+            return new NativeMethod
+            {
+                Name = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(name),
+                Signature = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(sig),
+                FuncPtr = Marshal.GetFunctionPointerForDelegate(d)
+            };
+        }
+
+        /// <summary>
+        /// <see cref="ILogger.Log"/> callback.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private void LoggerLog(IntPtr envPtr, IntPtr clazz, long igniteId, int level, IntPtr message, IntPtr category,
+            IntPtr errorInfo, long memPtr)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+                var env = _jvm.AttachCurrentThread();
+
+                var message0 = env.JStringToString(message);
+                var category0 = env.JStringToString(category);
+                var errorInfo0 = env.JStringToString(errorInfo);
+
+                cbs.LoggerLog(level, message0, category0, errorInfo0, memPtr);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+            }
+        }
+
+        /// <summary>
+        /// <see cref="ILogger.IsEnabled"/> callback.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long igniteId, int level)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.LoggerIsLevelEnabled(level);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 3 longs + object -> long.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz, long igniteId,
+            int op, long arg1, long arg2, long arg3, IntPtr arg)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.InLongLongLongObjectOutLong(op, arg1, arg2, arg3, arg);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// long -> long.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId,
+            int op, long arg)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.InLongOutLong(op, arg);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// System.out.println -> Console.Write.
+        /// <para />
+        /// Java uses system output which can not be accessed with native .NET APIs.
+        /// For example, unit test runners won't show Java console output, and so on.
+        /// To fix this we delegate console output from Java to .NET APIs.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private void ConsoleWrite(IntPtr envPtr, IntPtr clazz, IntPtr message, bool isError)
+        {
+            try
+            {
+                if (message != IntPtr.Zero)
+                {
+                    // Each domain registers it's own writer.
+                    var writer = _consoleWriters.Select(x => x.Value).FirstOrDefault();
+
+                    if (writer != null)
+                    {
+                        var env = _jvm.AttachCurrentThread();
+                        var msg = env.JStringToString(message);
+
+                        writer.Write(msg, isError);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+            }
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
new file mode 100644 (file)
index 0000000..ef4be1e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics.CodeAnalysis;
+
+    /// <summary>
+    /// Console writer.
+    /// </summary>
+    internal sealed class ConsoleWriter : MarshalByRefObject
+    {
+        /// <summary>
+        /// Writes the specified message to console.
+        /// </summary>
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+            Justification = "Only instance methods can be called across AppDomain boundaries.")]
+        public void Write(string message, bool isError)
+        {
+            var target = isError ? Console.Error : Console.Out;
+            target.Write(message);
+        }
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
new file mode 100644 (file)
index 0000000..da790d7
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Diagnostics;
+    using System.Runtime.InteropServices;
+    using System.Security;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// JNIEnv.
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal sealed unsafe class Env
+    {
+        /** JNIEnv pointer. */
+        private readonly IntPtr _envPtr;
+
+        /** JVM. */
+        private readonly Jvm _jvm;
+
+        /** */
+        private readonly EnvDelegates.CallStaticVoidMethod _callStaticVoidMethod;
+
+        /** */
+        private readonly EnvDelegates.CallStaticBooleanMethod _callStaticBoolMethod;
+
+        /** */
+        private readonly EnvDelegates.FindClass _findClass;
+
+        /** */
+        private readonly EnvDelegates.GetMethodId _getMethodId;
+
+        /** */
+        private readonly EnvDelegates.GetStaticMethodId _getStaticMethodId;
+
+        /** */
+        private readonly EnvDelegates.NewStringUtf _newStringUtf;
+
+        /** */
+        private readonly EnvDelegates.ExceptionOccurred _exceptionOccurred;
+
+        /** */
+        private readonly EnvDelegates.GetObjectClass _getObjectClass;
+
+        /** */
+        private readonly EnvDelegates.CallObjectMethod _callObjectMethod;
+
+        /** */
+        private readonly EnvDelegates.CallLongMethod _callLongMethod;
+
+        /** */
+        private readonly EnvDelegates.CallVoidMethod _callVoidMethod;
+
+        /** */
+        private readonly EnvDelegates.GetStringChars _getStringChars;
+
+        /** */
+        private readonly EnvDelegates.GetStringUtfChars _getStringUtfChars;
+
+        /** */
+        private readonly EnvDelegates.GetStringUtfLength _getStringUtfLength;
+
+        /** */
+        private readonly EnvDelegates.ReleaseStringUtfChars _releaseStringUtfChars;
+
+        /** */
+        private readonly EnvDelegates.ReleaseStringChars _releaseStringChars;
+
+        /** */
+        private readonly EnvDelegates.ExceptionClear _exceptionClear;
+
+        /** */
+        private readonly EnvDelegates.ExceptionCheck _exceptionCheck;
+
+        /** */
+        private readonly EnvDelegates.CallStaticObjectMethod _callStaticObjectMethod;
+
+        /** */
+        private readonly EnvDelegates.RegisterNatives _registerNatives;
+
+        /** */
+        private readonly EnvDelegates.DeleteLocalRef _deleteLocalRef;
+
+        /** */
+        private readonly EnvDelegates.NewGlobalRef _newGlobalRef;
+
+        /** */
+        private readonly EnvDelegates.DeleteGlobalRef _deleteGlobalRef;
+
+        /** */
+        private readonly EnvDelegates.ThrowNew _throwNew;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Env" /> class.
+        /// </summary>
+        internal Env(IntPtr envPtr, Jvm jvm)
+        {
+            Debug.Assert(envPtr != IntPtr.Zero);
+            Debug.Assert(jvm != null);
+
+            _envPtr = envPtr;
+            _jvm = jvm;
+
+            var funcPtr = (EnvInterface**)envPtr;
+            var func = **funcPtr;
+
+            GetDelegate(func.CallStaticVoidMethod, out _callStaticVoidMethod);
+            GetDelegate(func.CallStaticBooleanMethod, out _callStaticBoolMethod);
+            GetDelegate(func.FindClass, out _findClass);
+            GetDelegate(func.GetMethodID, out _getMethodId);
+            GetDelegate(func.GetStaticMethodID, out _getStaticMethodId);
+            GetDelegate(func.NewStringUTF, out _newStringUtf);
+            GetDelegate(func.ExceptionOccurred, out _exceptionOccurred);
+            GetDelegate(func.ExceptionClear, out _exceptionClear);
+            GetDelegate(func.ExceptionCheck, out _exceptionCheck);
+            GetDelegate(func.GetObjectClass, out _getObjectClass);
+            GetDelegate(func.CallObjectMethod, out _callObjectMethod);
+            GetDelegate(func.CallStaticObjectMethod, out _callStaticObjectMethod);
+            GetDelegate(func.CallLongMethod, out _callLongMethod);
+            GetDelegate(func.CallVoidMethod, out _callVoidMethod);
+
+            GetDelegate(func.GetStringChars, out _getStringChars);
+            GetDelegate(func.ReleaseStringChars, out _releaseStringChars);
+
+            GetDelegate(func.GetStringUTFChars, out _getStringUtfChars);
+            GetDelegate(func.ReleaseStringUTFChars, out _releaseStringUtfChars);
+
+            GetDelegate(func.GetStringUTFLength, out _getStringUtfLength);
+
+            GetDelegate(func.RegisterNatives, out _registerNatives);
+            GetDelegate(func.DeleteLocalRef, out _deleteLocalRef);
+            GetDelegate(func.NewGlobalRef, out _newGlobalRef);
+            GetDelegate(func.DeleteGlobalRef, out _deleteGlobalRef);
+            GetDelegate(func.ThrowNew, out _throwNew);
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
+        /// <summary>
+        /// Calls the static void method.
+        /// </summary>
+        public void CallStaticVoidMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            _callStaticVoidMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+        }
+
+        /// <summary>
+        /// Calls the static bool method.
+        /// </summary>
+        public bool CallStaticBoolMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callStaticBoolMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return res > 0;
+        }
+
+        /// <summary>
+        /// Calls the object method.
+        /// </summary>
+        public GlobalRef CallObjectMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            var lref = _callObjectMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(lref);
+        }
+
+        /// <summary>
+        /// Calls the long method.
+        /// </summary>
+        public long CallLongMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callLongMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return res;
+        }
+
+        /// <summary>
+        /// Calls the void method.
+        /// </summary>
+        public void CallVoidMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            _callVoidMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+        }
+
+        /// <summary>
+        /// Calls the static object method.
+        /// </summary>
+        private GlobalRef CallStaticObjectMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callStaticObjectMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Finds the class.
+        /// </summary>
+        public GlobalRef FindClass(string name)
+        {
+            var res = _findClass(_envPtr, name);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name);
+            }
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Gets the object class.
+        /// </summary>
+        private GlobalRef GetObjectClass(GlobalRef obj)
+        {
+            var res = _getObjectClass(_envPtr, obj.Target);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Gets the static method identifier.
+        /// </summary>
+        public IntPtr GetStaticMethodId(GlobalRef clazz, string name, string signature)
+        {
+            var res = _getStaticMethodId(_envPtr, clazz.Target, name, signature);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name + " " + signature);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the method identifier.
+        /// </summary>
+        public IntPtr GetMethodId(GlobalRef clazz, string name, string signature)
+        {
+            var res = _getMethodId(_envPtr, clazz.Target, name, signature);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name + " " + signature);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Creates new jstring from UTF chars.
+        /// </summary>
+        private GlobalRef NewStringUtf(sbyte* utf)
+        {
+            if (utf == null)
+            {
+                return null;
+            }
+
+            var res = _newStringUtf(_envPtr, new IntPtr(utf));
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Creates new jstring from string.
+        /// </summary>
+        public GlobalRef NewStringUtf(string str)
+        {
+            if (str == null)
+            {
+                return null;
+            }
+
+            var chars = IgniteUtils.StringToUtf8Unmanaged(str);
+
+            try
+            {
+                return NewStringUtf(chars);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(new IntPtr(chars));
+            }
+        }
+
+        /// <summary>
+        /// Gets the utf chars from jstring.
+        /// </summary>
+        private IntPtr GetStringUtfChars(IntPtr jstring)
+        {
+            Debug.Assert(jstring != IntPtr.Zero);
+
+            byte isCopy;
+            return _getStringUtfChars(_envPtr, jstring, &isCopy);
+        }
+
+        /// <summary>
+        /// Releases the string utf chars allocated by <see cref="GetStringUtfChars"/>.
+        /// </summary>
+        private void ReleaseStringUtfChars(IntPtr jstring, IntPtr chars)
+        {
+            _releaseStringUtfChars(_envPtr, jstring, chars);
+        }
+
+        /// <summary>
+        /// Gets the length of the jstring.
+        /// </summary>
+        private int GetStringUtfLength(IntPtr jstring)
+        {
+            Debug.Assert(jstring != IntPtr.Zero);
+
+            return _getStringUtfLength(_envPtr, jstring);
+        }
+
+        /// <summary>
+        /// Registers the native callbacks.
+        /// </summary>
+        public void RegisterNatives(GlobalRef clazz, NativeMethod[] methods)
+        {
+            Debug.Assert(methods != null);
+
+            fixed (NativeMethod* m = &methods[0])
+            {
+                var res = _registerNatives(_envPtr, clazz.Target, m, methods.Length);
+
+                if (res != JniResult.Success)
+                {
+                    throw new IgniteException("Failed to register natives: " + res);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Converts jstring to string.
+        /// </summary>
+        private string JStringToString(GlobalRef jstring)
+        {
+            if (jstring == null)
+            {
+                return null;
+            }
+
+            return JStringToString(jstring.Target);
+        }
+
+        /// <summary>
+        /// Converts jstring to string.
+        /// </summary>
+        public string JStringToString(IntPtr jstring)
+        {
+            if (jstring == IntPtr.Zero)
+            {
+                return null;
+            }
+
+            var chars = GetStringUtfChars(jstring);
+            var len = GetStringUtfLength(jstring);
+
+            try
+            {
+                return IgniteUtils.Utf8UnmanagedToString((sbyte*) chars, len);
+            }
+            finally 
+            {
+                ReleaseStringUtfChars(jstring, chars);
+            }
+        }
+
+        /// <summary>
+        /// Creates a new global reference from a local reference pointer.
+        /// </summary>
+        public GlobalRef NewGlobalRef(IntPtr lref)
+        {
+            if (lref == IntPtr.Zero)
+            {
+                return null;
+            }
+
+            var res = new GlobalRef(_newGlobalRef(_envPtr, lref), _jvm);
+
+            _deleteLocalRef(_envPtr, lref);
+
+            return res;
+        }
+
+        /// <summary>
+        /// Deletes the global reference.
+        /// </summary>
+        public void DeleteGlobalRef(IntPtr gref)
+        {
+            _deleteGlobalRef(_envPtr, gref);
+        }
+
+        /// <summary>
+        /// Throws an exception to java.
+        /// </summary>
+        public void ThrowToJava(Exception e)
+        {
+            Debug.Assert(e != null);
+            var msgChars = IgniteUtils.StringToUtf8Unmanaged(e.Message);
+
+            try
+            {
+                using (var cls = FindClass("org/apache/ignite/IgniteException"))
+                {
+                    _throwNew(_envPtr, cls.Target, new IntPtr(msgChars));
+                }
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(new IntPtr(msgChars));
+            }
+        }
+
+        /// <summary>
+        /// Checks for the JNI exception and throws.
+        /// </summary>
+        private void ExceptionCheck()
+        {
+            if (!_exceptionCheck(_envPtr))
+            {
+                return;
+            }
+
+            var err = _exceptionOccurred(_envPtr);
+            Debug.Assert(err != IntPtr.Zero);
+
+            _exceptionClear(_envPtr);
+
+            using (var errRef = NewGlobalRef(err))
+            {
+                var errRef0 = (long) errRef.Target;
+                var methodId = _jvm.MethodId;
+
+                using (var cls = GetObjectClass(errRef))
+                using (var clsName = CallObjectMethod(cls, methodId.ClassGetName))
+                using (var msg = CallObjectMethod(errRef, methodId.ThrowableGetMessage))
+                using (var trace = CallStaticObjectMethod(methodId.PlatformUtils,
+                    methodId.PlatformUtilsGetStackTrace, &errRef0))
+                {
+                    throw new JavaException(
+                        JStringToString(clsName),
+                        JStringToString(msg),
+                        JStringToString(trace));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the delegate.
+        /// </summary>
+        private static void GetDelegate<T>(IntPtr ptr, out T del)
+        {
+            del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
new file mode 100644 (file)
index 0000000..a2ad499
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// Delegates for JNI Env entity.
+    /// </summary>
+    internal static unsafe class EnvDelegates
+    {
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate JniResult CallStaticVoidMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate byte CallStaticBooleanMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr NewGlobalRef(IntPtr env, IntPtr lobj);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void DeleteLocalRef(IntPtr env, IntPtr lref);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void DeleteGlobalRef(IntPtr env, IntPtr gref);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr FindClass(IntPtr env, [MarshalAs(UnmanagedType.LPStr)] string name);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStaticMethodId(IntPtr env, IntPtr clazz,
+            [MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetMethodId(IntPtr env, IntPtr clazz, [MarshalAs(UnmanagedType.LPStr)] string name,
+            [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr NewStringUtf(IntPtr env, IntPtr utf);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr ExceptionOccurred(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ExceptionClear(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate bool ExceptionCheck(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetObjectClass(IntPtr env, IntPtr obj);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr CallObjectMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate long CallLongMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void CallVoidMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr CallStaticObjectMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStringChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ReleaseStringChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStringUtfChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ReleaseStringUtfChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate int GetStringUtfLength(IntPtr env, IntPtr jstring);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult RegisterNatives(IntPtr env, IntPtr clazz,
+            NativeMethod* methods, int nMethods);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult ThrowNew(IntPtr env, IntPtr clazz, IntPtr msg);
+    }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
new file mode 100644 (file)
index 0000000..01f8634
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// JNIEnv interface.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct EnvInterface
+    {
+        // ReSharper disable MemberCanBePrivate.Global
+        public IntPtr reserved0;
+        public IntPtr reserved1;
+        public IntPtr reserved2;
+        public IntPtr reserved3;
+        public IntPtr GetVersion;
+        public IntPtr DefineClass;
+        public IntPtr FindClass;
+        public IntPtr FromReflectedMethod;
+        public IntPtr FromReflectedField;
+        public IntPtr ToReflectedMethod;
+        public IntPtr GetSuperclass;
+        public IntPtr IsAssignableFrom;
+        public IntPtr ToReflectedField;
+        public IntPtr Throw;
+        public IntPtr ThrowNew;
+        public IntPtr ExceptionOccurred;
+        public IntPtr ExceptionDescribe;
+        public IntPtr ExceptionClear;
+        public IntPtr FatalError;
+        public IntPtr PushLocalFrame;
+        public IntPtr PopLocalFrame;
+        public IntPtr NewGlobalRef;
+        public IntPtr DeleteGlobalRef;
+        public IntPtr DeleteLocalRef;
+        public IntPtr IsSameObject;
+        public IntPtr NewLocalRef;
+        public IntPtr EnsureLocalCapacity;
+        public IntPtr AllocObject;
+        public IntPtr __NewObject;
+        public IntPtr __NewObjectV;
+        public IntPtr NewObject;
+        public IntPtr GetObjectClass;
+        public IntPtr IsInstanceOf;
+        public IntPtr GetMethodID;
+        public IntPtr __CallObjectMethod;
+        public IntPtr __CallObjectMethodV;
+        public IntPtr CallObjectMethod;
+        public IntPtr __CallBooleanMethod;
+        public IntPtr __CallBooleanMethodV;
+        public IntPtr CallBooleanMethod;
+        public IntPtr __CallByteMethod;
+        public IntPtr __CallByteMethodV;
+        public IntPtr CallByteMethod;
+        public IntPtr __CallCharMethod;
+        public IntPtr __CallCharMethodV;
+        public IntPtr CallCharMethod;
+        public IntPtr __CallShortMethod;
+        public IntPtr __CallShortMethodV;
+        public IntPtr CallShortMethod;
+        public IntPtr __CallIntMethod;
+        public IntPtr __CallIntMethodV;
+        public IntPtr CallIntMethod;
+        public IntPtr __CallLongMethod;
+        public IntPtr __CallLongMethodV;
+        public IntPtr CallLongMethod;
+        public IntPtr __CallFloatMethod;
+        public IntPtr __CallFloatMethodV;
+        public IntPtr CallFloatMethod;
+        public IntPtr __CallDoubleMethod;
+        public IntPtr __CallDoubleMethodV;
+        public IntPtr CallDoubleMethod;
+        public IntPtr __CallVoidMethod;
+        public IntPtr __CallVoidMethodV;
+        public IntPtr CallVoidMethod;
+        public IntPtr __CallNonvirtualObjectMethod;
+        public IntPtr __CallNonvirtualObjectMethodV;
+        public IntPtr CallNonvirtualObjectMethod;
+        public IntPtr __CallNonvirtualBooleanMethod;
+        public IntPtr __CallNonvirtualBooleanMethodV;
+        public IntPtr CallNonvirtualBooleanMethod;
+        public IntPtr __CallNonvirtualByteMethod;
+        public IntPtr __CallNonvirtualByteMethodV;
+        public IntPtr CallNonvirtualByteMethod;
+        public IntPtr __CallNonvirtualCharMethod;
+        public IntPtr __CallNonvirtualCharMethodV;
+        public IntPtr CallNonvirtualCharMethod;
+        public IntPtr __CallNonvirtualShortMethod;
+        public IntPtr __CallNonvirtualShortMethodV;
+        public IntPtr CallNonvirtualShortMethod;
+        public IntPtr __CallNonvirtualIntMethod;
+        public IntPtr __CallNonvirtualIntMethodV;
+        public IntPtr CallNonvirtualIntMethod;
+        public IntPtr __CallNonvirtualLongMethod;
+        public IntPtr __CallNonvirtualLongMethodV;
+        public IntPtr CallNonvirtualLongMethod;
+        public IntPtr __CallNonvirtualFloatMethod;
+        public IntPtr __CallNonvirtualFloatMethodV;
+        public IntPtr CallNonvirtualFloatMethod;
+        public IntPtr __CallNonvirtualDoubleMethod;
+        public IntPtr __CallNonvirtualDoubleMethodV;
+        public IntPtr CallNonvirtualDoubleMethod;
+        public IntPtr __CallNonvirtualVoidMethod;
+        public IntPtr __CallNonvirtualVoidMethodV;
+        public IntPtr CallNonvirtualVoidMethod;
+        public IntPtr GetFieldID;
+        public IntPtr GetObjectField;
+        public IntPtr GetBooleanField;
+        public IntPtr GetByteField;
+        public IntPtr GetCharField;
+        public IntPtr GetShortField;
+        public IntPtr GetIntField;
+        public IntPtr GetLongField;
+        public IntPtr GetFloatField;
+        public IntPtr GetDoubleField;
+        public IntPtr SetObjectField;
+        public IntPtr SetBooleanField;
+        public IntPtr SetByteField;
+        public IntPtr SetCharField;
+        public IntPtr SetShortField;
+        public IntPtr SetIntField;
+        public IntPtr SetLongField;
+        public IntPtr SetFloatField;
+        public IntPtr SetDoubleField;
+        public IntPtr GetStaticMethodID;
+        public IntPtr __CallStaticObjectMethod;
+        public IntPtr __CallStaticObjectMethodV;
+        public IntPtr CallStaticObjectMethod;
+        public IntPtr __CallStaticBooleanMethod;
+        public IntPtr __CallStaticBooleanMethodV;
+        public IntPtr CallStaticBooleanMethod;
+        public IntPtr __CallStaticByteMethod;
+        public IntPtr __CallStaticByteMethodV;
+        public IntPtr CallStaticByteMethod;
+        public IntPtr __CallStaticCharMethod;
+        public IntPtr __CallStaticCharMethodV;
+        public IntPtr CallStaticCharMethod;
+        public IntPtr __CallStaticShortMethod;
+        public IntPtr __CallStaticShortMethodV;
+        public IntPtr CallStaticShortMethod;
+        public IntPtr __CallStaticIntMethod;
+        public IntPtr __CallStaticIntMethodV;
+        public IntPtr CallStaticIntMethod;
+        public IntPtr __CallStaticLongMethod;
+        public IntPtr __CallStaticLongMethodV;
+        public IntPtr CallStaticLongMethod;
+        public IntPtr __CallStaticFloatMethod;
+        public IntPtr __CallStaticFloatMethodV;
+        public IntPtr CallStaticFloatMethod;
+        public IntPtr __CallStaticDoubleMethod;
+        public IntPtr __CallStaticDoubleMethodV;
+        public IntPtr CallStaticDoubleMethod;
+        public IntPtr __CallStaticVoidMethod;
+        public IntPtr __CallStaticVoidMethodV;
+        public IntPtr CallStaticVoidMethod;
+        public IntPtr GetStaticFieldID;
+        public IntPtr GetStaticObjectField;
+        public IntPtr GetStaticBooleanField;
+        public IntPtr GetStaticByteField;
+        public IntPtr GetStaticCharField;
+        public IntPtr GetStaticShortField;
+        public IntPtr GetStaticIntField;
+        public IntPtr GetStaticLongField;
+        public IntPtr GetStaticFloatField;
+        public IntPtr GetStaticDoubleField;
+        public IntPtr SetStaticObjectField;
+        public IntPtr SetStaticBooleanField;
+        public IntPtr SetStaticByteField;
+        public IntPtr SetStaticCharField;
+        public IntPtr SetStaticShortField;
+        public IntPtr SetStaticIntField;
+        public IntPtr SetStaticLongField;
+        public IntPtr SetStaticFloatField;
+        public IntPtr SetStaticDoubleField;
+        public IntPtr NewString;
+        public IntPtr GetStringLength;
+        public IntPtr GetStringChars;
+        public IntPtr ReleaseStringChars;
+        public IntPtr NewStringUTF;
+        public IntPtr GetStringUTFLength;
+        public IntPtr GetStringUTFChars;
+        public IntPtr ReleaseStringUTFChars;
+        public IntPtr GetArrayLength;
+        public IntPtr NewObjectArray;
+        public IntPtr GetObjectArrayElement;
+        public IntPtr SetObjectArrayElement;
+        public IntPtr NewBooleanArray;
+        public IntPtr NewByteArray;
+        public IntPtr NewCharArray;
+        public IntPtr NewShortArray;
+        public IntPtr NewIntArray;
+        public IntPtr NewLongArray;
+        public IntPtr NewFloatArray;
+        public IntPtr NewDoubleArray;
+        public IntPtr GetBooleanArrayElements;
+        public IntPtr GetByteArrayElements;
+        public IntPtr GetCharArrayElements;
+        public IntPtr GetShortArrayElements;
+        public IntPtr GetIntArrayElements;
+        public IntPtr GetLongArrayElements;
+        public IntPtr GetFloatArrayElements;
+        public IntPtr GetDoubleArrayElements;
+        public IntPtr ReleaseBooleanArrayElements;
+        public IntPtr ReleaseByteArrayElements;
+        public IntPtr ReleaseCharArrayElements;
+        public IntPtr ReleaseShortArrayElements;
+        public IntPtr ReleaseIntArrayElements;
+        public IntPtr ReleaseLongArrayElements;
+        public IntPtr ReleaseFloatArrayElements;
+        public IntPtr ReleaseDoubleArrayElements;
+        public IntPtr GetBooleanArrayRegion;
+        public IntPtr GetByteArrayRegion;
+        public IntPtr GetCharArrayRegion;
+        public IntPtr GetShortArrayRegion;
+        public IntPtr GetIntArrayRegion;
+        public IntPtr GetLongArrayRegion;
+        public IntPtr GetFloatArrayRegion;
+        public IntPtr GetDoubleArrayRegion;
+        public IntPtr SetBooleanArrayRegion;
+        public IntPtr SetByteArrayRegion;
+        public IntPtr SetCharArrayRegion;
+        public IntPtr SetShortArrayRegion;
+        public IntPtr SetIntArrayRegion;
+        public IntPtr SetLongArrayRegion;
+        public IntPtr SetFloatArrayRegion;
+        public IntPtr SetDoubleArrayRegion;
+        public IntPtr RegisterNatives;
+        public IntPtr UnregisterNatives;
+        public IntPtr MonitorEnter;
+        public IntPtr MonitorExit;
+        public IntPtr GetJavaVM;
+        public IntPtr GetStringRegion;
+        public IntPtr GetStringUTFRegion;
+        public IntPtr GetPrimitiveArrayCritical;
+        public IntPtr ReleasePrimitiveArrayCritical;
+        public IntPtr GetStringCritical;
+        public IntPtr ReleaseStringCritical;
+        public IntPtr NewWeakGlobalRef;
+        public IntPtr DeleteWeakGlobalRef;
+        public IntPtr ExceptionCheck;
+        public IntPtr NewDirectByteBuffer;
+        public IntPtr GetDirectBufferAddress;
+        public IntPtr GetDirectBufferCapacity;
+    }
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
new file mode 100644 (file)
index 0000000..c33a53b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics;
+
+    /// <summary>
+    /// JNI Global Reference.
+    /// <para />
+    /// We should always convert local reference to global and delete local one immediately,
+    /// otherwise these local references may cause memory leaks (false GC roots).
+    /// </summary>
+    internal sealed class GlobalRef : IDisposable
+    {
+        /** Reference. */
+        private readonly IntPtr _target;
+
+        /** JVM. */
+        private readonly Jvm _jvm;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="GlobalRef"/> class.
+        /// </summary>
+        public GlobalRef(IntPtr target, Jvm jvm)
+        {
+            Debug.Assert(target != IntPtr.Zero);
+            Debug.Assert(jvm != null);
+
+            _target = target;
+            _jvm = jvm;
+        }
+
+        /// <summary>
+        /// Gets the target.
+        /// </summary>
+        public IntPtr Target
+        {
+            get { return _target; }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
+        /// <summary>
+        /// Releases the unmanaged resources.
+        /// </summary>
+        private void ReleaseUnmanagedResources()
+        {
+            _jvm.AttachCurrentThread().DeleteGlobalRef(_target);
+        }
+
+        /** <inheritdoc /> */
+        public void Dispose()
+        {
+            ReleaseUnmanagedResources();
+            GC.SuppressFinalize(this);
+        }
+
+        /** <inheritdoc /> */
+        ~GlobalRef()
+        {
+            ReleaseUnmanagedResources();
+        }
+    }
+}
@@ -1,4 +1,4 @@
-/*
+/*
  * 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.
  * limitations under the License.
  */
 
-namespace Apache.Ignite.Core.Impl.Unmanaged
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
 {
-    using System;
-
     /// <summary>
-    /// Unmanaged target.
+    /// JNI call result.
     /// </summary>
-    internal unsafe interface IUnmanagedTarget : IDisposable
+    internal enum JniResult
     {
-        /// <summary>
-        /// Context.
-        /// </summary>
-        void* Context { get; }
-
-        /// <summary>
-        /// Target.
-        /// </summary>
-        void* Target { get; }
-
-        /// <summary>
-        /// Creates new instance with same context and different target.
-        /// </summary>
-        IUnmanagedTarget ChangeTarget(void* target);
+        Success = 0,
+        // ReSharper disable UnusedMember.Global
+        // Some statuses are not used directly, but will be displayed as part of error message.
+        Error = -1,
+        ThreadDetached = -2,
+        VersionError = -3,
+        NotEnoughMemory = -4,
+        AlreadyExists = -5,
+        InvalidArguments = -6
     }
-}
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
new file mode 100644 (file)
index 0000000..10c7468
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Reflection;
+    using System.Runtime.InteropServices;
+    using System.Security;
+    using System.Threading;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// JVM holder. Should exist once per domain.
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal sealed unsafe class Jvm
+    {
+        /** */
+        // ReSharper disable once InconsistentNaming
+        private const int JNI_VERSION_1_6 = 0x00010006;
+
+        /** */
+        private readonly IntPtr _jvmPtr;
+
+        /** */
+        private readonly JvmDelegates.AttachCurrentThread _attachCurrentThread;
+
+        /** */
+        private readonly MethodId _methodId;
+
+        /** Callbacks. */
+        private readonly Callbacks _callbacks;
+
+        /** Static instamce */
+        private static volatile Jvm _instance;
+
+        /** Sync. */
+        private static readonly object SyncRoot = new object();
+
+        /** Console writer. */
+        private static readonly ConsoleWriter ConsoleWriter = new ConsoleWriter();
+
+        /** Env for current thread. */
+        [ThreadStatic] private static Env _env;
+
+        /** Console writer flag. */
+        private int _isConsoleWriterEnabled;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="_instance"/> class.
+        /// </summary>
+        private Jvm(IntPtr jvmPtr)
+        {
+            Debug.Assert(jvmPtr != IntPtr.Zero);
+
+            _jvmPtr = jvmPtr;
+
+            var funcPtr = (JvmInterface**)jvmPtr;
+            var func = **funcPtr;
+            GetDelegate(func.AttachCurrentThread, out _attachCurrentThread);
+
+            var env = AttachCurrentThread();
+            _methodId = new MethodId(env);
+            _callbacks = GetCallbacks(env, this);
+        }
+
+        /// <summary>
+        /// Gets the callbacks.
+        /// </summary>
+        private static Callbacks GetCallbacks(Env env, Jvm jvm)
+        {
+            if (AppDomain.CurrentDomain.IsDefaultAppDomain())
+            {
+                return new Callbacks(env, jvm);
+            }
+
+            // JVM exists once per process, and JVM callbacks exist once per process.
+            // We should register callbacks ONLY from the default AppDomain (which can't be unloaded).
+            // Non-default appDomains should delegate this logic to the default one.
+            var defDomain = AppDomains.GetDefaultAppDomain();
+
+            // In some cases default AppDomain is not able to locate Apache.Ignite.Core assembly.
+            // First, use CreateInstanceFrom to set up the AssemblyResolve handler.
+            var resHelpType = typeof(AssemblyResolver);
+            var resHelp = (AssemblyResolver)defDomain.CreateInstanceFrom(resHelpType.Assembly.Location, resHelpType.FullName)
+                .Unwrap();
+            resHelp.TrackResolve(resHelpType.Assembly.FullName, resHelpType.Assembly.Location);
+
+            // Now use CreateInstance to get the domain helper of a properly loaded class.
+            var type = typeof(CallbackAccessor);
+            var helper = (CallbackAccessor)defDomain.CreateInstance(type.Assembly.FullName, type.FullName).Unwrap();
+
+            return helper.GetCallbacks();
+        }
+
+        /// <summary>
+        /// Gets or creates the JVM.
+        /// </summary>
+        /// <param name="options">JVM options.</param>
+        public static Jvm GetOrCreate(IList<string> options)
+        {
+            lock (SyncRoot)
+            {
+                return _instance ?? (_instance = new Jvm(GetJvmPtr(options)));
+            }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public static Jvm Get()
+        {
+            var res = _instance;
+
+            if (res == null)
+            {
+                throw new IgniteException("JVM has not been created.");
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the method IDs.
+        /// </summary>
+        public MethodId MethodId
+        {
+            get { return _methodId; }
+        }
+
+        /// <summary>
+        /// Attaches current thread to the JVM and returns JNIEnv.
+        /// </summary>
+        public Env AttachCurrentThread()
+        {
+            if (_env == null)
+            {
+                IntPtr envPtr;
+                var res = _attachCurrentThread(_jvmPtr, out envPtr, IntPtr.Zero);
+
+                if (res != JniResult.Success)
+                {
+                    throw new IgniteException("AttachCurrentThread failed: " + res);
+                }
+
+                _env = new Env(envPtr, this);
+            }
+
+            return _env;
+        }
+
+        /// <summary>
+        /// Registers the callbacks.
+        /// </summary>
+        public void RegisterCallbacks(UnmanagedCallbacks cbs)
+        {
+            var id = _callbacks.RegisterHandlers(cbs);
+            cbs.SetContext(id);
+        }
+
+        /// <summary>
+        /// Releases the callbacks.
+        /// </summary>
+        public void ReleaseCallbacks(long igniteId)
+        {
+            _callbacks.ReleaseHandlers(igniteId);
+        }
+
+        /// <summary>
+        /// Enables the Java console output propagation.
+        /// </summary>
+        public void EnableJavaConsoleWriter()
+        {
+            if (Interlocked.CompareExchange(ref _isConsoleWriterEnabled, 1, 0) == 0)
+            {
+                var writerId = _callbacks.RegisterConsoleWriter(ConsoleWriter);
+                AppDomain.CurrentDomain.DomainUnload += (s, a) => _callbacks.ReleaseConsoleWriter(writerId);
+            }
+        }
+
+        /// <summary>
+        /// Gets the JVM pointer.
+        /// </summary>
+        private static IntPtr GetJvmPtr(IList<string> options)
+        {
+            IntPtr jvm;
+            int existingJvmCount;
+
+            // Use existing JVM if present.
+            var res = JniNativeMethods.JNI_GetCreatedJavaVMs(out jvm, 1, out existingJvmCount);
+            if (res != JniResult.Success)
+            {
+                throw new IgniteException("JNI_GetCreatedJavaVMs failed: " + res);
+            }
+
+            if (existingJvmCount > 0)
+            {
+                return jvm;
+            }
+
+            var args = new JvmInitArgs
+            {
+                version = JNI_VERSION_1_6
+            };
+
+            if (options != null && options.Count > 0)
+            {
+                args.nOptions = options.Count;
+                var opt = new JvmOption[options.Count];
+
+                for (int i = 0; i < options.Count; i++)
+                {
+                    opt[i].optionString = Marshal.StringToHGlobalAnsi(options[i]);
+                }
+
+                fixed (JvmOption* a = &opt[0])
+                {
+                    args.options = a;
+                }
+            }
+
+            IntPtr env;
+            res = JniNativeMethods.JNI_CreateJavaVM(out jvm, out env, &args);
+            if (res != JniResult.Success)
+            {
+                throw new IgniteException("JNI_CreateJavaVM failed: " + res);
+            }
+
+            return jvm;
+        }
+
+        /// <summary>
+        /// Gets the delegate.
+        /// </summary>
+        private static void GetDelegate<T>(IntPtr ptr, out T del)
+        {
+            del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+        }
+
+        /// <summary>
+        /// JavaVMOption.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+        [StructLayout(LayoutKind.Sequential, Pack = 0)]
+        private struct JvmOption
+        {
+            public IntPtr optionString;
+            private readonly IntPtr extraInfo;
+        }
+
+        /// <summary>
+        /// JavaVMInitArgs.
+        /// </summary>
+        [StructLayout(LayoutKind.Sequential, Pack = 0)]
+        private struct JvmInitArgs
+        {
+            public int version;
+            public int nOptions;
+            public JvmOption* options;
+            private readonly byte ignoreUnrecognized;
+        }
+
+        /// <summary>
+        /// DLL imports.
+        /// </summary>
+        private static class JniNativeMethods
+        {
+            [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+            internal static extern JniResult JNI_CreateJavaVM(out IntPtr pvm, out IntPtr penv,
+                JvmInitArgs* args);
+
+            [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+            internal static extern JniResult JNI_GetCreatedJavaVMs(out IntPtr pvm, int size,
+                [Out] out int size2);
+        }
+
+        /// <summary>
+        /// Provides access to <see cref="Callbacks"/> instance in the default AppDomain.
+        /// </summary>
+        private class CallbackAccessor : MarshalByRefObject
+        {
+            /// <summary>
+            /// Gets the callbacks.
+            /// </summary>
+            [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+                Justification = "Only instance methods can be called across AppDomain boundaries.")]
+            public Callbacks GetCallbacks()
+            {
+                return GetOrCreate(null)._callbacks;
+            }
+        }
+
+        /// <summary>
+        /// Resolves Apache.Ignite.Core assembly in the default AppDomain when needed.
+        /// </summary>
+        private class AssemblyResolver : MarshalByRefObject
+        {
+            /// <summary>
+            /// Tracks the AssemblyResolve event.
+            /// </summary>
+            [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+                Justification = "Only instance methods can be called across AppDomain boundaries.")]
+            public void TrackResolve(string name, string path)
+            {
+                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
+                {
+                    if (args.Name == name)
+                    {
+                        return Assembly.LoadFrom(path);
+                    }
+
+                    return null;
+                };
+            }
+        }
+    }
+}
@@ -1,4 +1,4 @@
-/*
+/*
  * 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.
  * limitations under the License.
  */
 
-namespace Apache.Ignite.Core.Impl.Unmanaged
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
 {
+    using System;
     using System.Runtime.InteropServices;
 
     /// <summary>
-    /// Unmanaged callback handler function pointers.
+    /// Delegates for JavaVM JNI entity.
     /// </summary>
-    [StructLayout(LayoutKind.Sequential, Pack = 0)]
-    internal unsafe struct UnmanagedCallbackHandlers
+    internal static class JvmDelegates
     {
-        internal void* target;
-
-        internal void* error;
-
-        internal void* loggerLog;
-        internal void* loggerIsLevelEnabled;
-
-        internal void* inLongOutLong;
-        internal void* inLongLongObjectOutLong;
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult AttachCurrentThread(IntPtr jvm, out IntPtr env, IntPtr args);
     }
-}
+}
\ No newline at end of file
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
new file mode 100644 (file)
index 0000000..74d5ba1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// JavaVM interface.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct JvmInterface
+    {
+        // ReSharper disable MemberCanBePrivate.Global
+        public IntPtr reserved0;
+        public IntPtr reserved1;
+        public IntPtr reserved2;
+
+        public IntPtr DestroyJavaVM;
+        public IntPtr AttachCurrentThread;
+        public IntPtr DetachCurrentThread;
+        public IntPtr GetEnv;
+        public IntPtr AttachCurrentThreadAsDaemon;
+    }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
new file mode 100644 (file)
index 0000000..12a4dff
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Diagnostics;
+
+    /// <summary>
+    /// Cached JNI method ids: initialized once on JVM start.
+    /// </summary>
+    internal sealed class MethodId
+    {
+        /// <summary>
+        /// Class.getName().
+        /// </summary>
+        public IntPtr ClassGetName { get; private set; }
+
+        /// <summary>
+        /// Throwable.getMessage().
+        /// </summary>
+        public IntPtr ThrowableGetMessage { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.
+        /// </summary>
+        public GlobalRef PlatformIgnition { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.start().
+        /// </summary>
+        public IntPtr PlatformIgnitionStart { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.stop().
+        /// </summary>
+        public IntPtr PlatformIgnitionStop { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutObjectAsync().
+        /// </summary>
+        public IntPtr TargetInStreamOutObjectAsync { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamAsync().
+        /// </summary>
+        public IntPtr TargetInStreamAsync { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.outObject ().
+        /// </summary>
+        public IntPtr TargetOutObject { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.outStream().
+        /// </summary>
+        public IntPtr TargetOutStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutStream().
+        /// </summary>
+        public IntPtr TargetInStreamOutStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inObjectStreamOutObjectStream().
+        /// </summary>
+        public IntPtr TargetInObjectStreamOutObjectStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutObject().
+        /// </summary>
+        public IntPtr TargetInStreamOutObject { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutLong().
+        /// </summary>
+        public IntPtr TargetInStreamOutLong { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inLongOutLong().
+        /// </summary>
+        public IntPtr TargetInLongOutLong { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils class.
+        /// </summary>
+        public GlobalRef PlatformUtils { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils.getFullStackTrace.
+        /// </summary>
+        public IntPtr PlatformUtilsGetStackTrace { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils.reallocate.
+        /// </summary>
+        public IntPtr PlatformUtilsReallocate { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MethodId"/> class.
+        /// </summary>
+        public MethodId(Env env)
+        {
+            Debug.Assert(env != null);
+
+            using (var classCls = env.FindClass("java/lang/Class"))
+            {
+                ClassGetName = env.GetMethodId(classCls, "getName", "()Ljava/lang/String;");
+            }
+
+            using (var throwableCls = env.FindClass("java/lang/Throwable"))
+            {
+                ThrowableGetMessage = env.GetMethodId(throwableCls, "getMessage", "()Ljava/lang/String;");
+            }
+
+            PlatformIgnition = env.FindClass(
+                "org/apache/ignite/internal/processors/platform/PlatformIgnition");
+            PlatformIgnitionStart = env.GetStaticMethodId(PlatformIgnition,
+                "start", "(Ljava/lang/String;Ljava/lang/String;IJJ)V");
+            PlatformIgnitionStop = env.GetStaticMethodId(PlatformIgnition, "stop", "(Ljava/lang/String;Z)Z");
+
+            using (var target = env.FindClass("org/apache/ignite/internal/processors/platform/PlatformTargetProxy"))
+            {
+                TargetInLongOutLong = env.GetMethodId(target, "inLongOutLong", "(IJ)J");
+                TargetInStreamOutLong = env.GetMethodId(target, "inStreamOutLong", "(IJ)J");
+                TargetInStreamOutObject = env.GetMethodId(target, "inStreamOutObject", "(IJ)Ljava/lang/Object;");
+                TargetInStreamOutStream = env.GetMethodId(target, "inStreamOutStream", "(IJJ)V");
+                TargetInObjectStreamOutObjectStream = env.GetMethodId(target, "inObjectStreamOutObjectStream",
+                    "(ILjava/lang/Object;JJ)Ljava/lang/Object;");
+                TargetOutStream = env.GetMethodId(target, "outStream", "(IJ)V");
+                TargetOutObject = env.GetMethodId(target, "outObject", "(I)Ljava/lang/Object;");
+                TargetInStreamAsync = env.GetMethodId(target, "inStreamAsync", "(IJ)V");
+                TargetInStreamOutObjectAsync =
+                    env.GetMethodId(target, "inStreamOutObjectAsync", "(IJ)Ljava/lang/Object;");
+            }
+
+            PlatformUtils = env.FindClass("org/apache/ignite/internal/processors/platform/utils/PlatformUtils");
+            PlatformUtilsGetStackTrace = env.GetStaticMethodId(PlatformUtils, "getFullStackTrace",
+                "(Ljava/lang/Throwable;)Ljava/lang/String;");
+            PlatformUtilsReallocate = env.GetStaticMethodId(PlatformUtils, "reallocate", "(JI)V");
+        }
+    }
+}
\ No newline at end of file
@@ -1,4 +1,4 @@
-/*
+/*
  * 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.
  * limitations under the License.
  */
 
-namespace Apache.Ignite.Core.Impl.Unmanaged
+using System;
+
+#pragma warning disable 414  // Unused FuncPtr
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
 {
+    using System.Diagnostics.CodeAnalysis;
+    using System.Runtime.InteropServices;
+
     /// <summary>
-    /// Unmanaged context.
-    /// Wrapper around native ctx pointer to track finalization.
+    /// JNINativeMethod structure for registering Java -> .NET callbacks.
     /// </summary>
-    internal unsafe class UnmanagedContext
+    [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+    internal struct NativeMethod
     {
-        /** Context */
-        private readonly void* _nativeCtx;
-
         /// <summary>
-        /// Constructor.
+        /// Method name, char*.
         /// </summary>
-        public UnmanagedContext(void* ctx)
-        {
-            _nativeCtx = ctx;
-        }
+        public IntPtr Name;
 
         /// <summary>
-        /// Gets the native context pointer.
+        /// Method signature, char*.
         /// </summary>
-        public void* NativeContext
-        {
-            get { return _nativeCtx; }
-        }
+        public IntPtr Signature;
 
         /// <summary>
-        /// Destructor.
+        /// Function pointer (from <see cref="Marshal.GetFunctionPointerForDelegate"/>).
         /// </summary>
-        ~UnmanagedContext()
-        {
-            UnmanagedUtils.DeleteContext(_nativeCtx); // Release CPP object.
-        }
+        public IntPtr FuncPtr;
     }
-}
\ No newline at end of file
+}
index 2cc3659..77f7e3d 100644 (file)
@@ -23,7 +23,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.Linq;
-    using System.Runtime.InteropServices;
     using System.Threading;
     using Apache.Ignite.Core.Cache.Affinity;
     using Apache.Ignite.Core.Cluster;
@@ -44,6 +43,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using Apache.Ignite.Core.Impl.Messaging;
     using Apache.Ignite.Core.Impl.Resource;
     using Apache.Ignite.Core.Impl.Services;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Lifecycle;
     using Apache.Ignite.Core.Log;
     using Apache.Ignite.Core.Services;
@@ -52,32 +52,26 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     /// <summary>
     /// Unmanaged callbacks.
     /// </summary>
-    [SuppressMessage("ReSharper", "UnusedMember.Local")]
     [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
         Justification = "This class instance usually lives as long as the app runs.")]
     [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable",
         Justification = "This class instance usually lives as long as the app runs.")]
-    internal unsafe class UnmanagedCallbacks
+    internal unsafe class UnmanagedCallbacks : MarshalByRefObject
     {
-        /** Console write delegate. */
-        private static readonly ConsoleWriteDelegate ConsoleWriteDel = ConsoleWrite;
-
-        /** Console write pointer. */
-        private static readonly void* ConsoleWritePtr =
-            Marshal.GetFunctionPointerForDelegate(ConsoleWriteDel).ToPointer();
-
-        /** Unmanaged context. */
-        private volatile UnmanagedContext _ctx;
+        /** */
+        private long _igniteId;
 
         /** Handle registry. */
         private readonly HandleRegistry _handleRegistry = new HandleRegistry();
 
+        /** JVM. */
+        private readonly Jvm _jvm;
+
         /** Grid. */
         private volatile Ignite _ignite;
 
-        /** Keep references to created delegates. */
-        // ReSharper disable once CollectionNeverQueried.Local
-        private readonly List<Delegate> _delegates = new List<Delegate>(5);
+        /** Log. */
+        private volatile ILogger _log;
 
         /** Max op code. */
         private static readonly int MaxOpCode = Enum.GetValues(typeof(UnmanagedCallbackOp)).Cast<int>().Max();
@@ -95,38 +89,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /** Actions to be called upon Ignite initialization. */
         private readonly List<Action<Ignite>> _initActions = new List<Action<Ignite>>();
 
-        /** GC handle to UnmanagedCallbacks instance to prevent it from being GCed. */
-        private readonly GCHandle _thisHnd;
-
-        /** Callbacks pointer. */
-        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
-        private readonly IntPtr _cbsPtr;
-
-        /** Log. */
-        private readonly ILogger _log;
-
-        /** Error type: generic. */
-        private const int ErrGeneric = 1;
-
-        /** Error type: initialize. */
-        private const int ErrJvmInit = 2;
-
-        /** Error type: attach. */
-        private const int ErrJvmAttach = 3;
-
         /** Operation: prepare .Net. */
         private const int OpPrepareDotNet = 1;
 
-        private delegate void ErrorCallbackDelegate(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars, int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen);
-
-        private delegate void LoggerLogDelegate(void* target, int level, sbyte* messageChars, int messageCharsLen, sbyte* categoryChars, int categoryCharsLen, sbyte* errorInfoChars, int errorInfoCharsLen, long memPtr);
-        private delegate bool LoggerIsLevelEnabledDelegate(void* target, int level);
-
-        private delegate void ConsoleWriteDelegate(sbyte* chars, int charsLen, bool isErr);
-
-        private delegate long InLongOutLongDelegate(void* target, int type, long val);
-        private delegate long InLongLongLongObjectOutLongDelegate(void* target, int type, long val1, long val2, long val3, void* arg);
-
         private delegate long InLongOutLongFunc(long val);
         private delegate long InLongLongLongObjectOutLongFunc(long val1, long val2, long val3, void* arg);
 
@@ -134,30 +99,14 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /// Constructor.
         /// </summary>
         /// <param name="log">Logger.</param>
-        public UnmanagedCallbacks(ILogger log)
+        /// <param name="jvm"></param>
+        public UnmanagedCallbacks(ILogger log, Jvm jvm)
         {
             Debug.Assert(log != null);
+            Debug.Assert(jvm != null);
 
             _log = log;
-
-            var cbs = new UnmanagedCallbackHandlers
-            {
-                target = IntPtr.Zero.ToPointer(), // Target is not used in .Net as we rely on dynamic FP creation.
-
-                error = CreateFunctionPointer((ErrorCallbackDelegate)Error),
-
-                loggerLog = CreateFunctionPointer((LoggerLogDelegate)LoggerLog),
-                loggerIsLevelEnabled = CreateFunctionPointer((LoggerIsLevelEnabledDelegate)LoggerIsLevelEnabled),
-
-                inLongOutLong = CreateFunctionPointer((InLongOutLongDelegate)InLongOutLong),
-                inLongLongObjectOutLong = CreateFunctionPointer((InLongLongLongObjectOutLongDelegate)InLongLongLongObjectOutLong)
-            };
-
-            _cbsPtr = Marshal.AllocHGlobal(UU.HandlersSize());
-
-            Marshal.StructureToPtr(cbs, _cbsPtr, false);
-
-            _thisHnd = GCHandle.Alloc(this);
+            _jvm = jvm;
 
             InitHandlers();
         }
@@ -170,6 +119,22 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             get { return _handleRegistry; }
         }
 
+        /// <summary>
+        /// Gets the ignite identifier.
+        /// </summary>
+        public long IgniteId
+        {
+            get { return _igniteId; }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
         #region HANDLERS
 
         /// <summary>
@@ -266,7 +231,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         #region IMPLEMENTATION: GENERAL PURPOSE
 
         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private long InLongOutLong(void* target, int type, long val)
+        internal long InLongOutLong(int type, long val)
         {
             try
             {
@@ -286,15 +251,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return 0;
+                throw;
             }
         }
 
         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private long InLongLongLongObjectOutLong(void* target, int type, long val1, long val2, long val3, void* arg)
+        internal long InLongLongLongObjectOutLong(int type, long val1, long val2, long val3, IntPtr arg)
         {
             try
             {
@@ -309,15 +271,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
                 if (!hnd.AllowUninitialized)
                     _initEvent.Wait();
 
-                return hnd.Handler(val1, val2, val3, arg);
+                return hnd.Handler(val1, val2, val3, arg.ToPointer());
             }
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return 0;
+                throw;
             }
         }
 
@@ -680,8 +639,8 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
                 if (receiver != null)
                 {
-                    var target = new PlatformJniTarget(new UnmanagedNonReleaseableTarget(_ctx, cache), 
-                        _ignite.Marshaller);
+                    var cacheRef = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) cache);
+                    var target = new PlatformJniTarget(cacheRef, _ignite.Marshaller);
                     receiver.Receive(_ignite, target, stream, keepBinary);
                 }
 
@@ -1069,7 +1028,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         private long OnStart(long memPtr, long unused, long unused1, void* proc)
         {
-            var proc0 = UU.Acquire(_ctx, proc);
+            var proc0 = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) proc);
 
             using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
             {
@@ -1081,14 +1040,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         private long OnStop(long unused)
         {
-            Marshal.FreeHGlobal(_cbsPtr);
-
-            // ReSharper disable once ImpureMethodCallOnReadonlyValueField
-            _thisHnd.Free();
-
-            // Allow context to be collected, which will cause resource cleanup in finalizer.
-            _ctx = null;
-
             // Notify grid
             var ignite = _ignite;
 
@@ -1098,34 +1049,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return 0;
         }
 
-        private void Error(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars,
-            int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen)
-        {
-            // errData mechanism is only needed for CachePartialUpdateException and is no longer used,
-            // since CacheImpl handles all errors itself.
-            Debug.Assert(errDataLen == 0);
-            Debug.Assert(errData == null);
-
-            string errCls = IgniteUtils.Utf8UnmanagedToString(errClsChars, errClsCharsLen);
-            string errMsg = IgniteUtils.Utf8UnmanagedToString(errMsgChars, errMsgCharsLen);
-            string stackTrace = IgniteUtils.Utf8UnmanagedToString(stackTraceChars, stackTraceCharsLen);
-
-            switch (errType)
-            {
-                case ErrGeneric:
-                    throw ExceptionUtils.GetException(_ignite, errCls, errMsg, stackTrace);
-
-                case ErrJvmInit:
-                    throw ExceptionUtils.GetJvmInitializeException(errCls, errMsg, stackTrace);
-
-                case ErrJvmAttach:
-                    throw new IgniteException("Failed to attach to JVM.");
-
-                default:
-                    throw new IgniteException("Unknown exception [cls=" + errCls + ", msg=" + errMsg + ']');
-            }
-        }
-
         private long OnClientDisconnected(long unused)
         {
             _ignite.OnClientDisconnected();
@@ -1140,18 +1063,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return 0;
         }
 
-        private void LoggerLog(void* target, int level, sbyte* messageChars, int messageCharsLen, sbyte* categoryChars,
-            int categoryCharsLen, sbyte* errorInfoChars, int errorInfoCharsLen, long memPtr)
+        internal void LoggerLog(int level, string message, string category, string nativeError, long memPtr)
         {
             // When custom logger in .NET is not defined, Java should not call us.
             Debug.Assert(!(_log is JavaLogger));
 
             SafeCall(() =>
             {
-                var message = IgniteUtils.Utf8UnmanagedToString(messageChars, messageCharsLen);
-                var category = IgniteUtils.Utf8UnmanagedToString(categoryChars, categoryCharsLen);
-                var nativeError = IgniteUtils.Utf8UnmanagedToString(errorInfoChars, errorInfoCharsLen);
-
                 Exception ex = null;
 
                 if (memPtr != 0 && _ignite != null)
@@ -1166,7 +1084,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             }, true);
         }
 
-        private bool LoggerIsLevelEnabled(void* target, int level)
+        internal bool LoggerIsLevelEnabled(int level)
         {
             // When custom logger in .NET is not defined, Java should not call us.
             Debug.Assert(!(_log is JavaLogger));
@@ -1174,24 +1092,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return SafeCall(() => _log.IsEnabled((LogLevel) level), true);
         }
 
-        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private static void ConsoleWrite(sbyte* chars, int charsLen, bool isErr)
-        {
-            try
-            {
-                var str = IgniteUtils.Utf8UnmanagedToString(chars, charsLen);
-
-                var target = isErr ? Console.Error : Console.Out;
-
-                target.Write(str);
-
-            }
-            catch (Exception ex)
-            {
-                Console.Error.WriteLine("ConsoleWrite unmanaged callback failed: " + ex);
-            }
-        }
-
         private long PluginProcessorIgniteStop(long val)
         {
             _ignite.PluginProcessor.OnIgniteStop(val != 0);
@@ -1225,7 +1125,8 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
                 if (affBase != null)
                 {
-                    var baseFunc0 = new PlatformJniTarget(UU.Acquire(_ctx, baseFunc), _ignite.Marshaller);
+                    var baseFuncRef = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) baseFunc);
+                    var baseFunc0 = new PlatformJniTarget(baseFuncRef, _ignite.Marshaller);
 
                     affBase.SetBaseFunction(new PlatformAffinityFunction(baseFunc0));
                 }
@@ -1312,8 +1213,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
+                throw;
             }
         }
 
@@ -1330,32 +1230,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return default(T);
+                throw;
             }
         }
 
         #endregion
         
         /// <summary>
-        /// Callbacks pointer.
-        /// </summary>
-        public void* CallbacksPointer
-        {
-            get { return _cbsPtr.ToPointer(); }
-        }
-
-        /// <summary>
-        /// Gets the context.
-        /// </summary>
-        public UnmanagedContext Context
-        {
-            get { return _ctx; }
-        }
-
-        /// <summary>
         /// Gets the log.
         /// </summary>
         public ILogger Log
@@ -1364,22 +1245,11 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         }
 
         /// <summary>
-        /// Create function pointer for the given function.
+        /// Sets the context.
         /// </summary>
-        private void* CreateFunctionPointer(Delegate del)
-        {
-            _delegates.Add(del); // Prevent delegate from being GC-ed.
-
-            return Marshal.GetFunctionPointerForDelegate(del).ToPointer();
-        }
-
-        /// <param name="context">Context.</param>
-        public void SetContext(void* context)
+        public void SetContext(long igniteId)
         {
-            Debug.Assert(context != null);
-            Debug.Assert(_ctx == null);
-
-            _ctx = new UnmanagedContext(context);
+            _igniteId = igniteId;
         }
 
         /// <summary>
@@ -1409,17 +1279,15 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /// </summary>
         public void Cleanup()
         {
+            // This instance crosses AppDomain boundaries and is GCed with a delay.
+            // Release all external references.
+
             _ignite = null;
+            _log = null;
 
-            _handleRegistry.Close();
-        }
+            _jvm.ReleaseCallbacks(_igniteId);
 
-        /// <summary>
-        /// Gets the console write handler.
-        /// </summary>
-        public static void* ConsoleWriteHandler
-        {
-            get { return ConsoleWritePtr; }
+            _handleRegistry.Close();
         }
 
         /// <summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs
deleted file mode 100644 (file)
index d044c5f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System.Diagnostics.CodeAnalysis;
-
-    /// <summary>
-    /// Unmanaged target which does not require explicit release.
-    /// </summary>
-    internal unsafe class UnmanagedNonReleaseableTarget : IUnmanagedTarget
-    {
-        /** Context. */
-        private readonly UnmanagedContext _ctx;
-
-        /** Target. */
-        private readonly void* _target;
-
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        /// <param name="ctx">Context.</param>
-        /// <param name="target">Target.</param>
-        public UnmanagedNonReleaseableTarget(UnmanagedContext ctx, void* target)
-        {
-            _ctx = ctx;
-            _target = target;
-        }
-
-        /** <inheritdoc /> */
-        public void* Context
-        {
-            get { return _ctx.NativeContext; }
-        }
-
-        /** <inheritdoc /> */
-        public void* Target
-        {
-            get { return _target; }
-        }
-
-        /** <inheritdoc /> */
-        public IUnmanagedTarget ChangeTarget(void* target)
-        {
-            return new UnmanagedTarget(_ctx, target);
-        }
-
-        /** <inheritdoc /> */
-        [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
-            Justification = "There is no finalizer.")]
-        public void Dispose()
-        {
-            // No-op.
-        }
-    }
-}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs
deleted file mode 100644 (file)
index a5e2cb0..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System;
-    using System.Runtime.InteropServices;
-    using UU = UnmanagedUtils;
-
-    /// <summary>
-    /// Base unmanaged target implementation.
-    /// </summary>
-    internal sealed unsafe class UnmanagedTarget : CriticalHandle, IUnmanagedTarget
-    {
-        /** Context. */
-        private readonly UnmanagedContext _ctx;
-        
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        /// <param name="ctx">Context.</param>
-        /// <param name="target">Target.</param>
-        public UnmanagedTarget(UnmanagedContext ctx, void* target)
-            : base(IntPtr.Zero)
-        {
-            _ctx = ctx;
-            
-            SetHandle(new IntPtr(target));
-        }
-
-        /** <inheritdoc /> */
-        public void* Context
-        {
-            get { return _ctx.NativeContext; }
-        }
-
-        /** <inheritdoc /> */
-        public void* Target
-        {
-            get { return handle.ToPointer(); }
-        }
-
-        /** <inheritdoc /> */
-        public IUnmanagedTarget ChangeTarget(void* target)
-        {
-            return new UnmanagedTarget(_ctx, target);
-        }
-
-        /** <inheritdoc /> */
-        protected override bool ReleaseHandle()
-        {
-            UU.Release(this);
-            
-            return true;
-        }
-
-        /** <inheritdoc /> */
-        public override bool IsInvalid
-        {
-            get { return handle == IntPtr.Zero; }
-        }
-    }
-}
index 511bb7a..58586a9 100644 (file)
 
 namespace Apache.Ignite.Core.Impl.Unmanaged
 {
-    using System;
-    using System.Diagnostics;
-    using System.Diagnostics.CodeAnalysis;
-    using System.Runtime.InteropServices;
-    using System.Threading.Tasks;
-    using Apache.Ignite.Core.Common;
-    using JNI = IgniteJniNativeMethods;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
 
     /// <summary>
     /// Unmanaged utility classes.
@@ -33,93 +27,47 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /** Interop factory ID for .Net. */
         private const int InteropFactoryId = 1;
 
-        /// <summary>
-        /// Initializer.
-        /// </summary>
-        [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
-        static UnmanagedUtils()
-        {
-            var platform = Environment.Is64BitProcess ? "x64" : "x86";
-
-            var resName = string.Format("{0}.{1}", platform, IgniteUtils.FileIgniteJniDll);
-
-            var path = IgniteUtils.UnpackEmbeddedResource(resName, IgniteUtils.FileIgniteJniDll);
-
-            var ptr = NativeMethods.LoadLibrary(path);
-
-            if (ptr == IntPtr.Zero)
-            {
-                var err = Marshal.GetLastWin32Error();
-
-                throw new IgniteException(string.Format("Failed to load {0} from {1}: [{2}]",
-                    IgniteUtils.FileIgniteJniDll, path, IgniteUtils.FormatWin32Error(err)));
-            }
-
-            AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
-
-            JNI.SetConsoleHandler(UnmanagedCallbacks.ConsoleWriteHandler);
-
-            // Clean directories in background to avoid extra work on start.
-            Task.Factory.StartNew(IgniteUtils.TryCleanTempDirectories);
-        }
-
-        /// <summary>
-        /// Handles the DomainUnload event of the current AppDomain.
-        /// </summary>
-        private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
-        {
-            // Clean the handler to avoid JVM crash.
-            var removedCnt = JNI.RemoveConsoleHandler(UnmanagedCallbacks.ConsoleWriteHandler);
-
-            Debug.Assert(removedCnt == 1);
-        }
-
-        /// <summary>
-        /// No-op initializer used to force type loading and static constructor call.
-        /// </summary>
-        internal static void Initialize()
-        {
-            // No-op.
-        }
-
         #region NATIVE METHODS: PROCESSOR
 
-        internal static void IgnitionStart(UnmanagedContext ctx, string cfgPath, string gridName,
-            bool clientMode, bool userLogger)
+        internal static void IgnitionStart(Env env, string cfgPath, string gridName,
+            bool clientMode, bool userLogger, long igniteId)
         {
             using (var mem = IgniteManager.Memory.Allocate().GetStream())
+            using (var cfgPath0 = env.NewStringUtf(cfgPath))
+            using (var gridName0 = env.NewStringUtf(gridName))
             {
                 mem.WriteBool(clientMode);
                 mem.WriteBool(userLogger);
 
-                sbyte* cfgPath0 = IgniteUtils.StringToUtf8Unmanaged(cfgPath);
-                sbyte* gridName0 = IgniteUtils.StringToUtf8Unmanaged(gridName);
-
-                try
-                {
-                    // OnStart receives InteropProcessor referece and stores it.
-                    JNI.IgnitionStart(ctx.NativeContext, cfgPath0, gridName0, InteropFactoryId,
-                        mem.SynchronizeOutput());
-                }
-                finally
-                {
-                    Marshal.FreeHGlobal(new IntPtr(cfgPath0));
-                    Marshal.FreeHGlobal(new IntPtr(gridName0));
-                }
+                // Additional data.
+                mem.WriteBool(false);
+                mem.WriteBool(false);
+
+                long* args = stackalloc long[5];
+                args[0] = cfgPath == null ? 0 : cfgPath0.Target.ToInt64();
+                args[1] = gridName == null ? 0 : gridName0.Target.ToInt64();
+                args[2] = InteropFactoryId;
+                args[3] = igniteId;
+                args[4] = mem.SynchronizeOutput();
+
+                // OnStart receives InteropProcessor reference and stores it.
+                var methodId = env.Jvm.MethodId;
+                env.CallStaticVoidMethod(methodId.PlatformIgnition, methodId.PlatformIgnitionStart, args);
             }
         }
 
-        internal static bool IgnitionStop(void* ctx, string gridName, bool cancel)
+        internal static bool IgnitionStop(string gridName, bool cancel)
         {
-            sbyte* gridName0 = IgniteUtils.StringToUtf8Unmanaged(gridName);
+            var env = Jvm.Get().AttachCurrentThread();
+            var methodId = env.Jvm.MethodId;
 
-            try
+            using (var gridName1 = env.NewStringUtf(gridName))
             {
-                return JNI.IgnitionStop(ctx, gridName0, cancel);
-            }
-            finally
-            {
-                Marshal.FreeHGlobal(new IntPtr(gridName0));
+                long* args = stackalloc long[2];
+                args[0] = gridName == null ? 0 : gridName1.Target.ToInt64();
+                args[1] = cancel ? 1 : 0;
+
+                return env.CallStaticBoolMethod(methodId.PlatformIgnition, methodId.PlatformIgnitionStop, args);
             }
         }
 
@@ -127,122 +75,127 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         #region NATIVE METHODS: TARGET
 
-        internal static long TargetInLongOutLong(IUnmanagedTarget target, int opType, long memPtr)
+        internal static long TargetInLongOutLong(GlobalRef target, int opType, long memPtr)
         {
-            return JNI.TargetInLongOutLong(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static long TargetInStreamOutLong(IUnmanagedTarget target, int opType, long memPtr)
-        {
-            return JNI.TargetInStreamOutLong(target.Context, target.Target, opType, memPtr);
-        }
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = memPtr;
 
-        internal static void TargetInStreamOutStream(IUnmanagedTarget target, int opType, long inMemPtr, long outMemPtr)
-        {
-            JNI.TargetInStreamOutStream(target.Context, target.Target, opType, inMemPtr, outMemPtr);
+            return jvm.AttachCurrentThread().CallLongMethod(target, jvm.MethodId.TargetInLongOutLong, args);
         }
 
-        internal static IUnmanagedTarget TargetInStreamOutObject(IUnmanagedTarget target, int opType, long inMemPtr)
+        internal static long TargetInStreamOutLong(GlobalRef target, int opType, long memPtr)
         {
-            void* res = JNI.TargetInStreamOutObject(target.Context, target.Target, opType, inMemPtr);
+            var jvm = target.Jvm;
 
-            if (res == null)
-                return null;
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = memPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallLongMethod(target, jvm.MethodId.TargetInStreamOutLong, args);
         }
 
-        internal static IUnmanagedTarget TargetInObjectStreamOutObjectStream(IUnmanagedTarget target, int opType, void* arg, long inMemPtr, long outMemPtr)
+        internal static void TargetInStreamOutStream(GlobalRef target, int opType, long inMemPtr,
+            long outMemPtr)
         {
-            void* res = JNI.TargetInObjectStreamOutObjectStream(target.Context, target.Target, opType, arg, inMemPtr, outMemPtr);
+            var jvm = target.Jvm;
 
-            if (res == null)
-                return null;
+            long* args = stackalloc long[3];
+            args[0] = opType;
+            args[1] = inMemPtr;
+            args[2] = outMemPtr;
 
-            return target.ChangeTarget(res);
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetInStreamOutStream, args);
         }
 
-        internal static void TargetOutStream(IUnmanagedTarget target, int opType, long memPtr)
+        internal static GlobalRef TargetInStreamOutObject(GlobalRef target, int opType, long inMemPtr)
         {
-            JNI.TargetOutStream(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static IUnmanagedTarget TargetOutObject(IUnmanagedTarget target, int opType)
-        {
-            void* res = JNI.TargetOutObject(target.Context, target.Target, opType);
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = inMemPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInStreamOutObject, args);
         }
 
-        internal static void TargetInStreamAsync(IUnmanagedTarget target, int opType, long memPtr)
+        internal static GlobalRef TargetInObjectStreamOutObjectStream(GlobalRef target, int opType, 
+            GlobalRef arg, long inMemPtr, long outMemPtr)
         {
-            JNI.TargetInStreamAsync(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static IUnmanagedTarget TargetInStreamOutObjectAsync(IUnmanagedTarget target, int opType, long memPtr)
-        {
-            void* res = JNI.TargetInStreamOutObjectAsync(target.Context, target.Target, opType, memPtr);
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = (long) arg.Target;
+            args[2] = inMemPtr;
+            args[3] = outMemPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInObjectStreamOutObjectStream, args);
         }
 
-        #endregion
-
-        #region NATIVE METHODS: MISCELANNEOUS
-
-        internal static void Reallocate(long memPtr, int cap)
+        internal static void TargetOutStream(GlobalRef target, int opType, long memPtr)
         {
-            int res = JNI.Reallocate(memPtr, cap);
+            var jvm = target.Jvm;
 
-            if (res != 0)
-                throw new IgniteException("Failed to reallocate external memory [ptr=" + memPtr + 
-                    ", capacity=" + cap + ']');
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
+
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetOutStream, args);
         }
 
-        internal static IUnmanagedTarget Acquire(UnmanagedContext ctx, void* target)
+        internal static GlobalRef TargetOutObject(GlobalRef target, int opType)
         {
-            void* target0 = JNI.Acquire(ctx.NativeContext, target);
+            var jvm = target.Jvm;
 
-            return new UnmanagedTarget(ctx, target0);
-        }
+            long opType0 = opType;
 
-        internal static void Release(IUnmanagedTarget target)
-        {
-            JNI.Release(target.Target);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetOutObject, &opType0);
         }
 
-        internal static void ThrowToJava(void* ctx, Exception e)
+        internal static void TargetInStreamAsync(GlobalRef target, int opType, long memPtr)
         {
-            char* msgChars = (char*)IgniteUtils.StringToUtf8Unmanaged(e.Message);
+            var jvm = target.Jvm;
 
-            try
-            {
-                JNI.ThrowToJava(ctx, msgChars);
-            }
-            finally
-            {
-                Marshal.FreeHGlobal(new IntPtr(msgChars));
-            }
-        }
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
 
-        internal static int HandlersSize()
-        {
-            return JNI.HandlersSize();
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetInStreamAsync, args);
         }
 
-        internal static void* CreateContext(void* opts, int optsLen, void* cbs)
+        internal static GlobalRef TargetInStreamOutObjectAsync(GlobalRef target, int opType, long memPtr)
         {
-            return JNI.CreateContext(opts, optsLen, cbs);
-        }
+            var jvm = target.Jvm;
 
-        internal static void DeleteContext(void* ctx)
-        {
-            JNI.DeleteContext(ctx);
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
+
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInStreamOutObjectAsync, args);
         }
 
-        internal static void DestroyJvm(void* ctx)
+        #endregion
+
+        #region NATIVE METHODS: MISCELANNEOUS
+
+        internal static void Reallocate(long memPtr, int cap)
         {
-            JNI.DestroyJvm(ctx);
+            var jvm = Jvm.Get();
+            var methodId = jvm.MethodId;
+
+            long* args = stackalloc long[4];
+            args[0] = memPtr;
+            args[1] = cap;
+
+            jvm.AttachCurrentThread().CallStaticVoidMethod(methodId.PlatformUtils, methodId.PlatformUtilsReallocate,
+                args);
         }
 
         #endregion
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1 b/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1
deleted file mode 100644 (file)
index db24751..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-param([string]$configuration="Debug", [string]$msbuildexe = "MSBuild.exe")
-
-$x64 = [System.Environment]::Is64BitOperatingSystem
-$jdkRegKey = 'Software\JavaSoft\Java Development Kit'
-
-# Fisrt, check if JAVA_HOME env vars are set
-if (Test-Path Env:\JAVA_HOME) {
-    if ($x64 -and !$env:JAVA_HOME64) {
-        $env:JAVA_HOME64 = $env:JAVA_HOME
-    }
-    elseif (!$env:JAVA_HOME32) {
-        $env:JAVA_HOME32 = $env:JAVA_HOME
-    }
-}
-
-# Next, check registry
-Function GetJavaHome([string]$path, [Microsoft.Win32.RegistryView] $mode) {
-    $key = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $mode).OpenSubKey($path)
-
-    if ($key -eq $null) {
-        return $null
-    }
-
-    $subKeys = $key.GetSubKeyNames()
-    $curVer = $key.GetValue("CurrentVersion")
-
-    if ($subKeys.Length -eq 0) {
-        return $null
-    }
-
-    if ($curVer -eq $null -or !$subKeys.Contains($curVer)) {
-        $curVer = $subKeys[0]
-    }
-            
-    return $key.OpenSubKey($curVer).GetValue("JavaHome")
-}
-
-# do not read registry if env vars are already set
-if (!$env:JAVA_HOME32) {
-    $env:JAVA_HOME32 = GetJavaHome $jdkRegKey Registry32
-}
-
-
-if ($x64 -and !$env:JAVA_HOME64) {
-    $env:JAVA_HOME64 = GetJavaHome $jdkRegKey Registry64
-}
-
-echo "JAVA_HOME64: $env:JAVA_HOME64"
-echo "JAVA_HOME32: $env:JAVA_HOME32"
-echo "msbuildexe: $msbuildexe"
-echo "x64: $x64"
-
-# build common project
-if ($env:JAVA_HOME64) {
-    $env:JAVA_HOME = $env:JAVA_HOME64
-
-    & $msbuildexe "..\..\cpp\common\project\vs\common.vcxproj" /p:Platform=x64 /p:Configuration=$Configuration /t:Rebuild
-}
-
-if ($env:JAVA_HOME32) {
-    $env:JAVA_HOME = $env:JAVA_HOME32
-
-    & $msbuildexe "..\..\cpp\common\project\vs\common.vcxproj" /p:Platform=Win32 /p:Configuration=$Configuration /t:Rebuild
-}
-
-# build jni project
-if ($env:JAVA_HOME64) {
-    $env:JAVA_HOME = $env:JAVA_HOME64
-
-    & $msbuildexe "..\..\cpp\jni\project\vs\jni.vcxproj" /p:Platform=x64 /p:Configuration=$Configuration /t:Rebuild
-}
-
-if ($env:JAVA_HOME32) {
-    $env:JAVA_HOME = $env:JAVA_HOME32
-
-    & $msbuildexe "..\..\cpp\jni\project\vs\jni.vcxproj" /p:Platform=Win32 /p:Configuration=$Configuration /t:Rebuild
-}
\ No newline at end of file
index 372c2ed..4b302cc 100644 (file)
@@ -20,7 +20,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <DocumentationFile>bin\Debug\Apache.Ignite.EntityFramework.XML</DocumentationFile>
@@ -35,6 +35,7 @@
     <DebugType>none</DebugType>
     <DocumentationFile>bin\Release\Apache.Ignite.EntityFramework.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <PropertyGroup>
     <SignAssembly>true</SignAssembly>
index 142ce73..af87404 100644 (file)
@@ -20,7 +20,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
@@ -32,6 +32,8 @@
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Release\Apache.Ignite.Log4Net.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <PropertyGroup>
     <SignAssembly>true</SignAssembly>
index 9f5287b..34aaa4c 100644 (file)
@@ -2347,7 +2347,8 @@ warnif count > 0
 from t in JustMyCode.Types.Where(t =>
    !t.IsStatic && !t.IsInterface &&
    !t.IsEnumeration && !t.IsDelegate &&
-   !t.IsGeneratedByCompiler)
+   !t.IsGeneratedByCompiler &&
+   !t.FullName.Contains(".Jni."))
 
 let methodsThatCanBeMadeStatic = 
    from m in t.InstanceMethods
@@ -2477,7 +2478,7 @@ select new {
       <Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[//<Name>Avoid the Singleton pattern</Name>
 warnif count > 0
 from t in Application.Types
-where !t.IsStatic && !t.IsAbstract && (t.IsClass || t.IsStructure)
+where !t.IsStatic && !t.IsAbstract && (t.IsClass || t.IsStructure) && t.Name != "Jvm"
 
 // All ctors of a singleton are private
 where t.Constructors.Where(ctor => !ctor.IsPrivate).Count() == 0
@@ -5641,7 +5642,8 @@ from f in JustMyCode.Fields where
    !f.IsEnumValue &&  // The IL code never explicitly uses enumeration value.
     f.Name != "value__"  && // Field named 'value__' are relative to enumerations and the IL code never explicitly uses them.
    !f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
-   !f.IsGeneratedByCompiler
+   !f.IsGeneratedByCompiler &&
+   !f.ParentType.Name.StartsWith("Jvm")
    // If you don't want to link NDepend.API.dll, you can use your own IsNotDeadCodeAttribute
    // and adapt the source code of this rule.
 select new {
index fe83ccd..1ca7b14 100644 (file)
@@ -2,14 +2,9 @@
 Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core", "Apache.Ignite.Core\Apache.Ignite.Core.csproj", "{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}"
-       ProjectSection(ProjectDependencies) = postProject
-               {4F7E4917-4612-4B96-9838-025711ADE391} = {4F7E4917-4612-4B96-9838-025711ADE391}
-       EndProjectSection
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core.Tests", "Apache.Ignite.Core.Tests\Apache.Ignite.Core.Tests.csproj", "{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "..\cpp\common\project\vs\common.vcxproj", "{B63F2E01-5157-4719-8491-0E1C7CD3B701}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core.Tests.TestDll", "Apache.Ignite.Core.Tests.TestDll\Apache.Ignite.Core.Tests.TestDll.csproj", "{F4A69E2D-908E-4F0F-A794-84D508D60E5F}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite", "Apache.Ignite\Apache.Ignite.csproj", "{27F7F3C6-BDDE-43A9-B565-856F8395A04B}"
@@ -40,8 +35,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
                README.md = README.md
        EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jni", "..\cpp\jni\project\vs\jni.vcxproj", "{4F7E4917-4612-4B96-9838-025711ADE391}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Linq", "Apache.Ignite.Linq\Apache.Ignite.Linq.csproj", "{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.AspNet", "Apache.Ignite.AspNet\Apache.Ignite.AspNet.csproj", "{13EA96FC-CC83-4164-A7C0-4F30ED797460}"
@@ -59,201 +52,65 @@ EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
-               Debug|x64 = Debug|x64
-               Debug|x86 = Debug|x86
                Release|Any CPU = Release|Any CPU
-               Release|x64 = Release|x64
-               Release|x86 = Release|x86
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
                {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x64.ActiveCfg = Debug|x64
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x64.Build.0 = Debug|x64
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x86.ActiveCfg = Debug|x86
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x86.Build.0 = Debug|x86
                {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|Any CPU.Build.0 = Release|Any CPU
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x64.ActiveCfg = Release|x64
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x64.Build.0 = Release|x64
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x86.ActiveCfg = Release|x86
-               {4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x86.Build.0 = Release|x86
                {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x64.Build.0 = Debug|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x86.Build.0 = Debug|Any CPU
                {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|Any CPU.Build.0 = Release|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x64.ActiveCfg = Release|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x64.Build.0 = Release|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x86.ActiveCfg = Release|Any CPU
-               {6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x86.Build.0 = Release|Any CPU
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|Any CPU.ActiveCfg = Debug|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x64.ActiveCfg = Debug|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x64.Build.0 = Debug|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x86.ActiveCfg = Debug|Win32
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x86.Build.0 = Debug|Win32
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|Any CPU.ActiveCfg = Release|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x64.ActiveCfg = Release|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x64.Build.0 = Release|x64
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x86.ActiveCfg = Release|Win32
-               {B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x86.Build.0 = Release|Win32
                {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x64.Build.0 = Debug|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x86.Build.0 = Debug|Any CPU
                {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|Any CPU.Build.0 = Release|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x64.ActiveCfg = Release|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x64.Build.0 = Release|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x86.ActiveCfg = Release|Any CPU
-               {F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x86.Build.0 = Release|Any CPU
                {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x64.Build.0 = Debug|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x86.Build.0 = Debug|Any CPU
                {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|Any CPU.Build.0 = Release|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x64.ActiveCfg = Release|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x64.Build.0 = Release|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x86.ActiveCfg = Release|Any CPU
-               {27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x86.Build.0 = Release|Any CPU
                {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x64.Build.0 = Debug|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x86.Build.0 = Debug|Any CPU
                {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.Build.0 = Release|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x64.ActiveCfg = Release|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x64.Build.0 = Release|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x86.ActiveCfg = Release|Any CPU
-               {069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x86.Build.0 = Release|Any CPU
                {DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Debug|x64.Build.0 = Debug|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Debug|x86.Build.0 = Debug|Any CPU
                {DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.Build.0 = Release|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Release|x64.ActiveCfg = Release|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Release|x64.Build.0 = Release|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Release|x86.ActiveCfg = Release|Any CPU
-               {DFB08363-202E-412D-8812-349EF10A8702}.Release|x86.Build.0 = Release|Any CPU
                {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x64.Build.0 = Debug|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x86.Build.0 = Debug|Any CPU
                {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.Build.0 = Release|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x64.ActiveCfg = Release|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x64.Build.0 = Release|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x86.ActiveCfg = Release|Any CPU
-               {8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x86.Build.0 = Release|Any CPU
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Debug|Any CPU.ActiveCfg = Debug|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x64.ActiveCfg = Debug|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x64.Build.0 = Debug|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x86.ActiveCfg = Debug|Win32
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x86.Build.0 = Debug|Win32
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Release|Any CPU.ActiveCfg = Release|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Release|x64.ActiveCfg = Release|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Release|x64.Build.0 = Release|x64
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Release|x86.ActiveCfg = Release|Win32
-               {4F7E4917-4612-4B96-9838-025711ADE391}.Release|x86.Build.0 = Release|Win32
                {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x64.Build.0 = Debug|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x86.Build.0 = Debug|Any CPU
                {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|Any CPU.Build.0 = Release|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x64.ActiveCfg = Release|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x64.Build.0 = Release|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x86.ActiveCfg = Release|Any CPU
-               {5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x86.Build.0 = Release|Any CPU
                {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x64.Build.0 = Debug|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x86.Build.0 = Debug|Any CPU
                {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|Any CPU.Build.0 = Release|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x64.ActiveCfg = Release|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x64.Build.0 = Release|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x86.ActiveCfg = Release|Any CPU
-               {13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x86.Build.0 = Release|Any CPU
                {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x64.Build.0 = Debug|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x86.Build.0 = Debug|Any CPU
                {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|Any CPU.Build.0 = Release|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x64.ActiveCfg = Release|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x64.Build.0 = Release|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x86.ActiveCfg = Release|Any CPU
-               {18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x86.Build.0 = Release|Any CPU
                {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x64.Build.0 = Debug|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x86.Build.0 = Debug|Any CPU
                {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|Any CPU.Build.0 = Release|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x64.ActiveCfg = Release|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x64.Build.0 = Release|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x86.ActiveCfg = Release|Any CPU
-               {C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x86.Build.0 = Release|Any CPU
                {6F82D669-382E-4435-8092-68C4440146D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {6F82D669-382E-4435-8092-68C4440146D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Debug|x64.Build.0 = Debug|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Debug|x86.Build.0 = Debug|Any CPU
                {6F82D669-382E-4435-8092-68C4440146D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {6F82D669-382E-4435-8092-68C4440146D8}.Release|Any CPU.Build.0 = Release|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Release|x64.ActiveCfg = Release|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Release|x64.Build.0 = Release|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Release|x86.ActiveCfg = Release|Any CPU
-               {6F82D669-382E-4435-8092-68C4440146D8}.Release|x86.Build.0 = Release|Any CPU
                {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x64.Build.0 = Debug|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x86.Build.0 = Debug|Any CPU
                {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|Any CPU.Build.0 = Release|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x64.ActiveCfg = Release|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x64.Build.0 = Release|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x86.ActiveCfg = Release|Any CPU
-               {C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x86.Build.0 = Release|Any CPU
                {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|Any CPU.Build.0 = Debug|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x64.ActiveCfg = Debug|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x64.Build.0 = Debug|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x86.ActiveCfg = Debug|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x86.Build.0 = Debug|Any CPU
                {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|Any CPU.Build.0 = Release|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x64.ActiveCfg = Release|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x64.Build.0 = Release|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x86.ActiveCfg = Release|Any CPU
-               {CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x86.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index 5703aa6..6d8aa6b 100644 (file)
@@ -22,6 +22,7 @@ namespace Apache.Ignite
     using System.Configuration;
     using System.Linq;
     using System.ServiceProcess;
+    using System.Threading;
     using Apache.Ignite.Config;
     using Apache.Ignite.Core;
     using Apache.Ignite.Core.Impl;
@@ -97,9 +98,12 @@ namespace Apache.Ignite
                         IgniteService.DoInstall(allArgs);
                     else
                     {
-                        Ignition.Start(Configurator.GetConfiguration(allArgs));
+                        var ignite = Ignition.Start(Configurator.GetConfiguration(allArgs));
 
-                        IgniteManager.DestroyJvm();
+                        // Wait until stopped.
+                        var evt = new ManualResetEventSlim(false);
+                        ignite.Stopped += (s, a) => evt.Set();
+                        evt.Wait();
                     }
 
                     return;
index df0ebb5..db5bc6c 100644 (file)
@@ -6,7 +6,7 @@ Requirements:
 * Oracle JDK 7 and above
 * .NET Framework 4.0
 * PowerShell 3.0+
-* Visual Studio 2010 (later versions require upgrading "common" C++ project, see below)
+* Visual Studio 2010+
 * JAVA_HOME environment variable set to the corresponding JDK (x64 or x86)
 * Apache Maven bin directory in PATH, or MAVEN_HOME environment variable
 
@@ -15,15 +15,4 @@ Building binaries:
 Resulting binaries will be in bin folder, and NuGet packages in nupkg folder.
 
 Running built binaries: resulting "bin" folder in self contained, you can copy it anywhere and run
-  bin\Apache.Ignite.exe  
-
-NOTE: 
-* x86 solution platform requires x86 Oracle JDK.
-* x64 solution platform requires x64 Oracle JDK.
-* AnyCPU platform requires at least one of the above. 
-To build truly universal AnyCPU binaries (suitable for x86 and x64 modes), both x64 and x86 Oracle JDKs should be installed.
-
-Building in later versions of Visual Studio:
-* Open Apache.Ignite.sln in Visual Studio
-* You will be prompted to "Update VC++ Compiler and Libraries", click "Update"
-* OR, right-click "common" project in the Solution Explorer and select "Upgrade VC++ Compiler and Libraries"
\ No newline at end of file
+  bin\Apache.Ignite.exe  
\ No newline at end of file