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);