Repository: ignite Updated Branches: refs/heads/master 42293fac8 -> 69876116d
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; } + } + } +}
