IGNITE-5730 .NET: Fix ignite.jni.dll temp dir race
authorPavel Tupitsyn <ptupitsyn@apache.org>
Wed, 27 Sep 2017 11:57:47 +0000 (14:57 +0300)
committerPavel Tupitsyn <ptupitsyn@apache.org>
Wed, 27 Sep 2017 11:57:47 +0000 (14:57 +0300)
This closes #2755

modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs

index f3bdd2b..d55960a 100644 (file)
@@ -82,16 +82,6 @@ namespace Apache.Ignite.Core.Impl
         private static Random _rnd;
 
         /// <summary>
-        /// Initializes the <see cref="IgniteUtils"/> class.
-        /// </summary>
-        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline",
-            Justification = "Readability.")]
-        static IgniteUtils()
-        {
-            TryCleanTempDirectories();
-        }
-
-        /// <summary>
         /// Gets thread local random.
         /// </summary>
         /// <value>Thread local random.</value>
@@ -388,10 +378,20 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Tries to clean temporary directories created with <see cref="GetTempDirectoryName"/>.
         /// </summary>
-        private static void TryCleanTempDirectories()
+        internal static void TryCleanTempDirectories()
         {
-            foreach (var dir in Directory.GetDirectories(Path.GetTempPath(), DirIgniteTmp + "*"))
+            var dt = DateTime.Now;
+
+            foreach (var dir in Directory.EnumerateDirectories(Path.GetTempPath(), DirIgniteTmp + "*"))
             {
+                if ((dt - Directory.GetCreationTime(dir)).TotalMinutes < 1)
+                {
+                    // Do not clean up recently created temp directories:
+                    // they may be used by currently starting up nodes.
+                    // This is a workaround for multiple node startup problem, see IGNITE-5730.
+                    continue;
+                }
+
                 try
                 {
                     Directory.Delete(dir, true);
@@ -413,13 +413,13 @@ namespace Apache.Ignite.Core.Impl
         /// <returns>The full path of the temporary directory.</returns>
         internal static string GetTempDirectoryName()
         {
+            var baseDir = Path.Combine(Path.GetTempPath(), DirIgniteTmp);
+
             while (true)
             {
-                var dir = Path.Combine(Path.GetTempPath(), DirIgniteTmp + Path.GetRandomFileName());
-
                 try
                 {
-                    return Directory.CreateDirectory(dir).FullName;
+                    return Directory.CreateDirectory(baseDir + Path.GetRandomFileName()).FullName;
                 }
                 catch (IOException)
                 {
index b6e6582..511bb7a 100644 (file)
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
     using System.Runtime.InteropServices;
+    using System.Threading.Tasks;
     using Apache.Ignite.Core.Common;
     using JNI = IgniteJniNativeMethods;
 
@@ -57,6 +58,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
 
             JNI.SetConsoleHandler(UnmanagedCallbacks.ConsoleWriteHandler);
+
+            // Clean directories in background to avoid extra work on start.
+            Task.Factory.StartNew(IgniteUtils.TryCleanTempDirectories);
         }
 
         /// <summary>