Merge "Fix GC for FileRepo in case packfile renames fail"

This commit is contained in:
Matthias Sohn 2013-03-19 13:07:47 -04:00 committed by Gerrit Code Review @ Eclipse.org
commit 509c0b58ee
3 changed files with 55 additions and 3 deletions

View File

@ -435,6 +435,13 @@ public void testPackAllObjectsInOnePack() throws Exception {
assertEquals(0, stats.numberOfLooseObjects);
assertEquals(4, stats.numberOfPackedObjects);
assertEquals(1, stats.numberOfPackFiles);
// Do the gc again and check that it hasn't changed anything
gc.gc();
stats = gc.getStatistics();
assertEquals(0, stats.numberOfLooseObjects);
assertEquals(4, stats.numberOfPackedObjects);
assertEquals(1, stats.numberOfPackFiles);
}
@Test

View File

@ -735,11 +735,21 @@ public int compare(PackExt o1, PackExt o2) {
// rename the temporary files to real files
File realPack = nameFor(id, ".pack"); //$NON-NLS-1$
// if the packfile already exists (because we are rewriting a
// packfile for the same set of objects maybe with different
// PackConfig) then make sure we get rid of all handles on the file.
// Windows will not allow for rename otherwise.
if (realPack.exists())
for (PackFile p : repo.getObjectDatabase().getPacks())
if (realPack.getPath().equals(p.getPackFile().getPath())) {
p.close();
break;
}
tmpPack.setReadOnly();
boolean delete = true;
try {
if (!tmpPack.renameTo(realPack))
return null;
FileUtils.rename(tmpPack, realPack);
delete = false;
for (Map.Entry<PackExt, File> tmpEntry : tmpExts.entrySet()) {
File tmpExt = tmpEntry.getValue();
@ -747,7 +757,9 @@ public int compare(PackExt o1, PackExt o2) {
File realExt = nameFor(
id, "." + tmpEntry.getKey().getExtension()); //$NON-NLS-1$
if (!tmpExt.renameTo(realExt)) {
try {
FileUtils.rename(tmpExt, realExt);
} catch (IOException e) {
File newExt = new File(realExt.getParentFile(),
realExt.getName() + ".new"); //$NON-NLS-1$
if (!tmpExt.renameTo(newExt))

View File

@ -167,6 +167,39 @@ public static void delete(final File f, int options) throws IOException {
}
}
/**
* Rename a file or folder. If the rename fails and if we are running on a
* filesystem where it makes sense to repeat a failing rename then repeat
* the rename operation up to 9 times with 100ms sleep time between two
* calls
*
* @see FS#retryFailedLockFileCommit()
* @param src
* the old {@code File}
* @param dst
* the new {@code File}
* @throws IOException
* if the rename has failed
*/
public static void rename(final File src, final File dst)
throws IOException {
int attempts = FS.DETECTED.retryFailedLockFileCommit() ? 10 : 1;
while (--attempts >= 0) {
if (src.renameTo(dst))
return;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new IOException(MessageFormat.format(
JGitText.get().renameFileFailed, src.getAbsolutePath(),
dst.getAbsolutePath()));
}
}
throw new IOException(MessageFormat.format(
JGitText.get().renameFileFailed, src.getAbsolutePath(),
dst.getAbsolutePath()));
}
/**
* Creates the directory named by this abstract pathname.
*