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>
This commit is contained in:
Jens Baumgart 2010-07-21 09:35:15 +02:00
parent ec13e0382a
commit e99c48a61a
5 changed files with 48 additions and 4 deletions

View File

@ -297,10 +297,32 @@ public void write() throws IOException {
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);

View File

@ -148,6 +148,13 @@ public File userHome() {
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).
*

View File

@ -57,4 +57,9 @@ public boolean canExecute(final File f) {
public boolean setExecute(final File f, final boolean canExec) {
return false;
}
@Override
public boolean retryFailedLockFileCommit() {
return false;
}
}

View File

@ -104,4 +104,9 @@ public boolean setExecute(final File f, final boolean canExec) {
throw new Error(e);
}
}
@Override
public boolean retryFailedLockFileCommit() {
return false;
}
}

View File

@ -71,4 +71,9 @@ public boolean canExecute(final File f) {
public boolean setExecute(final File f, final boolean canExec) {
return false;
}
@Override
public boolean retryFailedLockFileCommit() {
return true;
}
}