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:
parent
ec13e0382a
commit
e99c48a61a
|
@ -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);
|
||||
|
|
|
@ -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).
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,4 +104,9 @@ public boolean setExecute(final File f, final boolean canExec) {
|
|||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retryFailedLockFileCommit() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue