You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/18 15:04:17 UTC

[18/46] ignite git commit: IGNITE-4856 .NET: StopAll on AppDomain unload

IGNITE-4856 .NET: StopAll on AppDomain unload

This closes #1732


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

Branch: refs/heads/ignite-1561-1
Commit: 99842bf1986b4cafc7d15ddee7dd2322e65b9c10
Parents: 323e387
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Apr 18 10:41:19 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Apr 18 10:41:19 2017 +0300

----------------------------------------------------------------------
 .../ConsoleRedirectTest.cs                      |  5 +-
 .../IgniteConfigurationSerializerTest.cs        |  3 +-
 .../IgniteStartStopTest.cs                      | 24 +++++++
 .../Apache.Ignite.Core/IgniteConfiguration.cs   | 13 ++++
 .../IgniteConfigurationSection.xsd              |  5 ++
 .../dotnet/Apache.Ignite.Core/Ignition.cs       | 67 ++++++++++++++++++--
 6 files changed, 107 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
index 5a59a37..3ab5ed3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
@@ -166,11 +166,12 @@ namespace Apache.Ignite.Core.Tests
         {
             public void Run()
             {
-                var ignite = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
+                Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
                 {
                     IgniteInstanceName = "newDomainGrid"
                 });
-                Ignition.Stop(ignite.Name, true);
+
+                // Will be stopped automatically on domain unload.
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/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 cba5647..4a197e5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -65,7 +65,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'>
+            var xml = @"<igniteConfig workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10' isDaemon='true' isLateAffinityAssignment='false' springConfigUrl='c:\myconfig.xml' autoGenerateIgniteInstanceName='true'>
                             <localhost>127.1.1.1</localhost>
                             <binaryConfiguration compactFooter='false' keepDeserialized='true'>
                                 <nameMapper type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+NameMapper' bar='testBar' />
@@ -158,6 +158,7 @@ namespace Apache.Ignite.Core.Tests
             Assert.IsFalse(cfg.BinaryConfiguration.CompactFooter);
             Assert.AreEqual(new[] {42, EventType.TaskFailed, EventType.JobFinished}, cfg.IncludedEventTypes);
             Assert.AreEqual(@"c:\myconfig.xml", cfg.SpringConfigUrl);
+            Assert.IsTrue(cfg.AutoGenerateIgniteInstanceName);
 
             Assert.AreEqual("secondCache", cfg.CacheConfiguration.Last().Name);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
index b863308..bc40f48 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests
     using System;
     using System.Collections.Generic;
     using System.IO;
+    using System.Linq;
     using System.Threading;
     using System.Threading.Tasks;
     using Apache.Ignite.Core.Common;
@@ -104,12 +105,15 @@ namespace Apache.Ignite.Core.Tests
             var grid1 = Ignition.Start(cfg);
 
             Assert.AreEqual("grid1", grid1.Name);
+            Assert.AreSame(grid1, Ignition.GetIgnite());
+            Assert.AreSame(grid1, Ignition.GetAll().Single());
 
             cfg.SpringConfigUrl = cfgs[1];
 
             var grid2 = Ignition.Start(cfg);
 
             Assert.AreEqual("grid2", grid2.Name);
+            Assert.Throws<IgniteException>(() => Ignition.GetIgnite());
 
             cfg.SpringConfigUrl = cfgs[2];
 
@@ -124,9 +128,12 @@ namespace Apache.Ignite.Core.Tests
             Assert.AreSame(grid2, Ignition.TryGetIgnite("grid2"));
 
             Assert.AreSame(grid3, Ignition.GetIgnite(null));
+            Assert.AreSame(grid3, Ignition.GetIgnite());
             Assert.AreSame(grid3, Ignition.TryGetIgnite(null));
             Assert.AreSame(grid3, Ignition.TryGetIgnite());
 
+            Assert.AreEqual(new[] {grid3, grid1, grid2}, Ignition.GetAll().OrderBy(x => x.Name).ToArray());
+
             Assert.Throws<IgniteException>(() => Ignition.GetIgnite("invalid_name"));
             Assert.IsNull(Ignition.TryGetIgnite("invalid_name"));
 
@@ -187,6 +194,23 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
+        /// Tests automatic grid name generation.
+        /// </summary>
+        [Test]
+        public void TestStartUniqueName()
+        {
+            var cfg = TestUtils.GetTestConfiguration();
+            cfg.AutoGenerateIgniteInstanceName = true;
+
+            Ignition.Start(cfg);
+            Assert.IsNotNull(Ignition.GetIgnite());
+
+            Ignition.Start(cfg);
+            Assert.Throws<IgniteException>(() => Ignition.GetIgnite());
+            Assert.AreEqual(2, Ignition.GetAll().Count);
+        }
+
+        /// <summary>
         /// 
         /// </summary>
         [Test]

http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/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 a22c568..24a4364 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -518,6 +518,7 @@ namespace Apache.Ignite.Core
             JvmInitialMemoryMb = cfg.JvmInitialMemoryMb;
             JvmMaxMemoryMb = cfg.JvmMaxMemoryMb;
             PluginConfigurations = cfg.PluginConfigurations;
+            AutoGenerateIgniteInstanceName = cfg.AutoGenerateIgniteInstanceName;
         }
 
         /// <summary>
