]> source.dussan.org Git - jgit.git/commitdiff
Fix concurrent read / write issue in GitIndex on Windows 52/1152/4
authorJens Baumgart <jens.baumgart@sap.com>
Wed, 21 Jul 2010 07:35:15 +0000 (09:35 +0200)
committerJens Baumgart <jens.baumgart@sap.com>
Wed, 21 Jul 2010 07:35:15 +0000 (09:35 +0200)
GitIndex.write fails if another thread concurrently reads
the index file. The problem is fixed by retrying the rename
operation if it fails.

Bug: 311051
Change-Id: Ib243d2a90adae312712d02521de4834d06804944
Signed-off-by: Jens Baumgart <jens.baumgart@sap.com>
org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java
org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java

index defda148c89678a1faa148a276b85fc34b3ad05f..df4906374fccedb25a6d3f11808ad0ecffb42f0e 100644 (file)
@@ -297,10 +297,32 @@ public class GitIndex {
                        fc.write(buf);
                        fc.close();
                        fileOutputStream.close();
-                       if (cacheFile.exists())
-                               if (!cacheFile.delete())
-                                       throw new IOException(
-                                               JGitText.get().couldNotRenameDeleteOldIndex);
+                       if (cacheFile.exists()) {
+                               if (db.getFS().retryFailedLockFileCommit()) {
+                                       // file deletion fails on windows if another
+                                       // thread is reading the file concurrently
+                                       // So let's try 10 times...
+                                       boolean deleted = false;
+                                       for (int i = 0; i < 10; i++) {
+                                               if (cacheFile.delete()) {
+                                                       deleted = true;
+                                                       break;
+                                               }
+                                               try {
+                                                       Thread.sleep(100);
+                                               } catch (InterruptedException e) {
+                                                       // ignore
+                                               }
+                                       }
+                                       if (!deleted)
+                                               throw new IOException(
+                                                               JGitText.get().couldNotRenameDeleteOldIndex);
+                               } else {
+                                       if (!cacheFile.delete())
+                                               throw new IOException(
+                                                               JGitText.get().couldNotRenameDeleteOldIndex);
+                               }
+                       }
                        if (!tmpIndex.renameTo(cacheFile))
                                throw new IOException(
                                                JGitText.get().couldNotRenameTemporaryIndexFileToIndex);
index b8d433762eb15bbb14701d83b74881ab782f4dfd..cb5c8bda542ba05f996a1479d5cb26b5dc50ef3b 100644 (file)
@@ -148,6 +148,13 @@ public abstract class FS {
                return userHome;
        }
 
+       /**
+        * Does this file system have problems with atomic renames?
+        *
+        * @return true if the caller should retry a failed rename of a lock file.
+        */
+       public abstract boolean retryFailedLockFileCommit();
+
        /**
         * Determine the user's home directory (location where preferences are).
         *
index 4ce0366fc8c5b3f3ebc9ff75739e2d8d83576975..950d49189c3cf2cf7a60521572d40d319151c409 100644 (file)
@@ -57,4 +57,9 @@ class FS_POSIX_Java5 extends FS {
        public boolean setExecute(final File f, final boolean canExec) {
                return false;
        }
+
+       @Override
+       public boolean retryFailedLockFileCommit() {
+               return false;
+       }
 }
index 8a86d2e65f8608f2cdd7589d423c562560ff9242..192d9bbbbf8022bc2a608e193bf5be2808222794 100644 (file)
@@ -104,4 +104,9 @@ class FS_POSIX_Java6 extends FS {
                        throw new Error(e);
                }
        }
+
+       @Override
+       public boolean retryFailedLockFileCommit() {
+               return false;
+       }
 }
index c86f3e1e43dffd4423b910203acbb6152720615d..4e35e6ee4b436bf388aac342b5e6c2364f420a1d 100644 (file)
@@ -71,4 +71,9 @@ class FS_Win32 extends FS {
        public boolean setExecute(final File f, final boolean canExec) {
                return false;
        }
+
+       @Override
+       public boolean retryFailedLockFileCommit() {
+               return true;
+       }
 }