You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2017/05/29 13:48:51 UTC
[2/2] ignite git commit: IGNITE-2492 .NET: Peer assembly loading
(enabled for Compute)
IGNITE-2492 .NET: Peer assembly loading (enabled for Compute)
This closes #1937
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/69876116
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/69876116
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/69876116
Branch: refs/heads/master
Commit: 69876116dd851d7bfbf0d82e6850654cc57d3d0b
Parents: 42293fa
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon May 29 16:48:37 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon May 29 16:48:37 2017 +0300
----------------------------------------------------------------------
.../Apache.Ignite.Core.Tests.csproj | 9 +
.../Binary/TypeNameParserTest.cs | 8 +-
.../Deployment/GetAddressFunc.cs | 35 ++++
.../PeerAssemblyLoadingAllApisTest.cs | 167 ++++++++++++++++
.../Deployment/PeerAssemblyLoadingTest.cs | 191 +++++++++++++++++++
.../PeerAssemblyLoadingVersioningTest.cs | 164 ++++++++++++++++
.../Deployment/ProcessNameFunc.cs | 50 +++++
.../Deployment/ProcessNameTask.cs | 74 +++++++
.../Deployment/peer_assembly_app.config | 35 ++++
.../IgniteConfigurationSerializerTest.cs | 10 +-
.../Process/IgniteProcess.cs | 12 +-
.../Apache.Ignite.Core.csproj | 9 +
.../Deployment/PeerAssemblyLoadingMode.cs | 55 ++++++
.../Apache.Ignite.Core/IgniteConfiguration.cs | 16 ++
.../IgniteConfigurationSection.xsd | 12 ++
.../dotnet/Apache.Ignite.Core/Ignition.cs | 18 +-
.../Impl/Binary/BinarizableSerializer.cs | 5 +-
.../Binary/BinaryEqualityComparerSerializer.cs | 1 -
.../Impl/Binary/BinaryProcessor.cs | 2 +-
.../Impl/Binary/BinaryReader.cs | 66 ++++---
.../BinaryReflectiveSerializerInternal.cs | 5 +-
.../Impl/Binary/BinarySystemTypeSerializer.cs | 2 +-
.../Impl/Binary/BinaryWriter.cs | 24 +++
.../Impl/Binary/BinaryWriterExtensions.cs | 9 +-
.../Impl/Binary/IBinarySerializerInternal.cs | 10 +-
.../Impl/Binary/Marshaller.cs | 37 +++-
.../Impl/Binary/SerializableSerializer.cs | 14 +-
.../Impl/Binary/TypeResolver.cs | 6 +-
.../Impl/Binary/UserSerializerProxy.cs | 5 +-
.../Common/CopyOnWriteConcurrentDictionary.cs | 8 -
.../Impl/Common/LoadedAssembliesResolver.cs | 8 +-
.../Impl/Compute/Closure/ComputeActionJob.cs | 7 +-
.../Impl/Compute/Closure/ComputeFuncJob.cs | 5 +-
.../Impl/Compute/ComputeFunc.cs | 5 +-
.../Impl/Compute/ComputeImpl.cs | 1 -
.../Impl/Compute/ComputeJob.cs | 3 +-
.../Impl/Compute/ComputeOutFunc.cs | 3 +-
.../Impl/Deployment/AssemblyLoader.cs | 105 ++++++++++
.../Impl/Deployment/AssemblyRequest.cs | 68 +++++++
.../Impl/Deployment/AssemblyRequestResult.cs | 80 ++++++++
.../Impl/Deployment/GetAssemblyFunc.cs | 77 ++++++++
.../Impl/Deployment/PeerAssemblyResolver.cs | 189 ++++++++++++++++++
.../Impl/Deployment/PeerLoadingExtensions.cs | 65 +++++++
.../Impl/Deployment/PeerLoadingObjectHolder.cs | 90 +++++++++
.../PeerLoadingObjectHolderSerializer.cs | 49 +++++
45 files changed, 1716 insertions(+), 98 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 974f858..6d4f34b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -75,6 +75,11 @@
<Compile Include="Binary\BinaryNameMapperTest.cs" />
<Compile Include="Binary\BinaryReaderWriterTest.cs" />
<Compile Include="Binary\BinarySelfTestSimpleName.cs" />
+ <Compile Include="Deployment\GetAddressFunc.cs" />
+ <Compile Include="Deployment\PeerAssemblyLoadingAllApisTest.cs" />
+ <Compile Include="Deployment\PeerAssemblyLoadingVersioningTest.cs" />
+ <Compile Include="Deployment\ProcessNameFunc.cs" />
+ <Compile Include="Deployment\ProcessNameTask.cs" />
<Compile Include="Binary\IO\BinaryStreamsTest.cs" />
<Compile Include="Binary\JavaBinaryInteropTest.cs" />
<Compile Include="Binary\JavaTypeMappingTest.cs" />
@@ -86,6 +91,7 @@
<Compile Include="Binary\Serializable\PrimitivesTest.cs" />
<Compile Include="Binary\Serializable\SqlDmlTest.cs" />
<Compile Include="Binary\TypeNameParserTest.cs" />
+ <Compile Include="Deployment\PeerAssemblyLoadingTest.cs" />
<Compile Include="Binary\TypeResolverTest.cs" />
<Compile Include="Cache\AddArgCacheEntryProcessor.cs" />
<Compile Include="Cache\Affinity\AffinityKeyTest.cs" />
@@ -379,6 +385,9 @@
<ItemGroup>
<None Include="Apache.Ignite.Core.Tests.nunit" />
<None Include="Apache.Ignite.Core.Tests.snk" />
+ <None Include="Deployment\peer_assembly_app.config">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="custom_app.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/TypeNameParserTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/TypeNameParserTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/TypeNameParserTest.cs
index e566a4b..8718d32 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/TypeNameParserTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/TypeNameParserTest.cs
@@ -43,6 +43,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual("x", res.GetName());
Assert.AreEqual(0, res.NameStart);
Assert.AreEqual(0, res.NameEnd);
+ Assert.AreEqual(0, res.FullNameEnd);
Assert.AreEqual(-1, res.AssemblyStart);
Assert.AreEqual(-1, res.AssemblyEnd);
Assert.IsNull(res.Generics);
@@ -52,6 +53,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(7, res.NameStart);
Assert.AreEqual(9, res.NameEnd);
+ Assert.AreEqual(9, res.FullNameEnd);
Assert.IsNull(res.Generics);
Assert.AreEqual(-1, res.AssemblyStart);
@@ -60,6 +62,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(7, res.NameStart);
Assert.AreEqual(9, res.NameEnd);
+ Assert.AreEqual(9, res.FullNameEnd);
Assert.IsNull(res.Generics);
Assert.AreEqual(12, res.AssemblyStart);
@@ -85,7 +88,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual("List`1", res.GetNameWithNamespace());
Assert.AreEqual("Int", res.Generics.Single().GetName());
Assert.AreEqual("Int", res.Generics.Single().GetNameWithNamespace());
-
+
// Simple name array.
res = TypeNameParser.Parse("List`1[[Byte[]]]");
Assert.AreEqual("List`1", res.GetName());
@@ -224,7 +227,7 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckType(typeof(int[,,]));
CheckType(typeof(int[][]));
CheckType(typeof(int[,,,][,,]));
-
+
CheckType(typeof(List<int>[]));
CheckType(typeof(List<int>[,]));
CheckType(typeof(List<int>[][]));
@@ -266,6 +269,7 @@ namespace Apache.Ignite.Core.Tests.Binary
}
Assert.AreEqual(type.FullName.Length + 2, res.AssemblyStart);
+ Assert.AreEqual(type.FullName, res.GetFullName());
}
private class Nested
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/GetAddressFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/GetAddressFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/GetAddressFunc.cs
new file mode 100644
index 0000000..9d08873
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/GetAddressFunc.cs
@@ -0,0 +1,35 @@
+/*
+ * 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.Deployment
+{
+ extern alias ExamplesDll;
+ using Apache.Ignite.Core.Compute;
+ using Address = ExamplesDll::Apache.Ignite.ExamplesDll.Binary.Address;
+
+ /// <summary>
+ /// Function that returns an instance of a class from another assembly.
+ /// </summary>
+ public class GetAddressFunc : IComputeFunc<int, Address>
+ {
+ /** <inheritdoc /> */
+ public Address Invoke(int arg)
+ {
+ return new Address("addr" + arg, arg);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingAllApisTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingAllApisTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingAllApisTest.cs
new file mode 100644
index 0000000..29abda9
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingAllApisTest.cs
@@ -0,0 +1,167 @@
+/*
+ * 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.Deployment
+{
+ extern alias ExamplesDll;
+ using System.Linq;
+ using Apache.Ignite.Core.Tests.Compute;
+ using Apache.Ignite.Core.Tests.Process;
+ using Apache.Ignite.Log4Net;
+ using NUnit.Framework;
+ using Address = ExamplesDll::Apache.Ignite.ExamplesDll.Binary.Address;
+
+ /// <summary>
+ /// Tests all APIs that support peer assembly loading.
+ /// </summary>
+ [Category(TestUtils.CategoryIntensive)]
+ public class PeerAssemblyLoadingAllApisTest
+ {
+ /// <summary>
+ /// Tests Compute.Call.
+ /// </summary>
+ [Test]
+ public void TestComputeCall([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ Assert.AreEqual("Apache.Ignite", async
+ ? remoteCompute.CallAsync(new ProcessNameFunc()).Result
+ : remoteCompute.Call(new ProcessNameFunc()));
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Call.
+ /// </summary>
+ [Test]
+ public void TestComputeAffinityCall([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(ignite =>
+ {
+ var cache = ignite.GetOrCreateCache<int, int>("myCache");
+
+ var key = TestUtils.GetPrimaryKey(ignite, cache.Name, ignite.GetCluster().ForRemotes().GetNode());
+
+ var res = async
+ ? ignite.GetCompute().AffinityCallAsync(cache.Name, key, new ProcessNameFunc()).Result
+ : ignite.GetCompute().AffinityCall(cache.Name, key, new ProcessNameFunc());
+
+ Assert.AreEqual("Apache.Ignite",
+ res);
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Execute.
+ /// </summary>
+ [Test]
+ public void TestComputeExecute([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ // Argument is from different assembly and should be peer deployed as well.
+ var taskArg = new Address("1", 2);
+
+ Assert.AreEqual("Apache.Ignite_Address [street=1, zip=2]", async
+ ? remoteCompute.ExecuteAsync(new ProcessNameTask(), taskArg).Result
+ : remoteCompute.Execute(new ProcessNameTask(), taskArg));
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Broadcast(IComputeAction).
+ /// </summary>
+ [Test]
+ public void TestComputeBroadcastAction([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ if (async)
+ {
+ remoteCompute.BroadcastAsync(new ComputeAction()).Wait();
+ }
+ else
+ {
+ remoteCompute.Broadcast(new ComputeAction());
+ }
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Broadcast(IComputeFunc{T}).
+ /// </summary>
+ [Test]
+ public void TestComputeBroadcastOutFunc([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ var results = async
+ ? remoteCompute.BroadcastAsync(new ProcessNameFunc()).Result
+ : remoteCompute.Broadcast(new ProcessNameFunc());
+
+ Assert.AreEqual("Apache.Ignite", results.Single());
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Broadcast(IComputeFunc{TArg, TRes}).
+ /// </summary>
+ [Test]
+ public void TestComputeBroadcastFunc([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ // Argument requires additional assembly.
+ var taskArg = new IgniteLog4NetLogger();
+
+ var results = async
+ ? remoteCompute.BroadcastAsync(new ProcessNameArgFunc(), taskArg).Result
+ : remoteCompute.Broadcast(new ProcessNameArgFunc(), taskArg);
+
+ Assert.AreEqual("Apache.IgniteApache.Ignite.Log4Net.IgniteLog4NetLogger", results.Single());
+ });
+ }
+
+ /// <summary>
+ /// Tests Compute.Apply.
+ /// </summary>
+ [Test]
+ public void TestComputeApply([Values(true, false)] bool async)
+ {
+ PeerAssemblyLoadingTest.TestDeployment(remoteCompute =>
+ {
+ // Argument is from different assembly and should be peer deployed as well.
+ var taskArg = new Address("1", 2);
+
+ Assert.AreEqual("Apache.IgniteAddress [street=1, zip=2]", async
+ ? remoteCompute.ApplyAsync(new ProcessNameArgFunc(), taskArg).Result
+ : remoteCompute.Apply(new ProcessNameArgFunc(), taskArg));
+ });
+ }
+
+ /// <summary>
+ /// Tears down the test.
+ /// </summary>
+ [TearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ IgniteProcess.KillAll();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
new file mode 100644
index 0000000..c74375d
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingTest.cs
@@ -0,0 +1,191 @@
+/*
+ * 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.Deployment
+{
+ extern alias ExamplesDll;
+ using System;
+ using System.IO;
+ using System.Threading;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Compute;
+ using Apache.Ignite.Core.Deployment;
+ using Apache.Ignite.Core.Impl;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Tests.Process;
+ using Apache.Ignite.Log4Net;
+ using NUnit.Framework;
+ using Address = ExamplesDll::Apache.Ignite.ExamplesDll.Binary.Address;
+
+ /// <summary>
+ /// Tests peer assembly loading feature:
+ /// when user-defined type is not found within loaded assemblies on remote node,
+ /// corresponding assembly is sent and loaded automatically.
+ /// </summary>
+ public class PeerAssemblyLoadingTest
+ {
+ /// <summary>
+ /// Tests that peer loading does not happen when not enabled in config, and error message is informative.
+ /// </summary>
+ [Test]
+ public void TestDisabledPeerLoading()
+ {
+ TestDeployment(remoteCompute =>
+ {
+ var ex = Assert.Throws<IgniteException>(() => remoteCompute.Call(new ProcessNameFunc()));
+
+ Assert.AreEqual("Compute job has failed on remote node, examine InnerException for details.",
+ ex.Message);
+
+ Assert.IsNotNull(ex.InnerException);
+ Assert.AreEqual("Failed to deserialize the job [errType=BinaryObjectException, errMsg=No matching " +
+ "type found for object", ex.InnerException.Message.Substring(0, 102));
+ }, false);
+ }
+
+ /// <summary>
+ /// Tests single assembly deployment (basic test).
+ /// </summary>
+ [Test]
+ public void TestSingleAssembly()
+ {
+ TestDeployment(remoteCompute =>
+ {
+ Assert.AreEqual("Apache.Ignite", remoteCompute.Call(new ProcessNameFunc()));
+ });
+ }
+
+ /// <summary>
+ /// Tests that a type which requires multiple assemblies can be peer deployed.
+ /// </summary>
+ [Test]
+ public void TestMultipleAssemblies()
+ {
+ TestDeployment(remoteCompute =>
+ {
+ // GetAddressFunc requires Tests and Examples assemblies.
+ var result = remoteCompute.Apply(new GetAddressFunc(), 3);
+
+ Assert.IsNotNull(result);
+
+ Assert.AreEqual(3, result.Zip);
+ Assert.AreEqual("addr3", result.Street);
+ });
+ }
+
+ /// <summary>
+ /// Tests that a type which requires multiple assemblies can be peer deployed.
+ /// </summary>
+ [Test]
+ public void TestMultipleAssembliesIndirectDependency()
+ {
+ TestDeployment(remoteCompute =>
+ {
+ // Arg is object, but value is from Examples assembly.
+ Assert.AreEqual("Apache.IgniteAddress [street=Central, zip=2]", remoteCompute.Call(
+ new ProcessNameFunc {Arg = new Address("Central", 2)}));
+ });
+ }
+
+ /// <summary>
+ /// Tests that a type which requires multiple assemblies can be peer deployed.
+ /// </summary>
+ [Test]
+ public void TestMultipleAssembliesIndirectDependencyMultiLevel()
+ {
+ TestDeployment(remoteCompute =>
+ {
+ // Arg is object, value is from Apache.Ignite.Log4Net, and it further depends on log4net.
+ Assert.AreEqual("Apache.IgniteApache.Ignite.Log4Net.IgniteLog4NetLogger", remoteCompute.Call(
+ new ProcessNameFunc {Arg = new IgniteLog4NetLogger()}));
+ });
+ }
+
+ /// <summary>
+ /// Tests the peer deployment.
+ /// </summary>
+ public static void TestDeployment(Action<ICompute> test, bool enablePeerDeployment = true)
+ {
+ TestDeployment((IClusterGroup remoteCluster) => test(remoteCluster.GetCompute()), enablePeerDeployment);
+ }
+
+ /// <summary>
+ /// Tests the peer deployment.
+ /// </summary>
+ private static void TestDeployment(Action<IClusterGroup> test, bool enablePeerDeployment = true)
+ {
+ TestDeployment(ignite => test(ignite.GetCluster().ForRemotes()), enablePeerDeployment);
+ }
+
+ /// <summary>
+ /// Tests the peer deployment.
+ /// </summary>
+ public static void TestDeployment(Action<IIgnite> test, bool enablePeerDeployment = true)
+ {
+ // Copy Apache.Ignite.exe and Apache.Ignite.Core.dll
+ // to a separate folder so that it does not locate our assembly automatically.
+ var folder = IgniteUtils.GetTempDirectoryName();
+ foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly})
+ {
+ Assert.IsNotNull(asm.Location);
+ File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
+ }
+
+ var exePath = Path.Combine(folder, "Apache.Ignite.exe");
+
+ // Start separate Ignite process without loading current dll.
+ // ReSharper disable once AssignNullToNotNullAttribute
+ var config = Path.Combine(Path.GetDirectoryName(typeof(PeerAssemblyLoadingTest).Assembly.Location),
+ "Deployment\\peer_assembly_app.config");
+
+ var proc = IgniteProcess.Start(exePath, IgniteHome.Resolve(null), null,
+ "-ConfigFileName=" + config, "-ConfigSectionName=igniteConfiguration");
+
+ Thread.Sleep(300);
+ Assert.IsFalse(proc.HasExited);
+
+ // Start Ignite and execute computation on remote node.
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ PeerAssemblyLoadingMode = enablePeerDeployment
+ ? PeerAssemblyLoadingMode.CurrentAppDomain
+ : PeerAssemblyLoadingMode.Disabled
+ };
+
+ using (var ignite = Ignition.Start(cfg))
+ {
+ Assert.IsTrue(ignite.WaitTopology(2));
+
+ for (var i = 0; i < 10; i++)
+ {
+ test(ignite);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Tears down the test.
+ /// </summary>
+ [TearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ IgniteProcess.KillAll();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingVersioningTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingVersioningTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingVersioningTest.cs
new file mode 100644
index 0000000..a6fe76e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/PeerAssemblyLoadingVersioningTest.cs
@@ -0,0 +1,164 @@
+/*
+ * 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.Deployment
+{
+ using System;
+ using System.CodeDom.Compiler;
+ using System.Diagnostics;
+ using System.IO;
+ using Apache.Ignite.Core.Deployment;
+ using Apache.Ignite.Core.Discovery.Tcp;
+ using Apache.Ignite.Core.Discovery.Tcp.Static;
+ using Apache.Ignite.Core.Impl;
+ using Apache.Ignite.Core.Tests.Process;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests assembly versioning: multiple assemblies with same name but different version should be supported.
+ /// </summary>
+ public class PeerAssemblyLoadingVersioningTest
+ {
+ private static readonly string TempDir = IgniteUtils.GetTempDirectoryName();
+
+ /// <summary>
+ /// Sets up the test.
+ /// </summary>
+ [SetUp]
+ public void SetUp()
+ {
+ // Copy referenced assemblies.
+ foreach (var type in new[] { typeof(Ignition), GetType() })
+ {
+ var loc = type.Assembly.Location;
+ Assert.IsNotNull(loc);
+ File.Copy(loc, Path.Combine(TempDir, type.Assembly.GetName().Name + ".dll"));
+ }
+ }
+
+ /// <summary>
+ /// Tears down the test.
+ /// </summary>
+ [TearDown]
+ public void TearDown()
+ {
+ Directory.Delete(TempDir, true);
+ }
+
+ /// <summary>
+ /// Tests that multiple versions of same assembly can be used on remote nodes.
+ /// </summary>
+ [Test]
+ public void TestMultipleVersionsOfSameAssembly()
+ {
+ using (Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ PeerAssemblyLoadingMode = PeerAssemblyLoadingMode.CurrentAppDomain,
+ IgniteInstanceName = "peerDeployTest",
+ DiscoverySpi = new TcpDiscoverySpi
+ {
+ IpFinder = new TcpDiscoveryStaticIpFinder {Endpoints = new[] {"127.0.0.1:47500..47502"}},
+ SocketTimeout = TimeSpan.FromSeconds(0.3)
+ }
+ }))
+ {
+ RunClientProcess(CompileClientNode(Path.Combine(TempDir, "PeerTest.exe"), "1.0.1.0"));
+ RunClientProcess(CompileClientNode(Path.Combine(TempDir, "PeerTest.exe"), "1.0.2.0"));
+ }
+ }
+
+ /// <summary>
+ /// Runs the client process.
+ /// </summary>
+ private static void RunClientProcess(string exePath)
+ {
+ var procStart = new ProcessStartInfo
+ {
+ FileName = exePath,
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ };
+
+ var proc = Process.Start(procStart);
+ Assert.IsNotNull(proc);
+
+ IgniteProcess.AttachProcessConsoleReader(proc);
+
+ Assert.IsTrue(proc.WaitForExit(30000));
+ Assert.AreEqual(0, proc.ExitCode);
+
+ File.Delete(exePath);
+ }
+
+ /// <summary>
+ /// Compiles the client node.
+ /// </summary>
+ private string CompileClientNode(string exePath, string version)
+ {
+ var parameters = new CompilerParameters
+ {
+ GenerateExecutable = true,
+ OutputAssembly = exePath,
+ ReferencedAssemblies =
+ {
+ typeof(Ignition).Assembly.Location,
+ GetType().Assembly.Location,
+ "System.dll"
+ }
+ };
+
+ var src = @"
+using System;
+using System.Reflection;
+
+using Apache.Ignite.Core;
+using Apache.Ignite.Core.Deployment;
+using Apache.Ignite.Core.Compute;
+using Apache.Ignite.Core.Tests;
+using Apache.Ignite.Core.Discovery;
+using Apache.Ignite.Core.Discovery.Tcp;
+using Apache.Ignite.Core.Discovery.Tcp.Static;
+
+[assembly: AssemblyVersion(""" + version + @""")]
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ using (var ignite = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration(false)) {ClientMode = true, PeerAssemblyLoadingMode = PeerAssemblyLoadingMode.CurrentAppDomain,
+ DiscoverySpi = new TcpDiscoverySpi { IpFinder = new TcpDiscoveryStaticIpFinder { Endpoints = new[] { ""127.0.0.1:47500..47502"" } }, SocketTimeout = TimeSpan.FromSeconds(0.3) }
+}))
+ {
+ var res = ignite.GetCompute().Call(new GridNameFunc());
+ if (res != ""peerDeployTest_" + version + @""") throw new Exception(""fail: "" + res);
+ }
+ }
+}
+
+public class GridNameFunc : IComputeFunc<string> { public string Invoke() { return Ignition.GetIgnite().Name + ""_"" + GetType().Assembly.GetName().Version; } }
+";
+
+ var results = CodeDomProvider.CreateProvider("CSharp").CompileAssemblyFromSource(parameters, src);
+
+ Assert.IsEmpty(results.Errors);
+
+ return exePath;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameFunc.cs
new file mode 100644
index 0000000..846e11a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameFunc.cs
@@ -0,0 +1,50 @@
+/*
+ * 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.Deployment
+{
+ using Apache.Ignite.Core.Compute;
+
+ /// <summary>
+ /// Function that returns parent process name.
+ /// </summary>
+ public class ProcessNameFunc : IComputeFunc<string>
+ {
+ /// <summary>
+ /// Gets or sets the argument.
+ /// </summary>
+ public object Arg { get; set; }
+
+ /** <inheritdoc /> */
+ public string Invoke()
+ {
+ return System.Diagnostics.Process.GetCurrentProcess().ProcessName + Arg;
+ }
+ }
+
+ /// <summary>
+ /// Function that returns parent process name.
+ /// </summary>
+ public class ProcessNameArgFunc : IComputeFunc<object, string>
+ {
+ /** <inheritdoc /> */
+ public string Invoke(object arg)
+ {
+ return System.Diagnostics.Process.GetCurrentProcess().ProcessName + arg;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameTask.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameTask.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameTask.cs
new file mode 100644
index 0000000..528ad6f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/ProcessNameTask.cs
@@ -0,0 +1,74 @@
+/*
+ * 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.Deployment
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Compute;
+
+ /// <summary>
+ /// Task that returns process name.
+ /// </summary>
+ public class ProcessNameTask : IComputeTask<object, string, string>
+ {
+ /** <inheritdoc /> */
+ public IDictionary<IComputeJob<string>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg)
+ {
+ return subgrid.ToDictionary(x => (IComputeJob<string>) new ProcessNameJob {Arg = arg}, x => x);
+ }
+
+ /** <inheritdoc /> */
+ public ComputeJobResultPolicy OnResult(IComputeJobResult<string> res, IList<IComputeJobResult<string>> rcvd)
+ {
+ return ComputeJobResultPolicy.Reduce;
+ }
+
+ /** <inheritdoc /> */
+ public string Reduce(IList<IComputeJobResult<string>> results)
+ {
+ var ex = results.Select(x => x.Exception).FirstOrDefault(x => x != null);
+
+ if (ex != null)
+ throw new IgniteException("Task failed", ex);
+
+ return results.Select(x => x.Data).FirstOrDefault();
+ }
+
+ /// <summary>
+ /// Job.
+ /// </summary>
+ private class ProcessNameJob : IComputeJob<string>
+ {
+ public object Arg { get; set; }
+
+ /** <inheritdoc /> */
+ public string Execute()
+ {
+ return System.Diagnostics.Process.GetCurrentProcess().ProcessName + "_" + Arg;
+ }
+
+ /** <inheritdoc /> */
+ public void Cancel()
+ {
+ // No-op.
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/peer_assembly_app.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/peer_assembly_app.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/peer_assembly_app.config
new file mode 100644
index 0000000..4cb1d6c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Deployment/peer_assembly_app.config
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ 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.
+-->
+
+<configuration>
+ <configSections>
+ <section name="igniteConfiguration" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ </configSections>
+
+ <igniteConfiguration xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ localhost="127.0.0.1" peerAssemblyLoadingMode="CurrentAppDomain">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+ </igniteConfiguration>
+</configuration>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
index 5bbf722..a90eae5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -41,6 +41,7 @@ namespace Apache.Ignite.Core.Tests
using Apache.Ignite.Core.Common;
using Apache.Ignite.Core.Communication.Tcp;
using Apache.Ignite.Core.DataStructures.Configuration;
+ using Apache.Ignite.Core.Deployment;
using Apache.Ignite.Core.Discovery.Tcp;
using Apache.Ignite.Core.Discovery.Tcp.Multicast;
using Apache.Ignite.Core.Events;
@@ -65,7 +66,7 @@ namespace Apache.Ignite.Core.Tests
[Test]
public void TestPredefinedXml()
{
- var xml = @"<igniteConfig workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10' isDaemon='true' isLateAffinityAssignment='false' springConfigUrl='c:\myconfig.xml' autoGenerateIgniteInstanceName='true'>
+ var xml = @"<igniteConfig workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10' isDaemon='true' isLateAffinityAssignment='false' springConfigUrl='c:\myconfig.xml' autoGenerateIgniteInstanceName='true' peerAssemblyLoadingMode='CurrentAppDomain'>
<localhost>127.1.1.1</localhost>
<binaryConfiguration compactFooter='false' keepDeserialized='true'>
<nameMapper type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+NameMapper' bar='testBar' />
@@ -92,7 +93,7 @@ namespace Apache.Ignite.Core.Tests
<cacheConfiguration>
<cacheConfiguration cacheMode='Replicated' readThrough='true' writeThrough='true' enableStatistics='true' writeBehindCoalescing='false' partitionLossPolicy='ReadWriteAll'>
<queryEntities>
- <queryEntity keyType='System.Int32' valueType='System.String' tableName='myTable'>
+ <queryEntity keyType='System.Int32' valueType='System.String' tableName='myTable'>
<fields>
<queryField name='length' fieldType='System.Int32' isKeyField='true' />
</fields>
@@ -273,6 +274,8 @@ namespace Apache.Ignite.Core.Tests
Assert.AreEqual(89, memPlc.InitialSize);
Assert.AreEqual(98, memPlc.MaxSize);
Assert.IsTrue(memPlc.MetricsEnabled);
+
+ Assert.AreEqual(PeerAssemblyLoadingMode.CurrentAppDomain, cfg.PeerAssemblyLoadingMode);
}
/// <summary>
@@ -831,7 +834,8 @@ namespace Apache.Ignite.Core.Tests
MetricsEnabled = true
}
}
- }
+ },
+ PeerAssemblyLoadingMode = PeerAssemblyLoadingMode.CurrentAppDomain
};
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/IgniteProcess.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/IgniteProcess.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/IgniteProcess.cs
index 5aec1ac..ee62354 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/IgniteProcess.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/IgniteProcess.cs
@@ -197,12 +197,20 @@ namespace Apache.Ignite.Core.Tests.Process
Debug.Assert(proc != null);
// 3. Attach output readers to avoid hangs.
+ AttachProcessConsoleReader(proc, outReader);
+
+ return proc;
+ }
+
+ /// <summary>
+ /// Attaches the process console reader.
+ /// </summary>
+ public static void AttachProcessConsoleReader(Process proc, IIgniteProcessOutputReader outReader = null)
+ {
outReader = outReader ?? DfltOutReader;
Attach(proc, proc.StandardOutput, outReader, false);
Attach(proc, proc.StandardError, outReader, true);
-
- return proc;
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/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 9ce9dd2..b37b685 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -98,6 +98,7 @@
<Compile Include="Cache\Configuration\PartitionLossPolicy.cs" />
<Compile Include="Cache\IMemoryMetrics.cs" />
<Compile Include="Common\ExceptionFactory.cs" />
+ <Compile Include="Deployment\PeerAssemblyLoadingMode.cs" />
<Compile Include="Events\IEventStorageSpi.cs" />
<Compile Include="Events\MemoryEventStorageSpi.cs" />
<Compile Include="Events\NoopEventStorageSpi.cs" />
@@ -111,6 +112,14 @@
<Compile Include="Impl\Binary\BinaryArrayEqualityComparer.cs" />
<Compile Include="Impl\Binary\BinaryProcessor.cs" />
<Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
+ <Compile Include="Impl\Deployment\AssemblyLoader.cs" />
+ <Compile Include="Impl\Deployment\AssemblyRequest.cs" />
+ <Compile Include="Impl\Deployment\AssemblyRequestResult.cs" />
+ <Compile Include="Impl\Deployment\GetAssemblyFunc.cs" />
+ <Compile Include="Impl\Deployment\PeerAssemblyResolver.cs" />
+ <Compile Include="Impl\Deployment\PeerLoadingExtensions.cs" />
+ <Compile Include="Impl\Deployment\PeerLoadingObjectHolder.cs" />
+ <Compile Include="Impl\Deployment\PeerLoadingObjectHolderSerializer.cs" />
<Compile Include="Impl\Binary\IBinarySerializerInternal.cs" />
<Compile Include="Binary\Package-Info.cs" />
<Compile Include="Cache\Affinity\AffinityKey.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Deployment/PeerAssemblyLoadingMode.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Deployment/PeerAssemblyLoadingMode.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Deployment/PeerAssemblyLoadingMode.cs
new file mode 100644
index 0000000..7217e2a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Deployment/PeerAssemblyLoadingMode.cs
@@ -0,0 +1,55 @@
+/*
+ * 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.Deployment
+{
+ using System;
+ using Apache.Ignite.Core.Compute;
+
+ /// <summary>
+ /// Peer assembly loading mode.
+ /// See <see cref="IgniteConfiguration.PeerAssemblyLoadingMode"/>.
+ /// </summary>
+ public enum PeerAssemblyLoadingMode
+ {
+ /// <summary>
+ /// Disabled peer assembly loading. Default mode.
+ /// </summary>
+ Disabled,
+
+ /// <summary>
+ /// Automatically load assemblies from remote nodes into the current <see cref="AppDomain"/>.
+ /// <para />
+ /// .NET does not allow assembly unloading, which means that all peer-loaded assemblies will
+ /// live as long as the current AppDomain lives. This may cause increased memory usage.
+ /// <para />
+ /// Assemblies are distinguished using their fully qualified name. Multiple versions of the same assembly can
+ /// be loaded and the correct version will be used (according to Type.AssemblyQualifiedName).
+ /// So in case when a new version of some type needs to be executed on remote nodes,
+ /// corresponding assembly version should be bumped up. If assembly is recompiled without version increment,
+ /// it is considered the same as before and won't be updated.
+ /// <para />
+ /// Assemblies are requested from remote nodes on demand.
+ /// For example, <see cref="IComputeFunc{TRes}"/> is sent to all nodes
+ /// via <see cref="ICompute.Broadcast{TRes}"/>. Each node then deserializes the instance and,
+ /// if containing assembly is not present, requests it from originating node (which did the
+ /// <see cref="ICompute.Broadcast{TRes}"/> call), if it is alive, or from any other node in cluster.
+ /// Therefore it is possible that eventually all nodes in cluster will have this assebly loaded.
+ /// </summary>
+ CurrentAppDomain
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/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 2a6f5f7..8fab8a4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -33,7 +33,9 @@ namespace Apache.Ignite.Core
using Apache.Ignite.Core.Common;
using Apache.Ignite.Core.Communication;
using Apache.Ignite.Core.Communication.Tcp;
+ using Apache.Ignite.Core.Compute;
using Apache.Ignite.Core.DataStructures.Configuration;
+ using Apache.Ignite.Core.Deployment;
using Apache.Ignite.Core.Discovery;
using Apache.Ignite.Core.Discovery.Tcp;
using Apache.Ignite.Core.Events;
@@ -979,5 +981,19 @@ namespace Apache.Ignite.Core
/// <see cref="MemoryConfiguration"/> for more details.
/// </summary>
public MemoryConfiguration MemoryConfiguration { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating how user assemblies should be loaded on remote nodes.
+ /// <para />
+ /// For example, when executing <see cref="ICompute.Call{TRes}(IComputeFunc{TRes})"/>,
+ /// the assembly with corresponding <see cref="IComputeFunc{TRes}"/> should be loaded on remote nodes.
+ /// With this option enabled, Ignite will attempt to send the assembly to remote nodes
+ /// and load it there automatically.
+ /// <para />
+ /// Default is <see cref="Apache.Ignite.Core.Deployment.PeerAssemblyLoadingMode.Disabled"/>.
+ /// <para />
+ /// Peer loading is enabled for <see cref="ICompute"/> functionality.
+ /// </summary>
+ public PeerAssemblyLoadingMode PeerAssemblyLoadingMode { get; set; }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index ad92661..bdfa8db 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -96,6 +96,13 @@
</xs:restriction>
</xs:simpleType>
+ <xs:simpleType name="peerAssemblyLoadingMode" final="restriction">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Disabled" />
+ <xs:enumeration value="CurrentAppDomain" />
+ </xs:restriction>
+ </xs:simpleType>
+
<xs:element name="igniteConfiguration">
<xs:annotation>
<xs:documentation>Ignite configuration root.</xs:documentation>
@@ -1411,6 +1418,11 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="peerAssemblyLoadingMode" type="peerAssemblyLoadingMode">
+ <xs:annotation>
+ <xs:documentation>Indicates whether user assemblies should be loaded on remote nodes automatically.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index fdddbb7..c5d056d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -84,7 +84,6 @@ namespace Apache.Ignite.Core
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
static Ignition()
{
- AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
}
@@ -124,7 +123,7 @@ namespace Apache.Ignite.Core
}
/// <summary>
- /// Reads <see cref="IgniteConfiguration"/> from application configuration
+ /// Reads <see cref="IgniteConfiguration"/> from application configuration
/// <see cref="IgniteConfigurationSection"/> with <see cref="ConfigurationSectionName"/>
/// name and starts Ignite.
/// </summary>
@@ -284,7 +283,7 @@ namespace Apache.Ignite.Core
if (_startup.Error != null)
{
// Wrap in a new exception to preserve original stack trace.
- throw new IgniteException("Failed to start Ignite.NET, check inner exception for details",
+ throw new IgniteException("Failed to start Ignite.NET, check inner exception for details",
_startup.Error);
}
@@ -722,18 +721,7 @@ namespace Apache.Ignite.Core
GC.Collect();
}
-
- /// <summary>
- /// Handles the AssemblyResolve event of the CurrentDomain control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="args">The <see cref="ResolveEventArgs"/> instance containing the event data.</param>
- /// <returns>Manually resolved assembly, or null.</returns>
- private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
- {
- return LoadedAssembliesResolver.Instance.GetAssembly(args.Name);
- }
-
+
/// <summary>
/// Handles the DomainUnload event of the CurrentDomain control.
/// </summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
index 2273a93..a211360 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
@@ -17,6 +17,7 @@
namespace Apache.Ignite.Core.Impl.Binary
{
+ using System;
using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
@@ -38,9 +39,9 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
{
- var obj = (T) FormatterServices.GetUninitializedObject(desc.Type);
+ var obj = (T) FormatterServices.GetUninitializedObject(typeOverride ?? desc.Type);
reader.AddHandle(pos, obj);
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs
deleted file mode 100644
index 5f28270..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEqualityComparerSerializer.cs
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
index f48bcc0..b8937c9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
@@ -232,7 +232,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Gets the type by id.
+ /// Gets the type name by id.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Type or null.</returns>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index 73a0456..e38085c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -522,13 +522,17 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Deserialize object.
/// </summary>
+ /// <param name="typeOverride">The type override.
+ /// There can be multiple versions of the same type when peer assembly loading is enabled.
+ /// Only first one is registered in Marshaller.
+ /// This parameter specifies exact type to be instantiated.</param>
/// <returns>Deserialized object.</returns>
- public T Deserialize<T>()
+ public T Deserialize<T>(Type typeOverride = null)
{
T res;
// ReSharper disable once CompareNonConstrainedGenericWithNull
- if (!TryDeserialize(out res) && default(T) != null)
+ if (!TryDeserialize(out res, typeOverride) && default(T) != null)
throw new BinaryObjectException(string.Format("Invalid data on deserialization. " +
"Expected: '{0}' But was: null", typeof (T)));
@@ -538,8 +542,15 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Deserialize object.
/// </summary>
- /// <returns>Deserialized object.</returns>
- public bool TryDeserialize<T>(out T res)
+ /// <param name="res">Deserialized object.</param>
+ /// <param name="typeOverride">The type override.
+ /// There can be multiple versions of the same type when peer assembly loading is enabled.
+ /// Only first one is registered in Marshaller.
+ /// This parameter specifies exact type to be instantiated.</param>
+ /// <returns>
+ /// Deserialized object.
+ /// </returns>
+ public bool TryDeserialize<T>(out T res, Type typeOverride = null)
{
int pos = Stream.Position;
@@ -557,12 +568,12 @@ namespace Apache.Ignite.Core.Impl.Binary
return false;
case BinaryUtils.HdrHnd:
- res = ReadHandleObject<T>(pos);
+ res = ReadHandleObject<T>(pos, typeOverride);
return true;
case BinaryUtils.HdrFull:
- res = ReadFullObject<T>(pos);
+ res = ReadFullObject<T>(pos, typeOverride);
return true;
@@ -583,7 +594,7 @@ namespace Apache.Ignite.Core.Impl.Binary
throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']');
}
-
+
/// <summary>
/// Gets the flag indicating that there is custom type information in raw region.
/// </summary>
@@ -657,8 +668,14 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Reads the full object.
/// </summary>
+ /// <param name="pos">The position.</param>
+ /// <param name="typeOverride">The type override.
+ /// There can be multiple versions of the same type when peer assembly loading is enabled.
+ /// Only first one is registered in Marshaller.
+ /// This parameter specifies exact type to be instantiated.</param>
+ /// <returns>Resulting object</returns>
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "hashCode")]
- private T ReadFullObject<T>(int pos)
+ private T ReadFullObject<T>(int pos, Type typeOverride)
{
var hdr = BinaryObjectHeader.Read(Stream, pos);
@@ -696,24 +713,17 @@ namespace Apache.Ignite.Core.Impl.Binary
{
// Find descriptor.
var desc = hdr.TypeId == BinaryUtils.TypeUnregistered
- ? _marsh.GetDescriptor(Type.GetType(ReadString(), true))
- : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true);
+ ? _marsh.GetDescriptor(ReadUnregisteredType(typeOverride))
+ : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true, null, typeOverride);
// Instantiate object.
if (desc.Type == null)
{
- if (desc is BinarySurrogateTypeDescriptor)
- {
- throw new BinaryObjectException(string.Format(
- "Unknown type ID: {0}. " +
- "This usually indicates missing BinaryConfiguration. " +
- "Make sure that all nodes have the same BinaryConfiguration.", hdr.TypeId));
- }
-
throw new BinaryObjectException(string.Format(
"No matching type found for object [typeId={0}, typeName={1}]. " +
"This usually indicates that assembly with specified type is not loaded on a node. " +
- "When using Apache.Ignite.exe, make sure to load assemblies with -assembly parameter.",
+ "When using Apache.Ignite.exe, make sure to load assemblies with -assembly parameter. " +
+ "Alternatively, set IgniteConfiguration.PeerAssemblyLoadingEnabled to true.",
desc.TypeId, desc.TypeName));
}
@@ -728,7 +738,7 @@ namespace Apache.Ignite.Core.Impl.Binary
_frame.Raw = false;
// Read object.
- var obj = desc.Serializer.ReadBinary<T>(this, desc, pos);
+ var obj = desc.Serializer.ReadBinary<T>(this, desc, pos, typeOverride);
_frame.Struct.UpdateReaderStructure();
@@ -746,6 +756,16 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Reads the unregistered type.
+ /// </summary>
+ private Type ReadUnregisteredType(Type knownType)
+ {
+ var typeName = ReadString(); // Must read always.
+
+ return knownType ?? Type.GetType(typeName, true);
+ }
+
+ /// <summary>
/// Sets the current schema.
/// </summary>
private void SetCurSchema(IBinaryTypeDescriptor desc)
@@ -815,7 +835,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Reads the handle object.
/// </summary>
- private T ReadHandleObject<T>(int pos)
+ private T ReadHandleObject<T>(int pos, Type typeOverride)
{
// Get handle position.
int hndPos = pos - Stream.ReadInt();
@@ -833,7 +853,7 @@ namespace Apache.Ignite.Core.Impl.Binary
// No such handler, i.e. we trying to deserialize inner object before deserializing outer.
Stream.Seek(hndPos, SeekOrigin.Begin);
- hndObj = Deserialize<T>();
+ hndObj = Deserialize<T>(typeOverride);
}
// Notify builder that we deserialized object on other location.
@@ -977,7 +997,7 @@ namespace Apache.Ignite.Core.Impl.Binary
return default(T);
if (hdr == BinaryUtils.HdrHnd)
- return ReadHandleObject<T>(Stream.Position - 1);
+ return ReadHandleObject<T>(Stream.Position - 1, null);
if (expHdr != hdr)
throw new BinaryObjectException(string.Format("Invalid header on deserialization. " +
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
index 69f7132..62c19ef 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
@@ -84,13 +84,14 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos,
+ Type typeOverride)
{
Debug.Assert(_rActions != null);
Debug.Assert(reader != null);
Debug.Assert(desc != null);
- var obj = FormatterServices.GetUninitializedObject(desc.Type);
+ var obj = FormatterServices.GetUninitializedObject(typeOverride ?? desc.Type);
var ctx = GetStreamingContext(reader);
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
index 1ea1f0b..681f57b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
@@ -48,7 +48,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritDoc /> */
- public T1 ReadBinary<T1>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ public T1 ReadBinary<T1>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
{
return TypeCaster<T1>.Cast(_ctor(reader));
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
index a5fed48..da2b371 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
@@ -54,6 +54,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Whether we are currently detaching an object. */
private bool _detaching;
+ /** Whether we are directly within peer loading object holder. */
+ private bool _isInWrapper;
+
/** Schema holder. */
private readonly BinaryObjectSchemaHolder _schema = BinaryObjectSchemaHolder.Current;
@@ -1165,6 +1168,22 @@ namespace Apache.Ignite.Core.Impl.Binary
return;
}
+ // Wrap objects as required.
+ if (WrapperFunc != null && type != WrapperFunc.Method.ReturnType)
+ {
+ if (_isInWrapper)
+ {
+ _isInWrapper = false;
+ }
+ else
+ {
+ _isInWrapper = true;
+ Write(WrapperFunc(obj));
+
+ return;
+ }
+ }
+
// Suppose that we faced normal object and perform descriptor lookup.
var desc = _marsh.GetDescriptor(type);
@@ -1424,6 +1443,11 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets or sets a function to wrap all serializer objects.
+ /// </summary>
+ internal Func<object, object> WrapperFunc { get; set; }
+
+ /// <summary>
/// Stream.
/// </summary>
internal IBinaryStream Stream
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
index b13a9ea..64bfa35 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
@@ -18,6 +18,7 @@
namespace Apache.Ignite.Core.Impl.Binary
{
using System;
+ using Apache.Ignite.Core.Binary;
/// <summary>
/// Writer extensions.
@@ -27,7 +28,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Writes the nullable boolean.
/// </summary>
- public static void WriteBooleanNullable(this BinaryWriter writer, bool? value)
+ public static void WriteBooleanNullable(this IBinaryRawWriter writer, bool? value)
{
if (value != null)
{
@@ -41,7 +42,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Writes the nullable boolean.
/// </summary>
- public static void WriteIntNullable(this BinaryWriter writer, int? value)
+ public static void WriteIntNullable(this IBinaryRawWriter writer, int? value)
{
if (value != null)
{
@@ -55,7 +56,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Writes the timespan.
/// </summary>
- public static void WriteTimeSpanAsLong(this BinaryWriter writer, TimeSpan value)
+ public static void WriteTimeSpanAsLong(this IBinaryRawWriter writer, TimeSpan value)
{
writer.WriteLong((long) value.TotalMilliseconds);
}
@@ -63,7 +64,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Writes the nullable boolean.
/// </summary>
- public static void WriteTimeSpanAsLongNullable(this BinaryWriter writer, TimeSpan? value)
+ public static void WriteTimeSpanAsLongNullable(this IBinaryRawWriter writer, TimeSpan? value)
{
if (value != null)
{
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
index b775999..42145e5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
@@ -17,6 +17,8 @@
namespace Apache.Ignite.Core.Impl.Binary
{
+ using System;
+
/// <summary>
/// Internal generic serializer interface.
/// </summary>
@@ -25,12 +27,18 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Write binary object.
/// </summary>
+ /// <param name="obj">The object.</param>
+ /// <param name="writer">The writer.</param>
void WriteBinary<T>(T obj, BinaryWriter writer);
/// <summary>
/// Read binary object.
/// </summary>
- T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos);
+ /// <param name="reader">The reader.</param>
+ /// <param name="desc">The descriptor.</param>
+ /// <param name="pos">The position.</param>
+ /// <param name="typeOverride">Type override, can be null.</param>
+ T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride);
/// <summary>
/// Gets a value indicating whether this serializer supports handles.
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index 8f12acf..9634e27 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -33,6 +33,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using Apache.Ignite.Core.Impl.Compute;
using Apache.Ignite.Core.Impl.Compute.Closure;
using Apache.Ignite.Core.Impl.Datastream;
+ using Apache.Ignite.Core.Impl.Deployment;
using Apache.Ignite.Core.Impl.Messaging;
using Apache.Ignite.Core.Log;
@@ -339,7 +340,7 @@ namespace Apache.Ignite.Core.Impl.Binary
IDictionary<int, BinaryTypeHolder> metas0 =
new Dictionary<int, BinaryTypeHolder>(_metas);
- holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName,
+ holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName,
desc.IsEnum, this);
metas0[desc.TypeId] = holder;
@@ -423,11 +424,12 @@ namespace Apache.Ignite.Core.Impl.Binary
/// Only when we really deserialize the value, requiresType is set to true
/// and we attempt to resolve the type by all means.</param>
/// <param name="typeName">Known type name.</param>
+ /// <param name="knownType">Optional known type.</param>
/// <returns>
/// Descriptor.
/// </returns>
- public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId, bool requiresType = false,
- string typeName = null)
+ public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId, bool requiresType = false,
+ string typeName = null, Type knownType = null)
{
BinaryFullTypeDescriptor desc;
@@ -442,18 +444,29 @@ namespace Apache.Ignite.Core.Impl.Binary
if (requiresType && _ignite != null)
{
// Check marshaller context for dynamically registered type.
- typeName = typeName ?? _ignite.BinaryProcessor.GetTypeName(typeId);
+ var type = knownType;
- if (typeName != null)
+ if (type == null && _ignite != null)
{
- var type = new TypeResolver().ResolveType(typeName, nameMapper:
- _cfg.NameMapper ?? GetDefaultNameMapper());
+ typeName = typeName ?? _ignite.BinaryProcessor.GetTypeName(typeId);
- if (type != null)
+ if (typeName != null)
{
- return AddUserType(type, typeId, GetTypeName(type), true, desc);
+ type = new TypeResolver().ResolveType(typeName,
+ nameMapper: _cfg.NameMapper ?? GetDefaultNameMapper());
+
+ if (type == null)
+ {
+ // Type is registered, but assembly is not present.
+ return new BinarySurrogateTypeDescriptor(_cfg, typeId, typeName);
+ }
}
}
+
+ if (type != null)
+ {
+ return AddUserType(type, typeId, GetTypeName(type), true, desc);
+ }
}
var meta = GetBinaryType(typeId);
@@ -593,7 +606,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Gets the serializer.
/// </summary>
- private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg,
+ private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg,
BinaryTypeConfiguration typeCfg, Type type, int typeId, IBinaryNameMapper nameMapper,
IBinaryIdMapper idMapper, ILogger log)
{
@@ -732,6 +745,10 @@ namespace Apache.Ignite.Core.Impl.Binary
AddSystemType(BinaryUtils.TypePlatformJavaObjectFactoryProxy, r => new PlatformJavaObjectFactoryProxy());
AddSystemType(0, r => new ObjectInfoHolder(r));
AddSystemType(BinaryUtils.TypeIgniteUuid, r => new IgniteGuid(r));
+ AddSystemType(0, r => new GetAssemblyFunc());
+ AddSystemType(0, r => new AssemblyRequest(r));
+ AddSystemType(0, r => new AssemblyRequestResult(r));
+ AddSystemType<PeerLoadingObjectHolder>(0, null, serializer: new PeerLoadingObjectHolderSerializer());
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
index 1e4af4b..13310e4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
@@ -87,11 +87,13 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
{
object res;
var ctx = GetStreamingContext(reader);
+ var type = typeOverride ?? desc.Type;
+
// Read additional information from raw part, if flag is set.
IEnumerable<string> fieldNames;
Type customType = null;
@@ -119,7 +121,7 @@ namespace Apache.Ignite.Core.Impl.Binary
if (customType != null)
{
// Custom type is present, which returns original type via IObjectReference.
- var serInfo = ReadSerializationInfo(reader, fieldNames, desc, dotNetFields);
+ var serInfo = ReadSerializationInfo(reader, fieldNames, type, dotNetFields);
res = ReadAsCustomType(customType, serInfo, ctx);
@@ -131,7 +133,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
else
{
- res = FormatterServices.GetUninitializedObject(desc.Type);
+ res = FormatterServices.GetUninitializedObject(type);
_serializableTypeDesc.OnDeserializing(res, ctx);
@@ -140,7 +142,7 @@ namespace Apache.Ignite.Core.Impl.Binary
reader.AddHandle(pos, res);
// Read actual data and call constructor.
- var serInfo = ReadSerializationInfo(reader, fieldNames, desc, dotNetFields);
+ var serInfo = ReadSerializationInfo(reader, fieldNames, type, dotNetFields);
_serializableTypeDesc.SerializationCtorUninitialized(res, serInfo, ctx);
}
@@ -536,9 +538,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/// Reads the serialization information.
/// </summary>
private static SerializationInfo ReadSerializationInfo(BinaryReader reader,
- IEnumerable<string> fieldNames, IBinaryTypeDescriptor desc, ICollection<int> dotNetFields)
+ IEnumerable<string> fieldNames, Type type, ICollection<int> dotNetFields)
{
- var serInfo = new SerializationInfo(desc.Type, new FormatterConverter());
+ var serInfo = new SerializationInfo(type, new FormatterConverter());
if (dotNetFields == null)
{
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/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 fa59d62..6fa7918 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
@@ -68,7 +68,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="typeName">Name of the type.</param>
/// <param name="assemblies">Assemblies to look in.</param>
/// <param name="nameMapper">The name mapper.</param>
- /// <returns>
+ /// <returns>
/// Resolved type.
/// </returns>
private static Type ResolveType(string assemblyName, TypeNameParser typeName, ICollection<Assembly> assemblies,
@@ -144,7 +144,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="assemblies">The assemblies.</param>
/// <param name="nameMapper">The name mapper.</param>
/// <returns>Resolved type, or null.</returns>
- private static Type ResolveNonGenericType(string assemblyName, string typeName,
+ private static Type ResolveNonGenericType(string assemblyName, string typeName,
ICollection<Assembly> assemblies, IBinaryNameMapper nameMapper)
{
// Fully-qualified name can be resolved with system mechanism.
@@ -187,7 +187,7 @@ namespace Apache.Ignite.Core.Impl.Binary
try
{
- var result = ResolveType(assemblyName, typeName, GetNotLoadedReferencedAssemblies().ToArray(),
+ var result = ResolveType(assemblyName, typeName, GetNotLoadedReferencedAssemblies().ToArray(),
nameMapper);
if (result == null)
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
index b0d393d..95762fd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
@@ -17,6 +17,7 @@
namespace Apache.Ignite.Core.Impl.Binary
{
+ using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
@@ -47,9 +48,9 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
{
- var obj = FormatterServices.GetUninitializedObject(desc.Type);
+ var obj = FormatterServices.GetUninitializedObject(typeOverride ?? desc.Type);
reader.AddHandle(pos, obj);
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
index 78cb8b6..cd26af7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
@@ -96,13 +96,5 @@ namespace Apache.Ignite.Core.Impl.Common
{
return _dict.ContainsKey(key);
}
-
- /// <summary>
- /// Gets the values.
- /// </summary>
- public ICollection<TValue> Values
- {
- get { return _dict.Values; }
- }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
index 9628478..06dffb7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
@@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Impl.Common
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
@@ -29,7 +30,8 @@ namespace Apache.Ignite.Core.Impl.Common
internal class LoadedAssembliesResolver
{
// The lazy singleton instance.
- private static readonly Lazy<LoadedAssembliesResolver> LazyInstance = new Lazy<LoadedAssembliesResolver>();
+ private static readonly Lazy<LoadedAssembliesResolver> LazyInstance =
+ new Lazy<LoadedAssembliesResolver>(() => new LoadedAssembliesResolver());
// Assemblies map.
private volatile Dictionary<string, Assembly> _map;
@@ -37,7 +39,7 @@ namespace Apache.Ignite.Core.Impl.Common
/// <summary>
/// Initializes a new instance of the <see cref="LoadedAssembliesResolver"/> class.
/// </summary>
- public LoadedAssembliesResolver()
+ private LoadedAssembliesResolver()
{
lock (this)
{
@@ -89,6 +91,8 @@ namespace Apache.Ignite.Core.Impl.Common
[SuppressMessage("ReSharper", "InconsistentlySynchronizedField")]
public Assembly GetAssembly(string assemblyName)
{
+ Debug.Assert(!string.IsNullOrWhiteSpace(assemblyName));
+
Assembly asm;
return _map.TryGetValue(assemblyName, out asm) ? asm : null;