@@ -530,6 +531,18 @@ namespace Apache.Ignite.Core
         public string IgniteInstanceName { get; set; }
 
         /// <summary>
+        /// Gets or sets a value indicating whether unique <see cref="IgniteInstanceName"/> should be generated.
+        /// <para />
+        /// Set this to true in scenarios where new node should be started regardless of other nodes present within
+        /// current process. In particular, this setting is useful is ASP.NET and IIS environments, where AppDomains
+        /// are loaded and unloaded within a single process during application restarts. Ignite stops all nodes
+        /// on <see cref="AppDomain"/> unload, however, IIS does not wait for previous AppDomain to unload before
+        /// starting up a new one, which may cause "Ignite instance with this name has already been started" errors.
+        /// This setting solves the issue.
+        /// </summary>
+        public bool AutoGenerateIgniteInstanceName { get; set; }
+
+        /// <summary>
         /// Gets or sets optional local instance name.
         /// <para />
         /// This name only works locally and has no effect on topology.

http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/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 b503338..1d2a948 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -1152,6 +1152,11 @@
                     <xs:documentation>Local Ignite instance name to be used with Ignition.GetIgnite.</xs:documentation>
                 </xs:annotation>
             </xs:attribute>
+            <xs:attribute name="autoGenerateIgniteInstanceName" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>Generate unique igniteInstanceName automatically.</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
             <xs:attribute name="jvmDllPath" type="xs:string">
                 <xs:annotation>
                     <xs:documentation>Path jvm.dll file. If not set, it's location will be determined using JAVA_HOME environment variable. If path is neither set nor determined automatically, an exception will be thrown.</xs:documentation>

http://git-wip-us.apache.org/repos/asf/ignite/blob/99842bf1/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 d2be92a..cdb1064 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -85,6 +85,7 @@ namespace Apache.Ignite.Core
         static Ignition()
         {
             AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+            AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
         }
 
         /// <summary>
@@ -231,6 +232,11 @@ namespace Apache.Ignite.Core
 
                 var gridName = cfg.IgniteInstanceName;
 
+                if (cfg.AutoGenerateIgniteInstanceName)
+                {
+                    gridName = (gridName ?? "ignite-instance-") + Guid.NewGuid();
+                }
+
                 // 3. Create startup object which will guide us through the rest of the process.
                 _startup = new Startup(cfg, cbs);
 
@@ -576,15 +582,49 @@ namespace Apache.Ignite.Core
         }
 
         /// <summary>
-        /// Gets an instance of default no-name grid. Note that
-        /// caller of this method should not assume that it will return the same
-        /// instance every time.
+        /// Gets the default Ignite instance with null name, or an instance with any name when there is only one.
+        /// <para />
+        /// Note that caller of this method should not assume that it will return the same instance every time.
         /// </summary>
-        /// <returns>An instance of default no-name grid.</returns>
-        /// <exception cref="IgniteException">When there is no Ignite instance with specified name.</exception>
+        /// <returns>Default Ignite instance.</returns>
+        /// <exception cref="IgniteException">When there is no matching Ignite instance.</exception>
         public static IIgnite GetIgnite()
         {
-            return GetIgnite(null);
+            lock (SyncRoot)
+            {
+                if (Nodes.Count == 0)
+                {
+                    throw new IgniteException("Failed to get default Ignite instance: " +
+                                              "there are no instances started.");
+                }
+
+                if (Nodes.Count == 1)
+                {
+                    return Nodes.Single().Value;
+                }
+
+                Ignite result;
+
+                if (Nodes.TryGetValue(new NodeKey(null), out result))
+                {
+                    return result;
+                }
+
+                throw new IgniteException(string.Format("Failed to get default Ignite instance: " +
+                    "there are {0} instances started, and none of them has null name.", Nodes.Count));
+            }
+        }
+
+        /// <summary>
+        /// Gets all started Ignite instances.
+        /// </summary>
+        /// <returns>All Ignite instances.</returns>
+        public static ICollection<IIgnite> GetAll()
+        {
+            lock (SyncRoot)
+            {
+                return Nodes.Values.ToArray();
+            }
         }
 
         /// <summary>
@@ -685,9 +725,22 @@ namespace Apache.Ignite.Core
         {
             return LoadedAssembliesResolver.Instance.GetAssembly(args.Name);
         }
+                
+        /// <summary>
+        /// Handles the DomainUnload event of the CurrentDomain control.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
+        private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
+        {
+            // If we don't stop Ignite.NET on domain unload,
+            // we end up with broken instances in Java (invalid callbacks, etc).
+            // IIS, in particular, is known to unload and reload domains within the same process.
+            StopAll(true);
+        }
 
         /// <summary>
-        /// Grid key.
+        /// Grid key. Workaround for non-null key requirement in Dictionary.
         /// </summary>
         private class NodeKey
         {