Browse Source

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

stable-3.0
Matthias Sohn 12 years ago committed by Gerrit Code Review @ Eclipse.org
parent
commit
509c0b58ee
  1. 7
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java
  2. 18
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
  3. 33
      org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java

7
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GCTest.java

@ -435,6 +435,13 @@ public class GCTest extends LocalDiskRepositoryTestCase {
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

18
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

@ -735,11 +735,21 @@ public class GC {
// 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 class GC {
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))

33
org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java

@ -167,6 +167,39 @@ public class FileUtils {
}
}
/**
* 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.
*

Loading…
Cancel
Save