summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorShawn Pearce <spearce@spearce.org>2017-08-09 05:22:14 -0700
committerMatthias Sohn <matthias.sohn@sap.com>2018-02-21 14:46:57 -0500
commitd0fbaf502e5d46c9f19b2c0c5e94ad68b3557670 (patch)
treede857e4f17fba32dd30aab32c16111b81597583c /org.eclipse.jgit
parent35bb7ccc4c9ac39a8dd56dc1c192793cf128b171 (diff)
downloadjgit-d0fbaf502e5d46c9f19b2c0c5e94ad68b3557670.tar.gz
jgit-d0fbaf502e5d46c9f19b2c0c5e94ad68b3557670.zip
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
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java66
1 files changed, 54 insertions, 12 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
index 27a7992c9e..197114bd6b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
@@ -44,12 +44,12 @@
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.lib.Constants.OBJECT_ID_LENGTH;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -578,10 +578,22 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
public void selectObjectRepresentation(PackWriter packer,
ProgressMonitor monitor, Iterable<ObjectToPack> objects)
throws IOException, MissingObjectException {
- // Don't check dirty bit on PackList; assume ObjectToPacks all came from the
- // current list.
- for (DfsPackFile pack : sortPacksForSelectRepresentation()) {
- List<DfsObjectToPack> tmp = findAllFromPack(pack, objects);
+ // Don't check dirty bit on PackList; assume ObjectToPacks all came
+ // from the current list.
+ List<DfsPackFile> packs = sortPacksForSelectRepresentation();
+ 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())
continue;
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 {
DfsPackFile[] packs = db.getPacks();
- DfsPackFile[] sorted = new DfsPackFile[packs.length];
- System.arraycopy(packs, 0, sorted, 0, packs.length);
- Arrays.sort(sorted, PACK_SORT_FOR_REUSE);
+ List<DfsPackFile> sorted = new ArrayList<>(packs.length);
+ for (DfsPackFile p : packs) {
+ if (p.getPackDescription().getPackSource() != UNREACHABLE_GARBAGE) {
+ sorted.add(p);
+ }
+ }
+ Collections.sort(sorted, PACK_SORT_FOR_REUSE);
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,
- Iterable<ObjectToPack> objects) throws IOException {
+ Iterable<ObjectToPack> objects, boolean skipFound)
+ throws IOException {
List<DfsObjectToPack> tmp = new BlockList<>();
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);
if (0 < p && !pack.isCorrupt(p)) {
otp.setOffset(p);
- tmp.add((DfsObjectToPack) otp);
+ tmp.add(otp);
}
}
return tmp;