DFSGarbargeCollector: Write object size indices
PackWriter knows how to add an object size index to the pack, but the garbage collector is not using it yet. Teach DfsGarbageCollector to write the object size index on writePack(). Disable by default in the unreachable-garbage pack. Callers control the content/presence of the index through the PackConfig option (minBytesForObjSizeIndex) for all other packs, so there is no need of a specific flag in DfsGarbageCollector. Change-Id: I86f5f17310e6913381125bec4caab32dc45b7c9d
This commit is contained in:
parent
9dace2e6d6
commit
12a4a4ccaa
|
@ -15,6 +15,7 @@
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -1100,6 +1101,70 @@ public void commitGraphWithoutGCrestPack() throws Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectSizeIdx_reachableBlob_bigEnough_indexed() throws Exception {
|
||||||
|
String master = "refs/heads/master";
|
||||||
|
RevCommit root = git.branch(master).commit().message("root").noParents()
|
||||||
|
.create();
|
||||||
|
RevBlob headsBlob = git.blob("twelve bytes");
|
||||||
|
git.branch(master).commit()
|
||||||
|
.message("commit on head")
|
||||||
|
.add("file.txt", headsBlob)
|
||||||
|
.parent(root)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
gcWithObjectSizeIndex(10);
|
||||||
|
|
||||||
|
DfsReader reader = odb.newReader();
|
||||||
|
DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
|
||||||
|
assertTrue(gcPack.hasObjectSizeIndex(reader));
|
||||||
|
assertEquals(12, gcPack.getIndexedObjectSize(reader, headsBlob));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectSizeIdx_reachableBlob_tooSmall_notIndexed() throws Exception {
|
||||||
|
String master = "refs/heads/master";
|
||||||
|
RevCommit root = git.branch(master).commit().message("root").noParents()
|
||||||
|
.create();
|
||||||
|
RevBlob tooSmallBlob = git.blob("small");
|
||||||
|
git.branch(master).commit()
|
||||||
|
.message("commit on head")
|
||||||
|
.add("small.txt", tooSmallBlob)
|
||||||
|
.parent(root)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
gcWithObjectSizeIndex(10);
|
||||||
|
|
||||||
|
DfsReader reader = odb.newReader();
|
||||||
|
DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
|
||||||
|
assertTrue(gcPack.hasObjectSizeIndex(reader));
|
||||||
|
assertEquals(-1, gcPack.getIndexedObjectSize(reader, tooSmallBlob));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void objectSizeIndex_unreachableGarbage_noIdx() throws Exception {
|
||||||
|
String master = "refs/heads/master";
|
||||||
|
RevCommit root = git.branch(master).commit().message("root").noParents()
|
||||||
|
.create();
|
||||||
|
git.branch(master).commit()
|
||||||
|
.message("commit on head")
|
||||||
|
.add("file.txt", git.blob("a blob"))
|
||||||
|
.parent(root)
|
||||||
|
.create();
|
||||||
|
git.update(master, root); // blob is unreachable
|
||||||
|
gcWithObjectSizeIndex(0);
|
||||||
|
|
||||||
|
DfsReader reader = odb.newReader();
|
||||||
|
DfsPackFile gcRestPack = findFirstBySource(odb.getPacks(), UNREACHABLE_GARBAGE);
|
||||||
|
assertFalse(gcRestPack.hasObjectSizeIndex(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DfsPackFile findFirstBySource(DfsPackFile[] packs, PackSource source) {
|
||||||
|
return Arrays.stream(packs)
|
||||||
|
.filter(p -> p.getPackDescription().getPackSource() == source)
|
||||||
|
.findFirst().get();
|
||||||
|
}
|
||||||
|
|
||||||
private TestRepository<InMemoryRepository>.CommitBuilder commit() {
|
private TestRepository<InMemoryRepository>.CommitBuilder commit() {
|
||||||
return git.commit();
|
return git.commit();
|
||||||
}
|
}
|
||||||
|
@ -1110,6 +1175,12 @@ private void gcWithCommitGraph() throws IOException {
|
||||||
run(gc);
|
run(gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void gcWithObjectSizeIndex(int threshold) throws IOException {
|
||||||
|
DfsGarbageCollector gc = new DfsGarbageCollector(repo);
|
||||||
|
gc.getPackConfig().setMinBytesForObjSizeIndex(threshold);
|
||||||
|
run(gc);
|
||||||
|
}
|
||||||
|
|
||||||
private void gcNoTtl() throws IOException {
|
private void gcNoTtl() throws IOException {
|
||||||
DfsGarbageCollector gc = new DfsGarbageCollector(repo);
|
DfsGarbageCollector gc = new DfsGarbageCollector(repo);
|
||||||
gc.setGarbageTtl(0, TimeUnit.MILLISECONDS); // disable TTL
|
gc.setGarbageTtl(0, TimeUnit.MILLISECONDS); // disable TTL
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
import static org.eclipse.jgit.internal.storage.pack.PackExt.BITMAP_INDEX;
|
import static org.eclipse.jgit.internal.storage.pack.PackExt.BITMAP_INDEX;
|
||||||
import static org.eclipse.jgit.internal.storage.pack.PackExt.COMMIT_GRAPH;
|
import static org.eclipse.jgit.internal.storage.pack.PackExt.COMMIT_GRAPH;
|
||||||
import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
|
import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
|
||||||
|
import static org.eclipse.jgit.internal.storage.pack.PackExt.OBJECT_SIZE_INDEX;
|
||||||
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.internal.storage.pack.PackExt.REFTABLE;
|
import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
|
||||||
import static org.eclipse.jgit.internal.storage.pack.PackWriter.NONE;
|
import static org.eclipse.jgit.internal.storage.pack.PackWriter.NONE;
|
||||||
|
@ -681,6 +682,17 @@ private DfsPackDescription writePack(PackSource source, PackWriter pw,
|
||||||
pack.setIndexVersion(pw.getIndexVersion());
|
pack.setIndexVersion(pw.getIndexVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (source != UNREACHABLE_GARBAGE && packConfig.getMinBytesForObjSizeIndex() >= 0) {
|
||||||
|
try (DfsOutputStream out = objdb.writeFile(pack,
|
||||||
|
OBJECT_SIZE_INDEX)) {
|
||||||
|
CountingOutputStream cnt = new CountingOutputStream(out);
|
||||||
|
pw.writeObjectSizeIndex(cnt);
|
||||||
|
pack.addFileExt(OBJECT_SIZE_INDEX);
|
||||||
|
pack.setFileSize(OBJECT_SIZE_INDEX, cnt.getCount());
|
||||||
|
pack.setBlockSize(OBJECT_SIZE_INDEX, out.blockSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pw.prepareBitmapIndex(pm)) {
|
if (pw.prepareBitmapIndex(pm)) {
|
||||||
try (DfsOutputStream out = objdb.writeFile(pack, BITMAP_INDEX)) {
|
try (DfsOutputStream out = objdb.writeFile(pack, BITMAP_INDEX)) {
|
||||||
CountingOutputStream cnt = new CountingOutputStream(out);
|
CountingOutputStream cnt = new CountingOutputStream(out);
|
||||||
|
|
Loading…
Reference in New Issue