ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [22/51] ignite git commit: IGNITE-2492 .NET: Peer assembly loading (enabled for Compute)
Date Wed, 31 May 2017 09:23:12 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
index 55332d5..a1f84da 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Compute.Closure
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Compute;
     using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Resource;
 
     /// <summary>
@@ -63,9 +64,9 @@ namespace Apache.Ignite.Core.Impl.Compute.Closure
         /** <inheritDoc /> */
         public void WriteBinary(IBinaryWriter writer)
         {
-            var writer0 = (BinaryWriter)writer.GetRawWriter();
+            var writer0 = (BinaryWriter) writer.GetRawWriter();
 
-            writer0.WithDetach(w => w.WriteObject(_action));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(_action));
         }
 
         /// <summary>
@@ -74,7 +75,7 @@ namespace Apache.Ignite.Core.Impl.Compute.Closure
         /// <param name="reader">The reader.</param>
         public ComputeActionJob(IBinaryRawReader reader)
         {
-            _action = reader.ReadObject<IComputeAction>();
+            _action = (IComputeAction) reader.ReadObject<object>();
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
index 0cd8df2..8350818 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Impl.Compute.Closure
     using System;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Resource;
 
     /// <summary>
@@ -67,8 +68,8 @@ namespace Apache.Ignite.Core.Impl.Compute.Closure
         {
             BinaryWriter writer0 = (BinaryWriter) writer.GetRawWriter();
 
-            writer0.WithDetach(w => w.WriteObject(_clo));
-            writer0.WithDetach(w => w.WriteObject(_arg));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(_clo));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(_arg));
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
index 951e179..4132347 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
@@ -23,6 +23,7 @@ namespace Apache.Ignite.Core.Impl.Compute
     using Apache.Ignite.Core.Compute;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Resource;
     using Apache.Ignite.Core.Resource;
 
@@ -76,9 +77,9 @@ namespace Apache.Ignite.Core.Impl.Compute
         /** <inheritDoc /> */
         public void WriteBinary(IBinaryWriter writer)
         {
-            var writer0 = (BinaryWriter)writer.GetRawWriter();
+            var writer0 = (BinaryWriter) writer.GetRawWriter();
 
-            writer0.WithDetach(w => w.WriteObject(_func));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(_func));
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
index 66e5339..7a028cd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
@@ -35,7 +35,6 @@ namespace Apache.Ignite.Core.Impl.Compute
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Compute.Closure;
     using Apache.Ignite.Core.Impl.Unmanaged;
-    using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
 
     /// <summary>
     /// Compute implementation.

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJob.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJob.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJob.cs
index 4c0b536..56e3708 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJob.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeJob.cs
@@ -23,6 +23,7 @@ namespace Apache.Ignite.Core.Impl.Compute
     using Apache.Ignite.Core.Compute;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Resource;
     using Apache.Ignite.Core.Resource;
 
@@ -108,7 +109,7 @@ namespace Apache.Ignite.Core.Impl.Compute
         {
             var writer0 = (BinaryWriter)writer.GetRawWriter();
 
-            writer0.WithDetach(w => w.WriteObject(Job));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(Job));
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeOutFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeOutFunc.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeOutFunc.cs
index 71934d4..4e5f523 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeOutFunc.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeOutFunc.cs
@@ -24,6 +24,7 @@ namespace Apache.Ignite.Core.Impl.Compute
     using Apache.Ignite.Core.Compute;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Impl.Deployment;
     using Apache.Ignite.Core.Impl.Resource;
     using Apache.Ignite.Core.Resource;
 
