Browse Source

dfs: Try to avoid searching UNREACHABLE_GARBAGE during packing

If an object can be found in a non-garbage pack, favor that pack over
paging in the garbage pack's idx and pack content.

Only fall back to garbage packs if an object cannot be found and there
are garbage packs present in the repository.  This fallback is
required to correct race conditions during GC.

Change-Id: Ia7c123975bc069b8e6e713eda2d357303b71e329
stable-4.11
Shawn Pearce 7 years ago committed by Matthias Sohn
parent
commit
d0fbaf502e
  1. 66
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java

66
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java

@ -44,12 +44,12 @@
package org.eclipse.jgit.internal.storage.dfs; package org.eclipse.jgit.internal.storage.dfs;
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK; import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH; import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -578,10 +578,22 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
public void selectObjectRepresentation(PackWriter packer, public void selectObjectRepresentation(PackWriter packer,
ProgressMonitor monitor, Iterable<ObjectToPack> objects) ProgressMonitor monitor, Iterable<ObjectToPack> objects)
throws IOException, MissingObjectException { throws IOException, MissingObjectException {
// Don't check dirty bit on PackList; assume ObjectToPacks all came from the // Don't check dirty bit on PackList; assume ObjectToPacks all came
// current list. // from the current list.
for (DfsPackFile pack : sortPacksForSelectRepresentation()) { List<DfsPackFile> packs = sortPacksForSelectRepresentation();
List<DfsObjectToPack> tmp = findAllFromPack(pack, objects); trySelectRepresentation(packer, monitor, objects, packs, false);
List<DfsPackFile> garbage = garbagePacksForSelectRepresentation();
if (!garbage.isEmpty() && checkGarbagePacks(objects)) {
trySelectRepresentation(packer, monitor, objects, garbage, true);
}
}
private void trySelectRepresentation(PackWriter packer,
ProgressMonitor monitor, Iterable<ObjectToPack> objects,
List<DfsPackFile> packs, boolean skipFound) throws IOException {
for (DfsPackFile pack : packs) {
List<DfsObjectToPack> tmp = findAllFromPack(pack, objects, skipFound);
if (tmp.isEmpty()) if (tmp.isEmpty())
continue; continue;
Collections.sort(tmp, OFFSET_SORT); Collections.sort(tmp, OFFSET_SORT);
@ -620,24 +632,54 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
} }
}; };
private DfsPackFile[] sortPacksForSelectRepresentation() private List<DfsPackFile> sortPacksForSelectRepresentation()
throws IOException { throws IOException {
DfsPackFile[] packs = db.getPacks(); DfsPackFile[] packs = db.getPacks();
DfsPackFile[] sorted = new DfsPackFile[packs.length]; List<DfsPackFile> sorted = new ArrayList<>(packs.length);
System.arraycopy(packs, 0, sorted, 0, packs.length); for (DfsPackFile p : packs) {
Arrays.sort(sorted, PACK_SORT_FOR_REUSE); if (p.getPackDescription().getPackSource() != UNREACHABLE_GARBAGE) {
sorted.add(p);
}
}
Collections.sort(sorted, PACK_SORT_FOR_REUSE);
return sorted; return sorted;
} }
private List<DfsPackFile> garbagePacksForSelectRepresentation()
throws IOException {
DfsPackFile[] packs = db.getPacks();
List<DfsPackFile> garbage = new ArrayList<>(packs.length);
for (DfsPackFile p : packs) {
if (p.getPackDescription().getPackSource() == UNREACHABLE_GARBAGE) {
garbage.add(p);
}
}
return garbage;
}
private static boolean checkGarbagePacks(Iterable<ObjectToPack> objects) {
for (ObjectToPack otp : objects) {
if (!((DfsObjectToPack) otp).isFound()) {
return true;
}
}
return false;
}
private List<DfsObjectToPack> findAllFromPack(DfsPackFile pack, private List<DfsObjectToPack> findAllFromPack(DfsPackFile pack,
Iterable<ObjectToPack> objects) throws IOException { Iterable<ObjectToPack> objects, boolean skipFound)
throws IOException {
List<DfsObjectToPack> tmp = new BlockList<>(); List<DfsObjectToPack> tmp = new BlockList<>();
PackIndex idx = pack.getPackIndex(this); PackIndex idx = pack.getPackIndex(this);
for (ObjectToPack otp : objects) { for (ObjectToPack obj : objects) {
DfsObjectToPack otp = (DfsObjectToPack) obj;
if (skipFound && otp.isFound()) {
continue;
}
long p = idx.findOffset(otp); long p = idx.findOffset(otp);
if (0 < p && !pack.isCorrupt(p)) { if (0 < p && !pack.isCorrupt(p)) {
otp.setOffset(p); otp.setOffset(p);
tmp.add((DfsObjectToPack) otp); tmp.add(otp);
} }
} }
return tmp; return tmp;

Loading…
Cancel
Save