IGNITE-1921 .Net: Fixed handle leak during ComputeJobHolder serialization.

Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fff85cb2
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fff85cb2
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fff85cb2

Branch: refs/heads/ignite-1816
Commit: fff85cb22bdffb0f758977156d41e683210ed148
Parents: b96886d
Author: Pavel Tupitsyn <ptupit...@gridgain.com>
Authored: Tue Nov 17 16:46:22 2015 +0300
Committer: vozerov-gridgain <voze...@gridgain.com>
Committed: Tue Nov 17 16:46:22 2015 +0300

----------------------------------------------------------------------
 .../Compute/ComputeApiTest.cs                   | 22 +++++-
 .../Impl/Compute/ComputeImpl.cs                 | 12 ++-
 .../Impl/Compute/ComputeTaskHolder.cs           | 79 +++++++++++++-------
 3 files changed, 84 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
index f02e67e..cb582b7 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
@@ -1087,6 +1087,16 @@ namespace Apache.Ignite.Core.Tests.Compute
             Assert.AreEqual(_grid1.GetCompute().ClusterGroup.GetNodes().Count, 
res);
         }
 
+        [Test]
+        public void TestExceptions()
+        {
+            Assert.Throws<BinaryObjectException>(() => 
_grid1.GetCompute().Broadcast(new InvalidComputeAction()));
+
+            Assert.Throws<BinaryObjectException>(
+                () => _grid1.GetCompute().Execute<NetSimpleJobArgument, 
NetSimpleJobResult, NetSimpleTaskResult>(
+                    typeof (NetSimpleTask), new NetSimpleJobArgument(-1)));
+        }
+
         /// <summary>
         /// Create configuration.
         /// </summary>
@@ -1143,7 +1153,7 @@ namespace Apache.Ignite.Core.Tests.Compute
 
             for (int i = 0; i < subgrid.Count; i++)
             {
-                NetSimpleJob job = new NetSimpleJob {Arg = arg};
+                var job = arg.Arg > 0 ? new NetSimpleJob {Arg = arg} : new 
InvalidNetSimpleJob();
 
                 jobs[job] = subgrid[i];
             }
@@ -1183,6 +1193,11 @@ namespace Apache.Ignite.Core.Tests.Compute
         }
     }
 
+    class InvalidNetSimpleJob : NetSimpleJob
+    {
+        // No-op.
+    }
+
     [Serializable]
     class NetSimpleJobArgument
     {
@@ -1234,6 +1249,11 @@ namespace Apache.Ignite.Core.Tests.Compute
         }
     }
 
+    class InvalidComputeAction : ComputeAction
+    {
+        // No-op.
+    }
+
     interface IUserInterface<out T>
     {
         T Invoke();

http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/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 bbb9489..b44b2ee 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
@@ -583,7 +583,17 @@ namespace Apache.Ignite.Core.Impl.Compute
             var jobHandle = 
Marshaller.Ignite.HandleRegistry.Allocate(jobHolder);
 
             writer.WriteLong(jobHandle);
-            writer.WriteObject(jobHolder);
+
+            try
+            {
+                writer.WriteObject(jobHolder);
+            }
+            catch (Exception)
+            {
+                Marshaller.Ignite.HandleRegistry.Release(jobHandle);
+
+                throw;
+            }
 
             return jobHandle;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/fff85cb2/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs
index 8f9d06a..e992245 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeTaskHolder.cs
@@ -221,34 +221,8 @@ namespace Apache.Ignite.Core.Impl.Compute
                     else
                     {
                         writer.WriteBoolean(true); // Map produced result.
-                        writer.WriteInt(map.Count); // Amount of mapped jobs.
 
-                        var jobHandles = new List<long>(map.Count);
-
-                        foreach (KeyValuePair<IComputeJob<T>, IClusterNode> 
mapEntry in map)
-                        {
-                            var job = new 
ComputeJobHolder(_compute.ClusterGroup.Ignite as Ignite, 
mapEntry.Key.ToNonGeneric());
-
-                            IClusterNode node = mapEntry.Value;
-
-                            var jobHandle = 
ignite.HandleRegistry.Allocate(job);
-
-                            jobHandles.Add(jobHandle);
-
-                            writer.WriteLong(jobHandle);
-
-                            if (node.IsLocal)
-                                writer.WriteBoolean(false); // Job is not 
serialized.
-                            else
-                            {
-                                writer.WriteBoolean(true); // Job is 
serialized.
-                                writer.WriteObject(job);
-                            }
-
-                            writer.WriteGuid(node.Id);
-                        }
-
-                        _jobHandles = jobHandles;
+                        _jobHandles = WriteJobs(writer, map);
                     }
                 }
                 else
@@ -277,6 +251,57 @@ namespace Apache.Ignite.Core.Impl.Compute
             }
         }
 
+        /// <summary>
+        /// Writes job map.
+        /// </summary>
+        /// <param name="writer">Writer.</param>
+        /// <param name="map">Map</param>
+        /// <returns>Job handle list.</returns>
+        private static List<long> WriteJobs(BinaryWriter writer, 
IDictionary<IComputeJob<T>, IClusterNode> map)
+        {
+            Debug.Assert(writer != null && map != null);
+
+            writer.WriteInt(map.Count); // Amount of mapped jobs.
+
+            var jobHandles = new List<long>(map.Count);
+            var ignite = writer.Marshaller.Ignite;
+
+            try
+            {
+                foreach (KeyValuePair<IComputeJob<T>, IClusterNode> mapEntry 
in map)
+                {
+                    var job = new ComputeJobHolder(ignite, 
mapEntry.Key.ToNonGeneric());
+
+                    IClusterNode node = mapEntry.Value;
+
+                    var jobHandle = ignite.HandleRegistry.Allocate(job);
+
+                    jobHandles.Add(jobHandle);
+
+                    writer.WriteLong(jobHandle);
+
+                    if (node.IsLocal)
+                        writer.WriteBoolean(false); // Job is not serialized.
+                    else
+                    {
+                        writer.WriteBoolean(true); // Job is serialized.
+                        writer.WriteObject(job);
+                    }
+
+                    writer.WriteGuid(node.Id);
+                }
+            }
+            catch (Exception)
+            {
+                foreach (var handle in jobHandles)
+                    ignite.HandleRegistry.Release(handle);
+
+                throw;
+            }
+
+            return jobHandles;
+        }
+
         /** <inheritDoc /> */
         public int JobResultLocal(ComputeJobHolder job)
         {

Reply via email to