diff options
| author | Jens Baumgart | 2010-07-21 07:35:15 +0000 |
|---|---|---|
| committer | Jens Baumgart | 2010-07-21 07:35:15 +0000 |
| commit | e99c48a61a835149133fca57be117dc9248f5cd2 (patch) | |
| tree | 4cd7d007dc34b9ec4b119fa398283e7e7fbdaa9e | |
| parent | ec13e0382ab1f9d32d889068b7aeb9c2ef6a2b60 (diff) | |
| download | jgit-e99c48a61a835149133fca57be117dc9248f5cd2.tar.gz jgit-e99c48a61a835149133fca57be117dc9248f5cd2.tar.xz jgit-e99c48a61a835149133fca57be117dc9248f5cd2.zip | |
Fix concurrent read / write issue in GitIndex on Windows
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>
5 files changed, 48 insertions, 4 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java index defda148c8..df4906374f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitIndex.java @@ -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); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index b8d433762e..cb5c8bda54 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -149,6 +149,13 @@ public abstract class FS { } /** + * 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). * * @return the user's home directory; null if the user does not have one. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java index 4ce0366fc8..950d49189c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java5.java @@ -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; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java index 8a86d2e65f..192d9bbbbf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX_Java6.java @@ -104,4 +104,9 @@ class FS_POSIX_Java6 extends FS { throw new Error(e); } } + + @Override + public boolean retryFailedLockFileCommit() { + return false; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java index c86f3e1e43..4e35e6ee4b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java @@ -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; + } } |