@@ -82,7 +83,7 @@ namespace Apache.Ignite.Core.Impl.Compute
         {
             var writer0 = (BinaryWriter)writer.GetRawWriter();
 
-            writer0.WithDetach(w => w.WriteObject(_func));
+            writer0.WithDetach(w => w.WriteWithPeerDeployment(_func));
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyLoader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyLoader.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyLoader.cs
new file mode 100644
index 0000000..47c94e8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyLoader.cs
@@ -0,0 +1,105 @@
+/*
+ * 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.Deployment
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.IO;
+    using System.Reflection;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Handles assembly loading and serialization.
+    /// </summary>
+    internal static class AssemblyLoader
+    {
+        /// <summary>
+        /// Cache of assemblies that are peer-loaded from byte array.
+        /// Keep these byte arrays to be able to send them further, because Location for
such assemblies is empty.
+        /// </summary>
+        private static readonly CopyOnWriteConcurrentDictionary<string, KeyValuePair<Assembly,
byte[]>>
+            InMemoryAssemblies
+                = new CopyOnWriteConcurrentDictionary<string, KeyValuePair<Assembly,
byte[]>>();
+
+        /// <summary>
+        /// Loads the assembly from bytes outside of any context.
+        /// Resulting assembly can only be retrieved with <see cref="GetAssembly"/>
call later.
+        /// It won't be located with <see cref="Type.GetType()"/> call.
+        /// </summary>
+        public static Assembly LoadAssembly(byte[] bytes, string assemblyName)
+        {
+            Debug.Assert(bytes != null);
+            Debug.Assert(!string.IsNullOrWhiteSpace(assemblyName));
+
+            return InMemoryAssemblies.GetOrAdd(assemblyName, _ =>
+            {
+                // Load is better for us than LoadFrom: we want to track loaded assemblies
manually.
+                // LoadFrom can cause exceptions when multiple versions of the same assembly
exist.
+                var asm = Assembly.Load(bytes);
+
+                Debug.Assert(assemblyName == asm.FullName);
+
+                return new KeyValuePair<Assembly, byte[]>(asm, bytes);
+            }).Key;
+        }
+
+        /// <summary>
+        /// Gets the assembly.
+        /// </summary>
+        public static byte[] GetAssemblyBytes(string assemblyName)
+        {
+            Debug.Assert(!string.IsNullOrWhiteSpace(assemblyName));
+
+            KeyValuePair<Assembly, byte[]> res;
+
+            return InMemoryAssemblies.TryGetValue(assemblyName, out res) ? res.Value : null;
+        }
+
+        /// <summary>
+        /// Gets the assembly.
+        /// </summary>
+        public static Assembly GetAssembly(string assemblyName)
+        {
+            Debug.Assert(!string.IsNullOrWhiteSpace(assemblyName));
+
+            KeyValuePair<Assembly, byte[]> res;
+
+            return InMemoryAssemblies.TryGetValue(assemblyName, out res) ? res.Key : null;
+        }
+
+        /// <summary>
+        /// Gets the assembly bytes.
+        /// </summary>
+        public static byte[] GetAssemblyBytes(Assembly assembly)
+        {
+            Debug.Assert(assembly != null);
+            Debug.Assert(!assembly.IsDynamic);
+
+            KeyValuePair<Assembly, byte[]> pair;
+
+            if (InMemoryAssemblies.TryGetValue(assembly.FullName, out pair))
+                return pair.Value;
+
+            if (string.IsNullOrEmpty(assembly.Location))
+                return null;
+
+            return File.ReadAllBytes(assembly.Location);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequest.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequest.cs
new file mode 100644
index 0000000..ac68893
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequest.cs
@@ -0,0 +1,68 @@
+/*
+ * 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.Deployment
+{
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Peer assembly request.
+    /// </summary>
+    internal class AssemblyRequest : IBinaryWriteAware
+    {
+        /** */
+        private readonly string _assemblyName;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblyRequest"/> class.
+        /// </summary>
+        /// <param name="assemblyName">Name of the assembly.</param>
+        public AssemblyRequest(string assemblyName)
+        {
+            Debug.Assert(assemblyName != null);
+
+            _assemblyName = assemblyName;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblyRequest"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public AssemblyRequest(IBinaryRawReader reader)
+        {
+            _assemblyName = reader.ReadString();
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            var raw = writer.GetRawWriter();
+
+            raw.WriteString(_assemblyName);
+        }
+
+        /// <summary>
+        /// Gets the name of the assembly.
+        /// </summary>
+        public string AssemblyName
+        {
+            get { return _assemblyName; }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequestResult.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequestResult.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequestResult.cs
new file mode 100644
index 0000000..f4ccfa1
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/AssemblyRequestResult.cs
@@ -0,0 +1,80 @@
+/*
+ * 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.Deployment
+{
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Peer assembly request result.
+    /// </summary>
+    internal class AssemblyRequestResult : IBinaryWriteAware
+    {
+        /** Assembly bytes. */
+        private readonly byte[] _assemblyBytes;
+
+        /** Error message. */
+        private readonly string _message;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblyRequestResult" />
class.
+        /// </summary>
+        /// <param name="assemblyBytes">The assembly bytes.</param>
+        /// <param name="message">The message.</param>
+        public AssemblyRequestResult(byte[] assemblyBytes, string message)
+        {
+            _assemblyBytes = assemblyBytes;
+            _message = message;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AssemblyRequestResult"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public AssemblyRequestResult(IBinaryRawReader reader)
+        {
+            _assemblyBytes = reader.ReadByteArray();
+            _message = reader.ReadString();
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            var raw = writer.GetRawWriter();
+
+            raw.WriteByteArray(_assemblyBytes);
+            raw.WriteString(_message);
+        }
+
+        /// <summary>
+        /// Gets the assembly bytes.
+        /// </summary>
+        public byte[] AssemblyBytes
+        {
+            get { return _assemblyBytes; }
+        }
+
+        /// <summary>
+        /// Gets the message.
+        /// </summary>
+        public string Message
+        {
+            get { return _message; }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
new file mode 100644
index 0000000..6d54dbf
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/GetAssemblyFunc.cs
@@ -0,0 +1,77 @@
+/*
+ * 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.Deployment
+{
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Compute;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Compute func that returns assembly for a specified name.
+    /// </summary>
+    internal class GetAssemblyFunc : IComputeFunc<AssemblyRequest, AssemblyRequestResult>,
IBinaryWriteAware
+    {
+        /** <inheritdoc /> */
+        public AssemblyRequestResult Invoke(AssemblyRequest arg)
+        {
+            if (arg == null)
+            {
+                throw new IgniteException("GetAssemblyFunc does not allow null arguments.");
+            }
+
+            if (arg.AssemblyName == null)
+            {
+                throw new IgniteException("GetAssemblyFunc does not allow null AssemblyName.");
+            }
+
+            Debug.WriteLine("Peer assembly request: " + arg.AssemblyName);
+
+            // Try assemblies in main context.
+            var asm = LoadedAssembliesResolver.Instance.GetAssembly(arg.AssemblyName);
+
+            if (asm != null)
+            {
+                if (asm.IsDynamic)
+                {
+                    return new AssemblyRequestResult(null, 
+                        "Peer assembly loading does not support dynamic assemblies: " + asm);
+                }
+
+                return new AssemblyRequestResult(AssemblyLoader.GetAssemblyBytes(asm), null);
+            }
+
+            var bytes = AssemblyLoader.GetAssemblyBytes(arg.AssemblyName);
+
+            if (bytes != null)
+            {
+                return new AssemblyRequestResult(bytes, null);
+            }
+
+            return null;
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            // No-op.
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
new file mode 100644
index 0000000..607ca57
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerAssemblyResolver.cs
@@ -0,0 +1,189 @@
+/*
+ * 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.Deployment
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Reflection;
+    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.Binary;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Loads assemblies from other nodes.
+    /// </summary>
+    internal sealed class PeerAssemblyResolver : IDisposable
+    {
+        /** Assembly resolve handler. */
+        private readonly ResolveEventHandler _handler;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PeerAssemblyResolver"/> class.
+        /// </summary>
+        public PeerAssemblyResolver(Ignite ignite, Guid originNodeId)
+        {
+            Debug.Assert(ignite != null);
+
+            _handler = (sender, args) => GetAssembly(ignite, args.Name, originNodeId);
+
+            AppDomain.CurrentDomain.AssemblyResolve += _handler;
+        }
+
+        /** <inheritdoc /> */
+        public void Dispose()
+        {
+            AppDomain.CurrentDomain.AssemblyResolve -= _handler;
+        }
+
+        /// <summary>
+        /// Gets the assembly from remote nodes.
+        /// </summary>
+        /// <param name="typeName">Assembly-qualified type name.</param>
+        /// <param name="ignite">Ignite.</param>
+        /// <param name="originNodeId">Originating node identifier.</param>
+        /// <returns>
+        /// Resulting type or null.
+        /// </returns>
+        public static Type LoadAssemblyAndGetType(string typeName, Ignite ignite, Guid originNodeId)
+        {
+            Debug.Assert(!string.IsNullOrEmpty(typeName));
+
+            var parsedName = TypeNameParser.Parse(typeName);
+
+            var assemblyName = parsedName.GetAssemblyName();
+
+            Debug.Assert(assemblyName != null);
+
+            var asm = GetAssembly(ignite, assemblyName, originNodeId);
+
+            if (asm == null)
+            {
+                return null;
+            }
+
+            // Assembly.GetType does not work for assembly-qualified names. Full name is
required without assembly.
+            return asm.GetType(parsedName.GetFullName(), false);
+        }
+
+        /// <summary>
+        /// Gets the assembly.
+        /// </summary>
+        private static Assembly GetAssembly(Ignite ignite, string assemblyName, Guid originNodeId)
+        {
+            return LoadedAssembliesResolver.Instance.GetAssembly(assemblyName)
+                   ?? AssemblyLoader.GetAssembly(assemblyName)
+                   ?? LoadAssembly(ignite, assemblyName, originNodeId);
+        }
+
+        /// <summary>
+        /// Loads the assembly.
+        /// </summary>
+        private static Assembly LoadAssembly(Ignite ignite, string assemblyName, Guid originNodeId)
+        {
+            var res = RequestAssembly(assemblyName, ignite, originNodeId);
+
+            if (res == null)
+                return null;
+
+            return AssemblyLoader.LoadAssembly(res.AssemblyBytes, assemblyName);
+        }
+
+        /// <summary>
+        /// Gets the assembly from remote nodes.
+        /// </summary>
+        /// <param name="assemblyName">Name of the assembly.</param>
+        /// <param name="ignite">Ignite.</param>
+        /// <param name="originNodeId">The origin node identifier.</param>
+        /// <returns>
+        /// Successful result or null.
+        /// </returns>
+        /// <exception cref="IgniteException"></exception>
+        private static AssemblyRequestResult RequestAssembly(string assemblyName, Ignite
ignite, Guid originNodeId)
+        {
+            Debug.Assert(assemblyName != null);
+            Debug.Assert(ignite != null);
+
+            if (ignite.Configuration.PeerAssemblyLoadingMode == PeerAssemblyLoadingMode.Disabled)
+                return null;
+
+            Debug.WriteLine("Requesting assembly from other nodes: " + assemblyName);
+
+            // New nodes are not tracked during the loop, since some of the existing nodes
caused this call.
+            var func = new GetAssemblyFunc();
+            var req = new AssemblyRequest(assemblyName);
+
+            foreach (var node in GetDotNetNodes(ignite, originNodeId))
+            {
+                var compute = ignite.GetCluster().ForNodeIds(node).GetCompute();
+                var result = ComputeApplySafe(compute, func, req);
+
+                if (result != null)
+                {
+                    if (result.AssemblyBytes != null)
+                    {
+                        return result;
+                    }
+
+                    if (result.Message != null)
+                    {
+                        throw new IgniteException(result.Message);
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Gets the dot net nodes, origin node comes first.
+        /// </summary>
+        private static IEnumerable<Guid> GetDotNetNodes(IIgnite ignite, Guid originNodeId)
+        {
+            yield return originNodeId;
+
+            foreach (var node in ignite.GetCluster().ForDotNet().ForRemotes().GetNodes())
+            {
+                if (node.Id != originNodeId)
+                {
+                    yield return node.Id;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Performs computation ignoring leaving nodes.
+        /// </summary>
+        private static AssemblyRequestResult ComputeApplySafe(ICompute compute, GetAssemblyFunc
func,
+            AssemblyRequest req)
+        {
+            try
+            {
+                return compute.Apply(func, req);
+            }
+            catch (ClusterGroupEmptyException)
+            {
+                // Normal situation: node has left.
+                return null;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingExtensions.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingExtensions.cs
new file mode 100644
index 0000000..035a041
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingExtensions.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.Deployment
+{
+    using System;
+    using Apache.Ignite.Core.Deployment;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Reader and Writer extensions for peer deployment.
+    /// </summary>
+    internal static class PeerLoadingExtensions
+    {
+        /** */
+        private static readonly Func<object, PeerLoadingObjectHolder> WrapperFunc =
+            x => new PeerLoadingObjectHolder(x);
+
+        /// <summary>
+        /// Writes the object with peer deployment (when enabled) or normally otherwise.
+        /// </summary>
+        public static void WriteWithPeerDeployment(this BinaryWriter writer, object o)
+        {
+            if (writer.Marshaller.IsPeerAssemblyLoadingEnabled())
+            {
+                try
+                {
+                    writer.WrapperFunc = WrapperFunc;
+                    writer.WriteObject(o);
+                }
+                finally
+                {
+                    writer.WrapperFunc = null;
+                }
+            }
+            else
+            {
+                writer.WriteObject(o);
+            }
+        }
+
+        /// <summary>
+        /// Determines whether peer loading is enabled.
+        /// </summary>
+        private static bool IsPeerAssemblyLoadingEnabled(this Marshaller marshaller)
+        {
+            return marshaller != null && marshaller.Ignite != null &&
+                   marshaller.Ignite.Configuration.PeerAssemblyLoadingMode != PeerAssemblyLoadingMode.Disabled;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolder.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolder.cs
new file mode 100644
index 0000000..584750a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolder.cs
@@ -0,0 +1,90 @@
+/*
+ * 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.Deployment
+{
+    using System;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Holds an object which can have it's assembly automatically loaded on remote nodes.
+    /// 
+    /// Contains assembly-qualified type name.
+    /// Types from assemblies with different versions can coexist and will be differentiated
properly.
+    /// </summary>
+    internal class PeerLoadingObjectHolder : IBinaryWriteAware
+    {
+        /** Object. */
+        private readonly object _object;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PeerLoadingObjectHolder"/>
class.
+        /// </summary>
+        /// <param name="o">The object.</param>
+        public PeerLoadingObjectHolder(object o)
+        {
+            Debug.Assert(o != null);
+
+            _object = o;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PeerLoadingObjectHolder"/>
class.
+        /// </summary>
+        public PeerLoadingObjectHolder(BinaryReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            var originNodeId = reader.ReadGuid().GetValueOrDefault();
+            
+            var typeName = reader.ReadString();
+
+            var ignite = reader.Marshaller.Ignite;
+
+            using (new PeerAssemblyResolver(ignite, originNodeId))  // Resolve transitive
dependencies when needed.
+            {
+                // Resolve type from existing assemblies or from remote nodes.
+                var type = Type.GetType(typeName, false)
+                           ?? PeerAssemblyResolver.LoadAssemblyAndGetType(typeName, ignite,
originNodeId);
+
+                Debug.Assert(type != null);
+
+                _object = reader.Deserialize<object>(type);
+            }
+        }
+
+        /// <summary>
+        /// Gets the object.
+        /// </summary>
+        public object Object
+        {
+            get { return _object; }
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            var writer0 = (BinaryWriter) writer.GetRawWriter();
+
+            writer0.WriteGuid(writer0.Marshaller.Ignite.GetLocalNode().Id);
+            writer0.WriteString(_object.GetType().AssemblyQualifiedName);
+            writer0.WithDetach(w => w.WriteObject(_object));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69876116/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolderSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolderSerializer.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolderSerializer.cs
new file mode 100644
index 0000000..c9a0a45
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Deployment/PeerLoadingObjectHolderSerializer.cs
@@ -0,0 +1,49 @@
+/*
+ * 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.Deployment
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Serializer for <see cref="PeerLoadingObjectHolder"/>. Unwraps underlying object
automatically.
+    /// </summary>
+    internal class PeerLoadingObjectHolderSerializer : IBinarySerializerInternal
+    {
+        /** <inheritdoc /> */
+        public void WriteBinary<T>(T obj, BinaryWriter writer)
+        {
+            TypeCaster<PeerLoadingObjectHolder>.Cast(obj).WriteBinary(writer);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int
pos, Type typeOverride)
+        {
+            var holder = new PeerLoadingObjectHolder(reader);
+
+            return (T) holder.Object;
+        }
+
+        /** <inheritdoc /> */
+        public bool SupportsHandles
+        {
+            get { return false; }
+        }
+    }
+}


Mime
View raw message