PackWriter: offer to write an object-size index for the pack

PackWriter callers tell the writer what do the want to include in the
pack and invoke #writePack(). Afterwards, they can invoke #writeIndex()
to write the corresponding pack index.

Mirror this for the object-size index, adding a #writeObjectSizeIndex()
method.

Change-Id: Ic319975c72c239cd6488303f7d4cced797e6fe00
This commit is contained in:
Ivan Frade 2021-12-28 14:23:40 -08:00
parent cfacc43b52
commit ca2c57b2ec
2 changed files with 82 additions and 0 deletions

View File

@ -504,6 +504,43 @@ public void testWriteIndex() throws Exception {
}
}
@Test
public void testWriteObjectSizeIndex_noDeltas() throws Exception {
config.setMinBytesForObjSizeIndex(0);
HashSet<ObjectId> interesting = new HashSet<>();
interesting.add(ObjectId
.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
NullProgressMonitor m1 = NullProgressMonitor.INSTANCE;
writer = new PackWriter(config, db.newObjectReader());
writer.setUseBitmaps(false);
writer.setThin(false);
writer.setIgnoreMissingUninteresting(false);
writer.preparePack(m1, interesting, NONE);
writer.writePack(m1, m1, os);
PackIndex idx;
try (ByteArrayOutputStream is = new ByteArrayOutputStream()) {
writer.writeIndex(is);
idx = PackIndex.read(new ByteArrayInputStream(is.toByteArray()));
}
PackObjectSizeIndex objSizeIdx;
try (ByteArrayOutputStream objSizeStream = new ByteArrayOutputStream()) {
writer.writeObjectSizeIndex(objSizeStream);
objSizeIdx = PackObjectSizeIndexLoader.load(
new ByteArrayInputStream(objSizeStream.toByteArray()));
}
writer.close();
ObjectId knownBlob1 = ObjectId
.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259");
ObjectId knownBlob2 = ObjectId
.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3");
assertEquals(18009, objSizeIdx.getSize(idx.findPosition(knownBlob1)));
assertEquals(18787, objSizeIdx.getSize(idx.findPosition(knownBlob2)));
}
@Test
public void testExclude() throws Exception {
// TestRepository closes repo

View File

@ -61,6 +61,7 @@
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexWriterV1;
import org.eclipse.jgit.internal.storage.file.PackIndexWriter;
import org.eclipse.jgit.internal.storage.file.PackObjectSizeIndexWriter;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.AsyncObjectSizeQueue;
import org.eclipse.jgit.lib.BatchingProgressMonitor;
@ -1091,6 +1092,50 @@ public void writeIndex(OutputStream indexStream) throws IOException {
stats.timeWriting += System.currentTimeMillis() - writeStart;
}
/**
* Create an object size index file for the contents of the pack file just
* written.
* <p>
* Called after
* {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)} that
* populates the list of objects to pack and before
* {@link #writeBitmapIndex(OutputStream)} that destroys it.
* <p>
* Writing this index is only required for local pack storage. Packs sent on
* the network do not need to create an object size index.
*
* @param objIdxStream
* output for the object size index data. Caller is responsible
* for closing this stream.
* @throws IOException
* errors while writing
*/
public void writeObjectSizeIndex(OutputStream objIdxStream)
throws IOException {
if (config.getMinBytesForObjSizeIndex() < 0) {
return;
}
long writeStart = System.currentTimeMillis();
// We only need to populate the size of blobs
AsyncObjectSizeQueue<ObjectToPack> sizeQueue = reader
.getObjectSize(objectsLists[OBJ_BLOB], /* reportMissing= */false);
try {
while (sizeQueue.next()) {
ObjectToPack otp = sizeQueue.getCurrent();
long sz = sizeQueue.getSize();
otp.setFullSize(sz);
}
} finally {
sizeQueue.release();
}
PackObjectSizeIndexWriter iw = PackObjectSizeIndexWriter.createWriter(
objIdxStream, config.getMinBytesForObjSizeIndex());
// All indexed objects because their positions must match primary index order
iw.write(sortByName());
stats.timeWriting += System.currentTimeMillis() - writeStart;
}
/**
* Create a bitmap index file to match the pack file just written.
* <p>