You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/11/24 08:30:59 UTC

[02/11] ignite git commit: IGNITE-2662 .NET Core and cross-platform (Linux) support

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
index f4660b1..e644e31 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MessagingTest.cs
@@ -635,7 +635,7 @@ namespace Apache.Ignite.Core.Tests
         /// <returns>New instance of message listener.</returns>
         public static IMessageListener<string> GetListener()
         {
-            return new MessageListener<string>(Listen);
+            return new RemoteListener();
         }
 
         /// <summary>
@@ -651,27 +651,29 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
-        /// Listen method.
+        /// Remote listener.
         /// </summary>
-        /// <param name="id">Originating node ID.</param>
-        /// <param name="msg">Message.</param>
-        private static bool Listen(Guid id, string msg)
+        private class RemoteListener : IMessageListener<string>
         {
-            try
+            /** <inheritdoc /> */
+            public bool Invoke(Guid nodeId, string message)
             {
-                LastNodeIds.Push(id);
-                ReceivedMessages.Push(msg);
+                try
+                {
+                    LastNodeIds.Push(nodeId);
+                    ReceivedMessages.Push(message);
 
-                ReceivedEvent.Signal();
+                    ReceivedEvent.Signal();
 
-                return ListenResult;
-            }
-            catch (Exception ex)
-            {
-                // When executed on remote nodes, these exceptions will not go to sender, 
-                // so we have to accumulate them.
-                Failures.Push(string.Format("Exception in Listen (msg: {0}, id: {1}): {2}", msg, id, ex));
-                throw;
+                    return ListenResult;
+                }
+                catch (Exception ex)
+                {
+                    // When executed on remote nodes, these exceptions will not go to sender, 
+                    // so we have to accumulate them.
+                    Failures.Push(string.Format("Exception in Listen (msg: {0}, id: {1}): {2}", message, nodeId, ex));
+                    throw;
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ProjectFilesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ProjectFilesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ProjectFilesTest.cs
index dff7ed7..5415378 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ProjectFilesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ProjectFilesTest.cs
@@ -36,9 +36,10 @@ namespace Apache.Ignite.Core.Tests
         [Test]
         public void TestCsprojToolsVersion()
         {
-            var projFiles = GetDotNetSourceDir().GetFiles("*.csproj", SearchOption.AllDirectories);
+            var projFiles = GetDotNetSourceDir().GetFiles("*.csproj", SearchOption.AllDirectories)
+                .Where(x => !x.Name.Contains("DotNetCore")).ToArray();
+            
             Assert.GreaterOrEqual(projFiles.Length, 7);
-
             CheckFiles(projFiles, x => !x.Contains("ToolsVersion=\"4.0\""), "Invalid csproj files: ");
         }
 
@@ -109,9 +110,10 @@ namespace Apache.Ignite.Core.Tests
         [Test]
         public void TestSlnToolsVersion()
         {
-            var slnFiles = GetDotNetSourceDir().GetFiles("*.sln", SearchOption.AllDirectories);
-            Assert.GreaterOrEqual(slnFiles.Length, 2);
+            var slnFiles = GetDotNetSourceDir().GetFiles("*.sln", SearchOption.AllDirectories)
+                .Where(x => !x.Name.Contains("DotNetCore")).ToArray();
 
+            Assert.GreaterOrEqual(slnFiles.Length, 2);
             CheckFiles(slnFiles, x => !x.Contains("# Visual Studio 2010") ||
                                       !x.Contains("Microsoft Visual Studio Solution File, Format Version 11.00"),
                 "Invalid sln files: ");

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
index 04f968c..e2b3a09 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServicesTest.cs
@@ -26,7 +26,7 @@ namespace Apache.Ignite.Core.Tests.Services
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Cluster;
     using Apache.Ignite.Core.Common;
-    using Apache.Ignite.Core.Impl;
+    //using Apache.Ignite.Core.Impl;
     using Apache.Ignite.Core.Resource;
     using Apache.Ignite.Core.Services;
     using Apache.Ignite.Core.Tests.Compute;
@@ -671,7 +671,9 @@ namespace Apache.Ignite.Core.Tests.Services
         {
             foreach (var grid in Grids)
             {
-                Assert.AreEqual(CompactFooter, ((Ignite)grid).Marshaller.CompactFooter);
+#if !NETCOREAPP2_0
+                Assert.AreEqual(CompactFooter, ((Impl.Ignite) grid).Marshaller.CompactFooter);
+#endif
                 Assert.AreEqual(CompactFooter, grid.GetConfiguration().BinaryConfiguration.CompactFooter);
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
new file mode 100644
index 0000000..4f5f3f4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Common.cs
@@ -0,0 +1,369 @@
+/*
+ * 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.Concurrent;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Threading;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Discovery.Tcp;
+    using Apache.Ignite.Core.Discovery.Tcp.Static;
+#if !NETCOREAPP2_0
+    using Apache.Ignite.Core.Impl;
+    using Apache.Ignite.Core.Impl.Binary;
+#endif
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Test utility methods.
+    /// </summary>
+    public static partial class TestUtils
+    {
+        /** Indicates long running and/or memory/cpu intensive test. */
+        public const string CategoryIntensive = "LONG_TEST";
+
+        /** Indicates examples tests. */
+        public const string CategoryExamples = "EXAMPLES_TEST";
+
+        /** */
+        private const int DfltBusywaitSleepInterval = 200;
+
+        /** */
+
+        private static readonly IList<string> TestJvmOpts = Environment.Is64BitProcess
+            ? new List<string>
+            {
+                "-XX:+HeapDumpOnOutOfMemoryError",
+                "-Xms1g",
+                "-Xmx4g",
+                "-ea",
+                "-DIGNITE_QUIET=true",
+                "-Duser.timezone=UTC"
+            }
+            : new List<string>
+            {
+                "-XX:+HeapDumpOnOutOfMemoryError",
+                "-Xms64m",
+                "-Xmx99m",
+                "-ea",
+                "-DIGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE=1000",
+                "-DIGNITE_QUIET=true",
+                "-Duser.timezone=UTC"
+            };
+
+        /** */
+        private static readonly IList<string> JvmDebugOpts =
+            new List<string> { "-Xdebug", "-Xnoagent", "-Djava.compiler=NONE", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" };
+
+        /** */
+        public static bool JvmDebug = true;
+
+        /** */
+        [ThreadStatic]
+        private static Random _random;
+
+        /** */
+        private static int _seed = Environment.TickCount;
+
+        /// <summary>
+        ///
+        /// </summary>
+        public static Random Random
+        {
+            get { return _random ?? (_random = new Random(Interlocked.Increment(ref _seed))); }
+        }
+
+        /// <summary>
+        ///
+        /// </summary>
+        /// <returns></returns>
+        public static IList<string> TestJavaOptions(bool? jvmDebug = null)
+        {
+            IList<string> ops = new List<string>(TestJvmOpts);
+
+            if (jvmDebug ?? JvmDebug)
+            {
+                foreach (string opt in JvmDebugOpts)
+                    ops.Add(opt);
+            }
+
+            return ops;
+        }
+
+        /// <summary>
+        ///
+        /// </summary>
+        /// <param name="action"></param>
+        /// <param name="threadNum"></param>
+        public static void RunMultiThreaded(Action action, int threadNum)
+        {
+            List<Thread> threads = new List<Thread>(threadNum);
+
+            var errors = new ConcurrentBag<Exception>();
+
+            for (int i = 0; i < threadNum; i++)
+            {
+                threads.Add(new Thread(() =>
+                {
+                    try
+                    {
+                        action();
+                    }
+                    catch (Exception e)
+                    {
+                        errors.Add(e);
+                    }
+                }));
+            }
+
+            foreach (Thread thread in threads)
+                thread.Start();
+
+            foreach (Thread thread in threads)
+                thread.Join();
+            
+            foreach (var ex in errors)
+                Assert.Fail("Unexpected exception: " + ex);
+        }
+
+        /// <summary>
+        ///
+        /// </summary>
+        /// <param name="action"></param>
+        /// <param name="threadNum"></param>
+        /// <param name="duration">Duration of test execution in seconds</param>
+        public static void RunMultiThreaded(Action action, int threadNum, int duration)
+        {
+            List<Thread> threads = new List<Thread>(threadNum);
+
+            var errors = new ConcurrentBag<Exception>();
+
+            bool stop = false;
+
+            for (int i = 0; i < threadNum; i++)
+            {
+                threads.Add(new Thread(() =>
+                {
+                    try
+                    {
+                        while (true)
+                        {
+                            Thread.MemoryBarrier();
+
+                            // ReSharper disable once AccessToModifiedClosure
+                            if (stop)
+                                break;
+
+                            action();
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        errors.Add(e);
+                    }
+                }));
+            }
+
+            foreach (Thread thread in threads)
+                thread.Start();
+
+            Thread.Sleep(duration * 1000);
+
+            stop = true;
+
+            Thread.MemoryBarrier();
+
+            foreach (Thread thread in threads)
+                thread.Join();
+
+            foreach (var ex in errors)
+                Assert.Fail("Unexpected exception: " + ex);
+        }
+
+        /// <summary>
+        /// Wait for particular topology size.
+        /// </summary>
+        /// <param name="grid">Grid.</param>
+        /// <param name="size">Size.</param>
+        /// <param name="timeout">Timeout.</param>
+        /// <returns>
+        ///   <c>True</c> if topology took required size.
+        /// </returns>
+        public static bool WaitTopology(this IIgnite grid, int size, int timeout = 30000)
+        {
+            int left = timeout;
+
+            while (true)
+            {
+                if (grid.GetCluster().GetNodes().Count != size)
+                {
+                    if (left > 0)
+                    {
+                        Thread.Sleep(100);
+
+                        left -= 100;
+                    }
+                    else
+                        break;
+                }
+                else
+                    return true;
+            }
+
+            return false;
+        }
+
+
+
+        /// <summary>
+        /// Waits for condition, polling in busy wait loop.
+        /// </summary>
+        /// <param name="cond">Condition.</param>
+        /// <param name="timeout">Timeout, in milliseconds.</param>
+        /// <returns>True if condition predicate returned true within interval; false otherwise.</returns>
+        public static bool WaitForCondition(Func<bool> cond, int timeout)
+        {
+            if (timeout <= 0)
+                return cond();
+
+            var maxTime = DateTime.Now.AddMilliseconds(timeout + DfltBusywaitSleepInterval);
+
+            while (DateTime.Now < maxTime)
+            {
+                if (cond())
+                    return true;
+
+                Thread.Sleep(DfltBusywaitSleepInterval);
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Gets the static discovery.
+        /// </summary>
+        public static TcpDiscoverySpi GetStaticDiscovery()
+        {
+            return new TcpDiscoverySpi
+            {
+                IpFinder = new TcpDiscoveryStaticIpFinder
+                {
+                    Endpoints = new[] { "127.0.0.1:47500" }
+                },
+                SocketTimeout = TimeSpan.FromSeconds(0.3)
+            };
+        }
+
+        /// <summary>
+        /// Gets the primary keys.
+        /// </summary>
+        public static IEnumerable<int> GetPrimaryKeys(IIgnite ignite, string cacheName,
+            IClusterNode node = null)
+        {
+            var aff = ignite.GetAffinity(cacheName);
+            node = node ?? ignite.GetCluster().GetLocalNode();
+
+            return Enumerable.Range(1, int.MaxValue).Where(x => aff.IsPrimary(node, x));
+        }
+
+        /// <summary>
+        /// Gets the primary key.
+        /// </summary>
+        public static int GetPrimaryKey(IIgnite ignite, string cacheName, IClusterNode node = null)
+        {
+            return GetPrimaryKeys(ignite, cacheName, node).First();
+        }
+
+        /// <summary>
+        /// Asserts that the handle registry is empty.
+        /// </summary>
+        /// <param name="timeout">Timeout, in milliseconds.</param>
+        /// <param name="grids">Grids to check.</param>
+        public static void AssertHandleRegistryIsEmpty(int timeout, params IIgnite[] grids)
+        {
+            foreach (var g in grids)
+                AssertHandleRegistryHasItems(g, 0, timeout);
+        }
+
+        /// <summary>
+        /// Asserts that the handle registry has specified number of entries.
+        /// </summary>
+        /// <param name="timeout">Timeout, in milliseconds.</param>
+        /// <param name="expectedCount">Expected item count.</param>
+        /// <param name="grids">Grids to check.</param>
+        public static void AssertHandleRegistryHasItems(int timeout, int expectedCount, params IIgnite[] grids)
+        {
+            foreach (var g in grids)
+                AssertHandleRegistryHasItems(g, expectedCount, timeout);
+        }
+
+        /// <summary>
+        /// Asserts that the handle registry has specified number of entries.
+        /// </summary>
+        /// <param name="grid">The grid to check.</param>
+        /// <param name="expectedCount">Expected item count.</param>
+        /// <param name="timeout">Timeout, in milliseconds.</param>
+        public static void AssertHandleRegistryHasItems(IIgnite grid, int expectedCount, int timeout)
+        {
+#if !NETCOREAPP2_0
+            var handleRegistry = ((Ignite)grid).HandleRegistry;
+
+            expectedCount++;  // Skip default lifecycle bean
+
+            if (WaitForCondition(() => handleRegistry.Count == expectedCount, timeout))
+                return;
+
+            var items = handleRegistry.GetItems().Where(x => !(x.Value is LifecycleHandlerHolder)).ToList();
+
+            if (items.Any())
+            {
+                Assert.Fail("HandleRegistry is not empty in grid '{0}' (expected {1}, actual {2}):\n '{3}'",
+                    grid.Name, expectedCount, handleRegistry.Count,
+                    items.Select(x => x.ToString()).Aggregate((x, y) => x + "\n" + y));
+            }
+#endif
+        }
+
+        /// <summary>
+        /// Serializes and deserializes back an object.
+        /// </summary>
+        public static T SerializeDeserialize<T>(T obj)
+        {
+#if NETCOREAPP2_0
+            var marshType = typeof(IIgnite).Assembly.GetType("Apache.Ignite.Core.Impl.Binary.Marshaller");
+            var marsh = Activator.CreateInstance(marshType, new object[] { null, null });
+            marshType.GetProperty("CompactFooter").SetValue(marsh, false);
+
+            var bytes = marshType.GetMethod("Marshal").MakeGenericMethod(typeof(object))
+                .Invoke(marsh, new object[] { obj });
+
+            var res = marshType.GetMethods().Single(mi =>
+                    mi.Name == "Unmarshal" && mi.GetParameters().First().ParameterType == typeof(byte[]))
+                .MakeGenericMethod(typeof(object)).Invoke(marsh, new[] { bytes, 0 });
+
+            return (T)res;
+#else
+            var marsh = new Marshaller(null) { CompactFooter = false };
+
+            return marsh.Unmarshal<T>(marsh.Marshal(obj));
+#endif
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
new file mode 100644
index 0000000..14b58f2
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.Windows.cs
@@ -0,0 +1,122 @@
+/*
+ * 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.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using Apache.Ignite.Core.Configuration;
+    using Apache.Ignite.Core.Impl;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Tests.Process;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Test utility methods - Windows-specific part (full framework).
+    /// </summary>
+    public static partial class TestUtils
+    {
+        /// <summary>
+        ///
+        /// </summary>
+        /// <returns></returns>
+        public static string CreateTestClasspath()
+        {
+            return Classpath.CreateClasspath(forceTestClasspath: true);
+        }
+
+        /// <summary>
+        /// Gets the name of the temporary directory.
+        /// </summary>
+        public static string GetTempDirectoryName()
+        {
+            return IgniteUtils.GetTempDirectoryName();
+        }
+
+        /// <summary>
+        /// Kill Ignite processes.
+        /// </summary>
+        public static void KillProcesses()
+        {
+            IgniteProcess.KillAll();
+        }
+
+        /// <summary>
+        /// Gets the default code-based test configuration.
+        /// </summary>
+        public static IgniteConfiguration GetTestConfiguration(bool? jvmDebug = null, string name = null)
+        {
+            return new IgniteConfiguration
+            {
+                DiscoverySpi = GetStaticDiscovery(),
+                Localhost = "127.0.0.1",
+                JvmOptions = TestJavaOptions(jvmDebug),
+                JvmClasspath = CreateTestClasspath(),
+                IgniteInstanceName = name,
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DefaultDataRegionConfiguration = new DataRegionConfiguration
+                    {
+                        Name = DataStorageConfiguration.DefaultDataRegionName,
+                        InitialSize = 128 * 1024 * 1024,
+                        MaxSize = Environment.Is64BitProcess
+                            ? DataRegionConfiguration.DefaultMaxSize
+                            : 256 * 1024 * 1024
+                    }
+                }
+            };
+        }
+
+        /// <summary>
+        /// Runs the test in new process.
+        /// </summary>
+        [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+        public static void RunTestInNewProcess(string fixtureName, string testName)
+        {
+            var procStart = new ProcessStartInfo
+            {
+                FileName = typeof(TestUtils).Assembly.Location,
+                Arguments = fixtureName + " " + testName,
+                CreateNoWindow = true,
+                UseShellExecute = false,
+                RedirectStandardOutput = true,
+                RedirectStandardError = true
+            };
+
+            var proc = System.Diagnostics.Process.Start(procStart);
+            Assert.IsNotNull(proc);
+
+            try
+            {
+                IgniteProcess.AttachProcessConsoleReader(proc);
+
+                Assert.IsTrue(proc.WaitForExit(19000));
+                Assert.AreEqual(0, proc.ExitCode);
+            }
+            finally
+            {
+                if (!proc.HasExited)
+                {
+                    proc.Kill();
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
deleted file mode 100644
index 26caf53..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
+++ /dev/null
@@ -1,488 +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.Tests
-{
-    using System;
-    using System.Collections;
-    using System.Collections.Concurrent;
-    using System.Collections.Generic;
-    using System.Diagnostics;
-    using System.Diagnostics.CodeAnalysis;
-    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;
-    using Apache.Ignite.Core.Impl.Binary;
-    using Apache.Ignite.Core.Impl.Common;
-    using Apache.Ignite.Core.Tests.Process;
-    using NUnit.Framework;
-
-    /// <summary>
-    /// Test utility methods.
-    /// </summary>
-    public static class TestUtils
-    {
-        /** Indicates long running and/or memory/cpu intensive test. */
-        public const string CategoryIntensive = "LONG_TEST";
-
-        /** Indicates examples tests. */
-        public const string CategoryExamples = "EXAMPLES_TEST";
-
-        /** */
-        private const int DfltBusywaitSleepInterval = 200;
-
-        /** */
-
-        private static readonly IList<string> TestJvmOpts = Environment.Is64BitProcess
-            ? new List<string>
-            {
-                "-XX:+HeapDumpOnOutOfMemoryError",
-                "-Xms1g",
-                "-Xmx4g",
-                "-ea",
-                "-DIGNITE_QUIET=true",
-                "-Duser.timezone=UTC"
-            }
-            : new List<string>
-            {
-                "-XX:+HeapDumpOnOutOfMemoryError",
-                "-Xms64m",
-                "-Xmx99m",
-                "-ea",
-                "-DIGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE=1000",
-                "-DIGNITE_QUIET=true"
-            };
-
-        /** */
-        private static readonly IList<string> JvmDebugOpts =
-            new List<string> { "-Xdebug", "-Xnoagent", "-Djava.compiler=NONE", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" };
-
-        /** */
-        public static bool JvmDebug = true;
-
-        /** */
-        [ThreadStatic]
-        private static Random _random;
-
-        /** */
-        private static int _seed = Environment.TickCount;
-
-        /// <summary>
-        /// Kill Ignite processes.
-        /// </summary>
-        public static void KillProcesses()
-        {
-            IgniteProcess.KillAll();
-        }
-
-        /// <summary>
-        ///
-        /// </summary>
-        public static Random Random
-        {
-            get { return _random ?? (_random = new Random(Interlocked.Increment(ref _seed))); }
-        }
-
-        /// <summary>
-        ///
-        /// </summary>
-        /// <returns></returns>
-        public static IList<string> TestJavaOptions(bool? jvmDebug = null)
-        {
-            IList<string> ops = new List<string>(TestJvmOpts);
-
-            if (jvmDebug ?? JvmDebug)
-            {
-                foreach (string opt in JvmDebugOpts)
-                    ops.Add(opt);
-            }
-
-            return ops;
-        }
-
-        /// <summary>
-        ///
-        /// </summary>
-        /// <returns></returns>
-        public static string CreateTestClasspath()
-        {
-            return Classpath.CreateClasspath(forceTestClasspath: true);
-        }
-
-        /// <summary>
-        ///
-        /// </summary>
-        /// <param name="action"></param>
-        /// <param name="threadNum"></param>
-        public static void RunMultiThreaded(Action action, int threadNum)
-        {
-            List<Thread> threads = new List<Thread>(threadNum);
-
-            var errors = new ConcurrentBag<Exception>();
-
-            for (int i = 0; i < threadNum; i++)
-            {
-                threads.Add(new Thread(() =>
-                {
-                    try
-                    {
-                        action();
-                    }
-                    catch (Exception e)
-                    {
-                        errors.Add(e);
-                    }
-                }));
-            }
-
-            foreach (Thread thread in threads)
-                thread.Start();
-
-            foreach (Thread thread in threads)
-                thread.Join();
-            
-            foreach (var ex in errors)
-                Assert.Fail("Unexpected exception: " + ex);
-        }
-
-        /// <summary>
-        ///
-        /// </summary>
-        /// <param name="action"></param>
-        /// <param name="threadNum"></param>
-        /// <param name="duration">Duration of test execution in seconds</param>
-        public static void RunMultiThreaded(Action action, int threadNum, int duration)
-        {
-            List<Thread> threads = new List<Thread>(threadNum);
-
-            var errors = new ConcurrentBag<Exception>();
-
-            bool stop = false;
-
-            for (int i = 0; i < threadNum; i++)
-            {
-                threads.Add(new Thread(() =>
-                {
-                    try
-                    {
-                        while (true)
-                        {
-                            Thread.MemoryBarrier();
-
-                            // ReSharper disable once AccessToModifiedClosure
-                            if (stop)
-                                break;
-
-                            action();
-                        }
-                    }
-                    catch (Exception e)
-                    {
-                        errors.Add(e);
-                    }
-                }));
-            }
-
-            foreach (Thread thread in threads)
-                thread.Start();
-
-            Thread.Sleep(duration * 1000);
-
-            stop = true;
-
-            Thread.MemoryBarrier();
-
-            foreach (Thread thread in threads)
-                thread.Join();
-
-            foreach (var ex in errors)
-                Assert.Fail("Unexpected exception: " + ex);
-        }
-
-        /// <summary>
-        /// Wait for particular topology size.
-        /// </summary>
-        /// <param name="grid">Grid.</param>
-        /// <param name="size">Size.</param>
-        /// <param name="timeout">Timeout.</param>
-        /// <returns>
-        ///   <c>True</c> if topology took required size.
-        /// </returns>
-        public static bool WaitTopology(this IIgnite grid, int size, int timeout = 30000)
-        {
-            int left = timeout;
-
-            while (true)
-            {
-                if (grid.GetCluster().GetNodes().Count != size)
-                {
-                    if (left > 0)
-                    {
-                        Thread.Sleep(100);
-
-                        left -= 100;
-                    }
-                    else
-                        break;
-                }
-                else
-                    return true;
-            }
-
-            return false;
-        }
-
-        /// <summary>
-        /// Asserts that the handle registry is empty.
-        /// </summary>
-        /// <param name="timeout">Timeout, in milliseconds.</param>
-        /// <param name="grids">Grids to check.</param>
-        public static void AssertHandleRegistryIsEmpty(int timeout, params IIgnite[] grids)
-        {
-            foreach (var g in grids)
-                AssertHandleRegistryHasItems(g, 0, timeout);
-        }
-
-        /// <summary>
-        /// Asserts that the handle registry has specified number of entries.
-        /// </summary>
-        /// <param name="timeout">Timeout, in milliseconds.</param>
-        /// <param name="expectedCount">Expected item count.</param>
-        /// <param name="grids">Grids to check.</param>
-        public static void AssertHandleRegistryHasItems(int timeout, int expectedCount, params IIgnite[] grids)
-        {
-            foreach (var g in grids)
-                AssertHandleRegistryHasItems(g, expectedCount, timeout);
-        }
-
-        /// <summary>
-        /// Asserts that the handle registry has specified number of entries.
-        /// </summary>
-        /// <param name="grid">The grid to check.</param>
-        /// <param name="expectedCount">Expected item count.</param>
-        /// <param name="timeout">Timeout, in milliseconds.</param>
-        public static void AssertHandleRegistryHasItems(IIgnite grid, int expectedCount, int timeout)
-        {
-            var handleRegistry = ((Ignite)grid).HandleRegistry;
-
-            expectedCount++;  // Skip default lifecycle bean
-
-            if (WaitForCondition(() => handleRegistry.Count == expectedCount, timeout))
-                return;
-
-            var items = handleRegistry.GetItems().Where(x => !(x.Value is LifecycleHandlerHolder)).ToList();
-
-            if (items.Any())
-                Assert.Fail("HandleRegistry is not empty in grid '{0}' (expected {1}, actual {2}):\n '{3}'", 
-                    grid.Name, expectedCount, handleRegistry.Count,
-                    items.Select(x => x.ToString()).Aggregate((x, y) => x + "\n" + y));
-        }
-
-        /// <summary>
-        /// Waits for condition, polling in busy wait loop.
-        /// </summary>
-        /// <param name="cond">Condition.</param>
-        /// <param name="timeout">Timeout, in milliseconds.</param>
-        /// <returns>True if condition predicate returned true within interval; false otherwise.</returns>
-        public static bool WaitForCondition(Func<bool> cond, int timeout)
-        {
-            if (timeout <= 0)
-                return cond();
-
-            var maxTime = DateTime.Now.AddMilliseconds(timeout + DfltBusywaitSleepInterval);
-
-            while (DateTime.Now < maxTime)
-            {
-                if (cond())
-                    return true;
-
-                Thread.Sleep(DfltBusywaitSleepInterval);
-            }
-
-            return false;
-        }
-
-        /// <summary>
-        /// Gets the static discovery.
-        /// </summary>
-        public static TcpDiscoverySpi GetStaticDiscovery()
-        {
-            return new TcpDiscoverySpi
-            {
-                IpFinder = new TcpDiscoveryStaticIpFinder
-                {
-                    Endpoints = new[] { "127.0.0.1:47500" }
-                },
-                SocketTimeout = TimeSpan.FromSeconds(0.3)
-            };
-        }
-
-        /// <summary>
-        /// Gets the default code-based test configuration.
-        /// </summary>
-        public static IgniteConfiguration GetTestConfiguration(bool? jvmDebug = null, string name = null)
-        {
-            return new IgniteConfiguration
-            {
-                DiscoverySpi = GetStaticDiscovery(),
-                Localhost = "127.0.0.1",
-                JvmOptions = TestJavaOptions(jvmDebug),
-                JvmClasspath = CreateTestClasspath(),
-                IgniteInstanceName = name,
-                DataStorageConfiguration = new DataStorageConfiguration
-                {
-                    DefaultDataRegionConfiguration = new DataRegionConfiguration
-                    {
-                        Name = DataStorageConfiguration.DefaultDataRegionName,
-                        InitialSize = 128 * 1024 * 1024,
-                        MaxSize = Environment.Is64BitProcess
-                            ? DataRegionConfiguration.DefaultMaxSize
-                            : 256 * 1024 * 1024
-                    }
-                }
-            };
-        }
-
-        /// <summary>
-        /// Runs the test in new process.
-        /// </summary>
-        [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
-        public static void RunTestInNewProcess(string fixtureName, string testName)
-        {
-            var procStart = new ProcessStartInfo
-            {
-                FileName = typeof(TestUtils).Assembly.Location,
-                Arguments = fixtureName + " " + testName,
-                CreateNoWindow = true,
-                UseShellExecute = false,
-                RedirectStandardOutput = true,
-                RedirectStandardError = true
-            };
-
-            var proc = System.Diagnostics.Process.Start(procStart);
-            Assert.IsNotNull(proc);
-
-            try
-            {
-                IgniteProcess.AttachProcessConsoleReader(proc);
-
-                Assert.IsTrue(proc.WaitForExit(19000));
-                Assert.AreEqual(0, proc.ExitCode);
-            }
-            finally
-            {
-                if (!proc.HasExited)
-                {
-                    proc.Kill();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Serializes and deserializes back an object.
-        /// </summary>
-        public static T SerializeDeserialize<T>(T obj)
-        {
-            var marsh = new Marshaller(null) {CompactFooter = false};
-
-            return marsh.Unmarshal<T>(marsh.Marshal(obj));
-        }
-
-        /// <summary>
-        /// Gets the primary keys.
-        /// </summary>
-        public static IEnumerable<int> GetPrimaryKeys(IIgnite ignite, string cacheName,
-            IClusterNode node = null)
-        {
-            var aff = ignite.GetAffinity(cacheName);
-            node = node ?? ignite.GetCluster().GetLocalNode();
-
-            return Enumerable.Range(1, int.MaxValue).Where(x => aff.IsPrimary(node, x));
-        }
-
-        /// <summary>
-        /// Gets the primary key.
-        /// </summary>
-        public static int GetPrimaryKey(IIgnite ignite, string cacheName, IClusterNode node = null)
-        {
-            return GetPrimaryKeys(ignite, cacheName, node).First();
-        }
-
-        /// <summary>
-        /// Asserts equality with reflection.
-        /// </summary>
-        public static void AssertReflectionEqual(object x, object y, string propertyPath = null,
-            HashSet<string> ignoredProperties = null)
-        {
-            if (x == null && y == null)
-            {
-                return;
-            }
-
-            Assert.IsNotNull(x, propertyPath);
-            Assert.IsNotNull(y, propertyPath);
-
-            var type = x.GetType();
-
-            if (type != typeof(string) && typeof(IEnumerable).IsAssignableFrom(type))
-            {
-                var xCol = ((IEnumerable)x).OfType<object>().ToList();
-                var yCol = ((IEnumerable)y).OfType<object>().ToList();
-
-                Assert.AreEqual(xCol.Count, yCol.Count, propertyPath);
-
-                for (var i = 0; i < xCol.Count; i++)
-                {
-                    AssertReflectionEqual(xCol[i], yCol[i], propertyPath, ignoredProperties);
-                }
-
-                return;
-            }
-
-            Assert.AreEqual(type, y.GetType());
-
-            propertyPath = propertyPath ?? type.Name;
-
-            if (type.IsValueType || type == typeof(string) || type.IsSubclassOf(typeof(Type)))
-            {
-                Assert.AreEqual(x, y, propertyPath);
-                return;
-            }
-
-            var props = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0);
-
-            foreach (var propInfo in props)
-            {
-                if (ignoredProperties != null && ignoredProperties.Contains(propInfo.Name))
-                {
-                    continue;
-                }
-
-                var propName = propertyPath + "." + propInfo.Name;
-
-                var xVal = propInfo.GetValue(x, null);
-                var yVal = propInfo.GetValue(y, null);
-
-                AssertReflectionEqual(xVal, yVal, propName, ignoredProperties);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 21738a2..6deaa9b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -141,6 +141,8 @@
     <Compile Include="Impl\IPlatformTargetInternal.cs" />
     <Compile Include="Impl\DataRegionMetrics.cs" />
     <Compile Include="Impl\PersistentStore\PersistentStoreMetrics.cs" />
+    <Compile Include="Impl\Shell.cs" />
+    <Compile Include="Impl\Unmanaged\DllLoader.cs" />
     <Compile Include="Impl\Unmanaged\Jni\AppDomains.cs" />
     <Compile Include="Impl\Unmanaged\Jni\CallbackDelegates.cs" />
     <Compile Include="Impl\Unmanaged\Jni\Callbacks.cs" />
@@ -157,6 +159,7 @@
     <Compile Include="Impl\Unmanaged\Jni\JniResult.cs" />
     <Compile Include="Impl\Unmanaged\Jni\Jvm.cs" />
     <Compile Include="Impl\Unmanaged\Jni\JvmDelegates.cs" />
+    <Compile Include="Impl\Unmanaged\Os.cs" />
     <Compile Include="PersistentStore\CheckpointWriteOrder.cs" />
     <Compile Include="PersistentStore\IPersistentStoreMetrics.cs" />
     <Compile Include="PersistentStore\Package-Info.cs" />
@@ -463,7 +466,7 @@
     <Compile Include="Impl\Memory\PlatformUnpooledMemory.cs" />
     <Compile Include="Impl\Messaging\MessageListenerHolder.cs" />
     <Compile Include="Impl\Messaging\Messaging.cs" />
-    <Compile Include="Impl\NativeMethods.cs" />
+    <Compile Include="Impl\MemoryInfo.cs" />
     <Compile Include="Impl\Binary\IO\IBinaryStream.cs" />
     <Compile Include="Impl\Binary\IO\BinaryHeapStream.cs" />
     <Compile Include="Impl\Binary\IBinaryTypeDescriptor.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.nuspec
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.nuspec b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.nuspec
index 9049526..88bf095 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.nuspec
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.nuspec
@@ -41,6 +41,7 @@ Creating NuGet package:
         <requireLicenseAcceptance>false</requireLicenseAcceptance>
         <description>
 Apache Ignite In-Memory Data Fabric is a high-performance, integrated and distributed in-memory platform for computing and transacting on large-scale data sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
+Supports .NET 4+ and .NET Core 2.0+.
             
 More info: https://apacheignite-net.readme.io/
         </description>
@@ -54,6 +55,10 @@ More info: https://apacheignite-net.readme.io/
         <file src="NuGet\Uninstall.ps1" target="tools" />
         <file src="NuGet\PostBuild.ps1" target="tools" />
 
+		<!-- Binaries -->
+        <file src="bin\$configuration$\Apache.Ignite.Core.dll" target="lib\net40" />
+		<file src="bin\$configuration$\Apache.Ignite.Core.xml" target="lib\net40" />
+		
         <!-- Include Apache.Ignite.exe -->
         <file src="..\Apache.Ignite\bin\$configuration$\Apache.Ignite.exe" target="lib\net40" />
         <file src="..\Apache.Ignite\bin\$configuration$\Apache.Ignite.exe.config" target="lib\net40" />
@@ -62,7 +67,7 @@ More info: https://apacheignite-net.readme.io/
             Library files (jars) should not be included in project, so that NuGet package restore works properly.
             We keep jars in NuGet dir and copy them over in PostBuild event.
         -->
-        <file src="..\bin\Libs\*.jar" target="Libs" />
+        <file src="..\bin\libs\*.jar" target="libs" />
     
         <!-- LINQPad samples -->
         <file src="NuGet\LINQPad\*.*" target="linqpad-samples" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/MemoryPolicyConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/MemoryPolicyConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/MemoryPolicyConfiguration.cs
index e204ee7..0eedd48 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/MemoryPolicyConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/MemoryPolicyConfiguration.cs
@@ -50,7 +50,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /// <summary>
         /// The default maximum size, equals to 20% of total RAM.
         /// </summary>
-        public static readonly long DefaultMaxSize = (long) ((long) NativeMethods.GetTotalPhysicalMemory() * 0.2);
+        public static readonly long DefaultMaxSize =
+            (long) ((long) MemoryInfo.GetTotalPhysicalMemory(2048L * 1024 * 1024) * 0.2);
 
         /// <summary>
         /// The default sub intervals.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/DataRegionConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/DataRegionConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/DataRegionConfiguration.cs
index d20ce49..6fce7ad 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/DataRegionConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/DataRegionConfiguration.cs
@@ -59,7 +59,8 @@ namespace Apache.Ignite.Core.Configuration
         /// <summary>
         /// The default maximum size, equals to 20% of total RAM.
         /// </summary>
-        public static readonly long DefaultMaxSize = (long)((long)NativeMethods.GetTotalPhysicalMemory() * 0.2);
+        public static readonly long DefaultMaxSize =
+            (long)((long)MemoryInfo.GetTotalPhysicalMemory(2048L * 1024 * 1024) * 0.2);
 
         /// <summary>
         /// The default sub intervals.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index f8c42e5..29b8519 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -733,11 +733,6 @@ namespace Apache.Ignite.Core
 
             JvmInitialMemoryMb = (int) (binaryReader.ReadLong()/1024/2014);
             JvmMaxMemoryMb = (int) (binaryReader.ReadLong()/1024/2014);
-
-            // Local data (not from reader)
-            JvmDllPath = Process.GetCurrentProcess().Modules.OfType<ProcessModule>()
-                .Single(x => string.Equals(x.ModuleName, IgniteUtils.FileJvmDll, StringComparison.OrdinalIgnoreCase))
-                .FileName;
         }
 
         /// <summary>
@@ -756,6 +751,7 @@ namespace Apache.Ignite.Core
             IgniteHome = cfg.IgniteHome;
             JvmClasspath = cfg.JvmClasspath;
             JvmOptions = cfg.JvmOptions;
+            JvmDllPath = cfg.JvmDllPath;
             Assemblies = cfg.Assemblies;
             SuppressWarnings = cfg.SuppressWarnings;
             LifecycleHandlers = cfg.LifecycleHandlers;

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
index 6fa7918..38b17a1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
@@ -278,7 +278,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <summary>
         /// Safely gets all assembly types.
         /// </summary>
-        private static IEnumerable<Type> GetAssemblyTypesSafe(Assembly asm)
+        public static IEnumerable<Type> GetAssemblyTypesSafe(Assembly asm)
         {
             try
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/Classpath.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/Classpath.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/Classpath.cs
index 2065e41..86e70a6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/Classpath.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/Classpath.cs
@@ -18,8 +18,10 @@
 namespace Apache.Ignite.Core.Impl.Common
 {
     using System;
+    using System.Diagnostics.CodeAnalysis;
     using System.Text;
     using System.IO;
+    using Apache.Ignite.Core.Impl.Unmanaged;
     using Apache.Ignite.Core.Log;
 
     /// <summary>
@@ -33,6 +35,10 @@ namespace Apache.Ignite.Core.Impl.Common
         /** Classpath prefix. */
         private const string ClasspathPrefix = "-Djava.class.path=";
 
+        /** Classpath separator. */
+        [SuppressMessage("Microsoft.Performance", "CA1802:UseLiteralsWhereAppropriate")]
+        private static readonly string ClasspathSeparator = Os.IsWindows ? ";" : ":";
+
         /// <summary>
         /// Creates classpath from the given configuration, or default classpath if given config is null.
         /// </summary>
@@ -52,8 +58,8 @@ namespace Apache.Ignite.Core.Impl.Common
             {
                 cpStr.Append(cfg.JvmClasspath);
 
-                if (!cfg.JvmClasspath.EndsWith(";"))
-                    cpStr.Append(';');
+                if (!cfg.JvmClasspath.EndsWith(ClasspathSeparator))
+                    cpStr.Append(ClasspathSeparator);
             }
 
             var ggHome = IgniteHome.Resolve(cfg, log);
@@ -64,7 +70,10 @@ namespace Apache.Ignite.Core.Impl.Common
             if (log != null)
                 log.Debug("Classpath resolved to: " + cpStr);
 
-            return ClasspathPrefix + cpStr;
+            var res = cpStr.ToString();
+            res = res.StartsWith(ClasspathPrefix) ? res : ClasspathPrefix + res;
+
+            return res;
         }
 
         /// <summary>
@@ -79,12 +88,12 @@ namespace Apache.Ignite.Core.Impl.Common
             // Append test directories (if needed) first, because otherwise build *.jar will be picked first.
             if (forceTestClasspath || "true".Equals(Environment.GetEnvironmentVariable(EnvIgniteNativeTestClasspath)))
             {
-                AppendTestClasses(ggHome + "\\examples", cpStr);
-                AppendTestClasses(ggHome + "\\modules", cpStr);
-                AppendTestClasses(ggHome + "\\modules\\extdata\\platform", cpStr);
+                AppendTestClasses(Path.Combine(ggHome, "examples"), cpStr);
+                AppendTestClasses(Path.Combine(ggHome, "modules"), cpStr);
+                AppendTestClasses(Path.Combine(ggHome, "modules", "extdata", "platform"), cpStr);
             }
 
-            string ggLibs = ggHome + "\\libs";
+            string ggLibs = Path.Combine(ggHome, "libs");
 
             AppendJars(ggLibs, cpStr);
 
@@ -124,14 +133,23 @@ namespace Apache.Ignite.Core.Impl.Common
             if (path.EndsWith("rest-http", StringComparison.OrdinalIgnoreCase))
                 return;
 
-            if (Directory.Exists(path + "\\target\\classes"))
-                cp.Append(path + "\\target\\classes;");
+            var dir = Path.Combine(path, "target", "classes");
+            if (Directory.Exists(dir))
+            {
+                cp.Append(dir).Append(ClasspathSeparator);
+            }
 
-            if (Directory.Exists(path + "\\target\\test-classes"))
-                cp.Append(path + "\\target\\test-classes;");
+            dir = Path.Combine(path, "target", "test-classes");
+            if (Directory.Exists(dir))
+            {
+                cp.Append(dir).Append(ClasspathSeparator);
+            }
 
-            if (Directory.Exists(path + "\\target\\libs"))
-                AppendJars(path + "\\target\\libs", cp);
+            dir = Path.Combine(path, "target", "libs");
+            if (Directory.Exists(dir))
+            {
+                AppendJars(dir, cp);
+            }
         }
 
         /// <summary>
@@ -143,10 +161,9 @@ namespace Apache.Ignite.Core.Impl.Common
         {
             if (Directory.Exists(path))
             {
-                foreach (string jar in Directory.EnumerateFiles(path, "*.jar"))
+                foreach (var jar in Directory.EnumerateFiles(path, "*.jar"))
                 {
-                    cpStr.Append(jar);
-                    cpStr.Append(';');
+                    cpStr.Append(jar).Append(ClasspathSeparator);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
index be1a7f1..9a65a24 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
@@ -403,7 +403,7 @@ namespace Apache.Ignite.Core.Impl.Common
         /// </summary>
         private static List<Type> GetConcreteDerivedTypes(Type type)
         {
-            return typeof(IIgnite).Assembly.GetTypes()
+            return TypeResolver.GetAssemblyTypesSafe(typeof(IIgnite).Assembly)
                 .Where(t => t.IsClass && !t.IsAbstract && type.IsAssignableFrom(t)).ToList();
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteHome.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteHome.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteHome.cs
index 3d4ad4d..47065bc 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteHome.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteHome.cs
@@ -114,9 +114,11 @@ namespace Apache.Ignite.Core.Impl.Common
                        (dir.EnumerateDirectories().Count(x => x.Name == "examples" || x.Name == "bin") == 2 &&
                         dir.EnumerateDirectories().Count(x => x.Name == "modules" || x.Name == "platforms") == 1)
                        || // NuGet home
-                       (dir.EnumerateDirectories().Any(x => x.Name == "Libs") &&
+                       (dir.EnumerateDirectories().Any(x => x.Name == "libs") &&
                         (dir.EnumerateFiles("Apache.Ignite.Core.dll").Any() ||
                          dir.EnumerateFiles("Apache.Ignite.*.nupkg").Any() ||
+                         dir.EnumerateFiles("apache.ignite.*.nupkg").Any() ||  // Lowercase on Linux
+                         dir.EnumerateFiles("apache.ignite.nuspec").Any() ||  // Lowercase on Linux
                          dir.EnumerateFiles("Apache.Ignite.nuspec").Any()));
             }
             catch (IOException)

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
index 38eda1b..022a5ed 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
@@ -19,8 +19,6 @@ namespace Apache.Ignite.Core.Impl
 {
     using System;
     using System.Collections.Generic;
-    using System.ComponentModel;
-    using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.IO;
     using System.Linq;
@@ -33,6 +31,7 @@ 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;
@@ -46,17 +45,28 @@ namespace Apache.Ignite.Core.Impl
         private const string EnvJavaHome = "JAVA_HOME";
 
         /** Lookup paths. */
-        private static readonly string[] JvmDllLookupPaths =
-        {
-            // JRE paths
-            @"bin\server",
-            @"bin\client",
-
-            // JDK paths
-            @"jre\bin\server",
-            @"jre\bin\client",
-            @"jre\bin\default"
-        };
+        private static readonly string[] JvmDllLookupPaths = Os.IsWindows
+            ? new[]
+            {
+                // JRE paths
+                @"bin\server",
+                @"bin\client",
+
+                // JDK paths
+                @"jre\bin\server",
+                @"jre\bin\client",
+                @"jre\bin\default"
+            }
+            : new[]
+            {
+                // JRE paths
+                "lib/amd64/server",
+                "lib/amd64/client",
+
+                // JDK paths
+                "jre/lib/amd64/server",
+                "jre/lib/amd64/client"
+            };
 
         /** Registry lookup paths. */
         private static readonly string[] JreRegistryKeys =
@@ -65,8 +75,8 @@ namespace Apache.Ignite.Core.Impl
             @"Software\Wow6432Node\JavaSoft\Java Runtime Environment"
         };
 
-        /** File: jvm.dll. */
-        internal const string FileJvmDll = "jvm.dll";
+        /** Jvm dll file name. */
+        internal static readonly string FileJvmDll = Os.IsWindows ? "jvm.dll" : "libjvm.so";
 
         /** Prefix for temp directory names. */
         private const string DirIgniteTmp = "Ignite_";
@@ -195,15 +205,15 @@ namespace Apache.Ignite.Core.Impl
             {
                 log.Debug("Trying to load JVM dll from [option={0}, path={1}]...", dllPath.Key, dllPath.Value);
 
-                var errCode = LoadDll(dllPath.Value, FileJvmDll);
-                if (errCode == 0)
+                var errInfo = LoadDll(dllPath.Value, FileJvmDll);
+                if (errInfo == null)
                 {
                     log.Debug("jvm.dll successfully loaded from [option={0}, path={1}]", dllPath.Key, dllPath.Value);
                     return;
                 }
 
                 var message = string.Format(CultureInfo.InvariantCulture, "[option={0}, path={1}, error={2}]",
-                                                  dllPath.Key, dllPath.Value, FormatWin32Error(errCode));
+                                                  dllPath.Key, dllPath.Value, errInfo);
                 messages.Add(message);
 
                 log.Debug("Failed to load jvm.dll: " + message);
@@ -228,62 +238,32 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
-        /// Formats the Win32 error.
-        /// </summary>
-        [ExcludeFromCodeCoverage]
-        private static string FormatWin32Error(int errorCode)
-        {
-            if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT)
-            {
-                var mode = Environment.Is64BitProcess ? "x64" : "x86";
-
-                return string.Format("DLL could not be loaded (193: ERROR_BAD_EXE_FORMAT). " +
-                                     "This is often caused by x64/x86 mismatch. " +
-                                     "Current process runs in {0} mode, and DLL is not {0}.", mode);
-            }
-
-            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. ";
-            }
-
-            return string.Format("{0}: {1}", errorCode, new Win32Exception(errorCode).Message);
-        }
-
-        /// <summary>
         /// Try loading DLLs first using file path, then using it's simple name.
         /// </summary>
         /// <param name="filePath"></param>
         /// <param name="simpleName"></param>
-        /// <returns>Zero in case of success, error code in case of failure.</returns>
-        private static int LoadDll(string filePath, string simpleName)
+        /// <returns>Null in case of success, error info in case of failure.</returns>
+        private static string LoadDll(string filePath, string simpleName)
         {
-            int res = 0;
-
-            IntPtr ptr;
+            string res = null;
 
             if (filePath != null)
             {
-                ptr = NativeMethods.LoadLibrary(filePath);
+                res = DllLoader.Load(filePath);
 
-                if (ptr == IntPtr.Zero)
-                    res = Marshal.GetLastWin32Error();
-                else
-                    return res;
+                if (res == null)
+                {
+                    return null;  // Success.
+                }
             }
 
             // Failed to load using file path, fallback to simple name.
-            ptr = NativeMethods.LoadLibrary(simpleName);
+            var res2 = DllLoader.Load(simpleName);
 
-            if (ptr == IntPtr.Zero)
+            if (res2 == null)
             {
-                // Preserve the first error code, if any.
-                if (res == 0)
-                    res = Marshal.GetLastWin32Error();
+                return null;  // Success.
             }
-            else
-                res = 0;
 
             return res;
         }
@@ -294,16 +274,37 @@ namespace Apache.Ignite.Core.Impl
         private static IEnumerable<KeyValuePair<string, string>> GetJvmDllPaths(string configJvmDllPath)
         {
             if (!string.IsNullOrEmpty(configJvmDllPath))
+            {
                 yield return new KeyValuePair<string, string>("IgniteConfiguration.JvmDllPath", configJvmDllPath);
+            }
 
             var javaHomeDir = Environment.GetEnvironmentVariable(EnvJavaHome);
 
             if (!string.IsNullOrEmpty(javaHomeDir))
+            {
                 foreach (var path in JvmDllLookupPaths)
+                {
                     yield return
                         new KeyValuePair<string, string>(EnvJavaHome, Path.Combine(javaHomeDir, path, FileJvmDll));
+                }
+            }
+
+            foreach (var keyValuePair in GetJvmDllPathsFromRegistry().Concat(GetJvmDllPathsFromSymlink()))
+            {
+                yield return keyValuePair;
+            }
+        }
+
+        /// <summary>
+        /// Gets Jvm dll paths from Windows registry.
+        /// </summary>
+        private static IEnumerable<KeyValuePair<string, string>> GetJvmDllPathsFromRegistry()
+        {
+            if (!Os.IsWindows)
+            {
+                yield break;
+            }
 
-            // Get paths from the Windows Registry
             foreach (var regPath in JreRegistryKeys)
             {
                 using (var jSubKey = Registry.LocalMachine.OpenSubKey(regPath))
@@ -331,6 +332,50 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
+        /// Gets the Jvm dll paths from symlink.
+        /// </summary>
+        private static IEnumerable<KeyValuePair<string, string>> GetJvmDllPathsFromSymlink()
+        {
+            if (Os.IsWindows)
+            {
+                yield break;
+            }
+
+            const string javaExec = "/usr/bin/java";
+            if (!File.Exists(javaExec))
+            {
+                yield break;
+            }
+
+            var file = Shell.BashExecute("readlink -f /usr/bin/java");
+            // /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
+
+            var dir = Path.GetDirectoryName(file);
+            // /usr/lib/jvm/java-8-openjdk-amd64/jre/bin
+
+            if (dir == null)
+            {
+                yield break;
+            }
+
+            var libFolder = Path.GetFullPath(Path.Combine(dir, "../lib/"));
+            if (!Directory.Exists(libFolder))
+            {
+                yield break;
+            }
+
+            // Predefined path: /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so
+            yield return new KeyValuePair<string, string>(javaExec,
+                Path.Combine(libFolder, "amd64", "server", FileJvmDll));
+
+            // Last resort - custom paths:
+            foreach (var f in Directory.GetFiles(libFolder, FileJvmDll, SearchOption.AllDirectories))
+            {
+                yield return new KeyValuePair<string, string>(javaExec, f);
+            }
+        }
+
+        /// <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>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/MemoryInfo.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/MemoryInfo.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/MemoryInfo.cs
new file mode 100644
index 0000000..7cfd019
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/MemoryInfo.cs
@@ -0,0 +1,110 @@
+/*
+ * 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
+{
+    using System.Diagnostics.CodeAnalysis;
+    using System.IO;
+    using System.Linq;
+    using System.Runtime.InteropServices;
+    using System.Text.RegularExpressions;
+    using Apache.Ignite.Core.Impl.Unmanaged;
+
+    /// <summary>
+    /// Memory info.
+    /// </summary>
+    internal static class MemoryInfo
+    {
+        /// <summary>
+        /// Gets the total physical memory.
+        /// </summary>
+        public static ulong GetTotalPhysicalMemory(ulong defaultValue)
+        {
+            if (Os.IsWindows)
+            {
+                return NativeMethodsWindows.GlobalMemoryStatusExTotalPhys();
+            }
+
+            const string memInfo = "/proc/meminfo";
+
+            if (File.Exists(memInfo))
+            {
+                var kbytes = File.ReadAllLines(memInfo).Select(x => Regex.Match(x, @"MemTotal:\s+([0-9]+) kB"))
+                    .Where(x => x.Success)
+                    .Select(x => x.Groups[1].Value).FirstOrDefault();
+
+                if (kbytes != null)
+                {
+                    return ulong.Parse(kbytes) * 1024;
+                }
+            }
+
+            return defaultValue;
+        }
+
+        /// <summary>
+        /// Native methods.
+        /// </summary>
+        private static class NativeMethodsWindows
+        {
+            /// <summary>
+            /// Gets the total physical memory.
+            /// </summary>
+            internal static ulong GlobalMemoryStatusExTotalPhys()
+            {
+                var status = new MEMORYSTATUSEX();
+                status.Init();
+
+                GlobalMemoryStatusEx(ref status);
+
+                return status.ullTotalPhys;
+            }
+
+            /// <summary>
+            /// Globals the memory status.
+            /// </summary>
+            [return: MarshalAs(UnmanagedType.Bool)]
+            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            private static extern bool GlobalMemoryStatusEx([In, Out] ref MEMORYSTATUSEX lpBuffer);
+
+            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+            // ReSharper disable InconsistentNaming
+            // ReSharper disable MemberCanBePrivate.Local
+            private struct MEMORYSTATUSEX
+            {
+                public uint dwLength;
+                public readonly uint dwMemoryLoad;
+                public readonly ulong ullTotalPhys;
+                public readonly ulong ullAvailPhys;
+                public readonly ulong ullTotalPageFile;
+                public readonly ulong ullAvailPageFile;
+                public readonly ulong ullTotalVirtual;
+                public readonly ulong ullAvailVirtual;
+                public readonly ulong ullAvailExtendedVirtual;
+
+                /// <summary>
+                /// Initializes a new instance of the <see cref="MEMORYSTATUSEX"/> struct.
+                /// </summary>
+                public void Init()
+                {
+                    dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/NativeMethods.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/NativeMethods.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/NativeMethods.cs
deleted file mode 100644
index 0004772..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/NativeMethods.cs
+++ /dev/null
@@ -1,93 +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
-{
-    using System;
-    using System.Runtime.InteropServices;
-
-    /// <summary>
-    /// Native methods.
-    /// </summary>
-    internal static class NativeMethods
-    {
-        /// <summary>
-        /// ERROR_BAD_EXE_FORMAT constant.
-        /// </summary>
-        // ReSharper disable once InconsistentNaming
-        public const int ERROR_BAD_EXE_FORMAT = 193;
-
-        /// <summary>
-        /// ERROR_MOD_NOT_FOUND constant.
-        /// </summary>
-        // ReSharper disable once InconsistentNaming
-        public const int ERROR_MOD_NOT_FOUND = 126;
-
-        /// <summary>
-        /// Load DLL with WinAPI.
-        /// </summary>
-        /// <param name="path">Path to dll.</param>
-        /// <returns></returns>
-        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false, 
-            ThrowOnUnmappableChar = true)]
-        internal static extern IntPtr LoadLibrary(string path);
-
-        /// <summary>
-        /// Gets the total physical memory.
-        /// </summary>
-        internal static ulong GetTotalPhysicalMemory()
-        {
-            var status = new MEMORYSTATUSEX();
-            status.Init();
-
-            GlobalMemoryStatusEx(ref status);
-
-            return status.ullTotalPhys;
-        }
-
-        /// <summary>
-        /// Globals the memory status.
-        /// </summary>
-        [return: MarshalAs(UnmanagedType.Bool)]
-        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
-        private static extern bool GlobalMemoryStatusEx([In, Out] ref MEMORYSTATUSEX lpBuffer);
-
-        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
-        // ReSharper disable InconsistentNaming
-        // ReSharper disable MemberCanBePrivate.Local
-        private struct MEMORYSTATUSEX
-        {
-            public uint dwLength;
-            public readonly uint dwMemoryLoad;
-            public readonly ulong ullTotalPhys;
-            public readonly ulong ullAvailPhys;
-            public readonly ulong ullTotalPageFile;
-            public readonly ulong ullAvailPageFile;
-            public readonly ulong ullTotalVirtual;
-            public readonly ulong ullAvailVirtual;
-            public readonly ulong ullAvailExtendedVirtual;
-
-            /// <summary>
-            /// Initializes a new instance of the <see cref="MEMORYSTATUSEX"/> struct.
-            /// </summary>
-            public void Init()
-            {
-                dwLength = (uint) Marshal.SizeOf(typeof(MEMORYSTATUSEX));
-            }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Shell.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Shell.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Shell.cs
new file mode 100644
index 0000000..e48c8fe
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Shell.cs
@@ -0,0 +1,63 @@
+/*
+ * 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
+{
+    using System.Diagnostics;
+
+    /// <summary>
+    /// Shell utils (cmd/bash).
+    /// </summary>
+    internal static class Shell
+    {
+        /// <summary>
+        /// Executes Bash command.
+        /// </summary>
+        public static string BashExecute(string args)
+        {
+            return Execute("/bin/bash", args);
+        }
+
+        /// <summary>
+        /// Executes the command.
+        /// </summary>
+        private static string Execute(string file, string args)
+        {
+            var escapedArgs = args.Replace("\"", "\\\"");
+
+            var process = new Process
+            {
+                StartInfo = new ProcessStartInfo
+                {
+                    FileName = file,
+                    Arguments = string.Format("-c \"{0}\"", escapedArgs),
+                    RedirectStandardOutput = true,
+                    UseShellExecute = false,
+                    CreateNoWindow = true
+                }
+            };
+
+            process.Start();
+
+            var res = process.StandardOutput.ReadToEnd();
+            process.WaitForExit();
+
+            return res;
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/DllLoader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/DllLoader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/DllLoader.cs
new file mode 100644
index 0000000..61de8e4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/DllLoader.cs
@@ -0,0 +1,176 @@
+/*
+ * 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.ComponentModel;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// Dynamically loads unmanaged DLLs with respect to current platform.
+    /// </summary>
+    internal static class DllLoader
+    {
+        /** Lazy symbol binding. */
+        private const int RtldLazy = 1;
+
+        /** Global symbol access. */
+        private const int RtldGlobal = 8;
+
+        /// <summary>
+        /// ERROR_BAD_EXE_FORMAT constant.
+        /// </summary>
+        // ReSharper disable once InconsistentNaming
+        private const int ERROR_BAD_EXE_FORMAT = 193;
+
+        /// <summary>
+        /// ERROR_MOD_NOT_FOUND constant.
+        /// </summary>
+        // ReSharper disable once InconsistentNaming
+        private const int ERROR_MOD_NOT_FOUND = 126;
+
+        /// <summary>
+        /// Loads specified DLL.
+        /// </summary>
+        /// <returns>Null when successful; error message otherwise.</returns>
+        public static string Load(string dllPath)
+        {
+            if (Os.IsWindows)
+            {
+                return NativeMethodsWindows.LoadLibrary(dllPath) == IntPtr.Zero 
+                    ? FormatWin32Error(Marshal.GetLastWin32Error()) ?? "Unknown error"
+                    : null;
+            }
+
+            if (Os.IsLinux)
+            {
+                if (Os.IsMono)
+                {
+                    return NativeMethodsMono.dlopen(dllPath, RtldGlobal | RtldLazy) == IntPtr.Zero
+                        ? GetErrorText(NativeMethodsMono.dlerror())
+                        : null;
+                }
+
+                if (Os.IsNetCore)
+                {
+                    return NativeMethodsCore.dlopen(dllPath, RtldGlobal | RtldLazy) == IntPtr.Zero
+                        ? GetErrorText(NativeMethodsCore.dlerror())
+                        : null;
+                }
+
+                return NativeMethodsLinux.dlopen(dllPath, RtldGlobal | RtldLazy) == IntPtr.Zero
+                    ? GetErrorText(NativeMethodsLinux.dlerror())
+                    : null;
+            }
+
+            throw new InvalidOperationException("Unsupported OS: " + Environment.OSVersion);
+        }
+
+        /// <summary>
+        /// Gets the error text.
+        /// </summary>
+        private static string GetErrorText(IntPtr charPtr)
+        {
+            return Marshal.PtrToStringAnsi(charPtr) ?? "Unknown error";
+        }
+
+        /// <summary>
+        /// Formats the Win32 error.
+        /// </summary>
+        [ExcludeFromCodeCoverage]
+        private static string FormatWin32Error(int errorCode)
+        {
+            if (errorCode == ERROR_BAD_EXE_FORMAT)
+            {
+                var mode = Environment.Is64BitProcess ? "x64" : "x86";
+
+                return string.Format("DLL could not be loaded (193: ERROR_BAD_EXE_FORMAT). " +
+                                     "This is often caused by x64/x86 mismatch. " +
+                                     "Current process runs in {0} mode, and DLL is not {0}.", mode);
+            }
+
+            if (errorCode == ERROR_MOD_NOT_FOUND)
+            {
+                return "DLL could not be loaded (126: ERROR_MOD_NOT_FOUND). " +
+                       "This can be caused by missing dependencies. ";
+            }
+
+            return string.Format("{0}: {1}", errorCode, new Win32Exception(errorCode).Message);
+        }
+
+        /// <summary>
+        /// Windows.
+        /// </summary>
+        private static class NativeMethodsWindows
+        {
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr LoadLibrary(string filename);
+        }
+
+        /// <summary>
+        /// Linux.
+        /// </summary>
+        private static class NativeMethodsLinux
+        {
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("libdl.so", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlopen(string filename, int flags);
+
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("libdl.so", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlerror();
+        }
+
+        /// <summary>
+        /// libdl.so depends on libc6-dev on Linux, use Mono instead.
+        /// </summary>
+        private static class NativeMethodsMono
+        {
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("__Internal", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlopen(string filename, int flags);
+
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("__Internal", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlerror();
+        }
+
+        /// <summary>
+        /// libdl.so depends on libc6-dev on Linux, use libcoreclr instead.
+        /// </summary>
+        private static class NativeMethodsCore
+        {
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("libcoreclr.so", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlopen(string filename, int flags);
+
+            [SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+            [DllImport("libcoreclr.so", SetLastError = true, CharSet = CharSet.Ansi, BestFitMapping = false,
+                ThrowOnUnmappableChar = true)]
+            internal static extern IntPtr dlerror();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
----------------------------------------------------------------------
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
index da790d7..93b5e69 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
@@ -460,13 +460,18 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
         /// </summary>
         private void ExceptionCheck()
         {
-            if (!_exceptionCheck(_envPtr))
+            var res = _exceptionCheck(_envPtr);
+            if (res == 0)
             {
                 return;
             }
 
             var err = _exceptionOccurred(_envPtr);
-            Debug.Assert(err != IntPtr.Zero);
+
+            if (err == IntPtr.Zero)
+            {
+                throw new IgniteException("Inconsistent JNI ExceptionCheck status.");
+            }
 
             _exceptionClear(_envPtr);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed1ff82a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
----------------------------------------------------------------------
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
index a2ad499..664ef6e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
@@ -63,7 +63,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
         internal delegate void ExceptionClear(IntPtr env);
 
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
-        internal delegate bool ExceptionCheck(IntPtr env);
+        internal delegate byte ExceptionCheck(IntPtr env);
 
         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
         internal delegate IntPtr GetObjectClass(IntPtr env, IntPtr obj);