Introduce RefDatabase#hasFastTipsWithSha1
The reftable format supports fast inverse (SHA1 => ref) queries. If the ref database does not support fast inverse queries, it may be advantageous to build a complete SHA1 to ref map in advance for multiple uses. To let applications decide, this function indicates whether the inverse map is available. Signed-off-by: Han-Wen Nienhuys <hanwen@google.com> Change-Id: Idaf7e01075906972ec21332cade285289619c2b3
This commit is contained in:
parent
3198df1860
commit
5185d288c1
|
@ -155,6 +155,8 @@ public void testConvert() throws Exception {
|
|||
assertFalse(b.isSymbolic());
|
||||
assertTrue(b.isPeeled());
|
||||
assertEquals(bCommit, b.getObjectId().name());
|
||||
|
||||
assertTrue(db.getRefDatabase().hasFastTipsWithSha1());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -169,6 +171,8 @@ public void testConvertToRefdir() throws Exception {
|
|||
assertFalse(b.isSymbolic());
|
||||
assertTrue(b.isPeeled());
|
||||
assertEquals(bCommit, b.getObjectId().name());
|
||||
|
||||
assertFalse(db.getRefDatabase().hasFastTipsWithSha1());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -176,6 +176,67 @@ public void estimateCurrentBytesWithIndex() throws IOException {
|
|||
assertEquals(expBytes, table.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasObjMapRefs() throws IOException {
|
||||
ArrayList<Ref> refs = new ArrayList<>();
|
||||
refs.add(ref(MASTER, 1));
|
||||
byte[] table = write(refs);
|
||||
ReftableReader t = read(table);
|
||||
assertTrue(t.hasObjectMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasObjMapRefsSmallTable() throws IOException {
|
||||
ArrayList<Ref> refs = new ArrayList<>();
|
||||
ReftableConfig cfg = new ReftableConfig();
|
||||
cfg.setIndexObjects(false);
|
||||
refs.add(ref(MASTER, 1));
|
||||
byte[] table = write(refs);
|
||||
ReftableReader t = read(table);
|
||||
assertTrue(t.hasObjectMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasObjLogs() throws IOException {
|
||||
PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
|
||||
String msg = "test";
|
||||
ReftableConfig cfg = new ReftableConfig();
|
||||
cfg.setIndexObjects(false);
|
||||
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
ReftableWriter writer = new ReftableWriter(buffer)
|
||||
.setMinUpdateIndex(1)
|
||||
.setConfig(cfg)
|
||||
.setMaxUpdateIndex(1)
|
||||
.begin();
|
||||
|
||||
writer.writeLog("master", 1, who, ObjectId.zeroId(), id(1), msg);
|
||||
writer.finish();
|
||||
byte[] table = buffer.toByteArray();
|
||||
|
||||
ReftableReader t = read(table);
|
||||
assertTrue(t.hasObjectMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasObjMapRefsNoIndexObjects() throws IOException {
|
||||
ArrayList<Ref> refs = new ArrayList<>();
|
||||
ReftableConfig cfg = new ReftableConfig();
|
||||
cfg.setIndexObjects(false);
|
||||
cfg.setRefBlockSize(256);
|
||||
cfg.setAlignBlocks(true);
|
||||
|
||||
// Fill up 5 blocks.
|
||||
int N = 256 * 5 / 25;
|
||||
for (int i= 0; i < N; i++) {
|
||||
refs.add(ref(String.format("%02d/xxxxxxxxxx", i), i));
|
||||
}
|
||||
byte[] table = write(refs, cfg);
|
||||
|
||||
ReftableReader t = read(table);
|
||||
assertFalse(t.hasObjectMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneIdRef() throws IOException {
|
||||
Ref exp = ref(MASTER, 1);
|
||||
|
@ -936,8 +997,13 @@ private byte[] write(Ref... refs) throws IOException {
|
|||
}
|
||||
|
||||
private byte[] write(Collection<Ref> refs) throws IOException {
|
||||
return write(refs, new ReftableConfig());
|
||||
}
|
||||
|
||||
private byte[] write(Collection<Ref> refs, ReftableConfig cfg) throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
stats = new ReftableWriter(buffer)
|
||||
.setConfig(cfg)
|
||||
.begin()
|
||||
.sortAndWriteRefs(refs)
|
||||
.finish()
|
||||
|
|
|
@ -216,6 +216,12 @@ public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
|
|||
return reftableDatabase.getTipsWithSha1(id);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean hasFastTipsWithSha1() throws IOException {
|
||||
return reftableDatabase.hasFastTipsWithSha1();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Ref peel(Ref ref) throws IOException {
|
||||
|
|
|
@ -125,6 +125,12 @@ public static boolean isReftable(File repoDir) {
|
|||
&& new File(repoDir, Constants.REFTABLE).isDirectory();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean hasFastTipsWithSha1() throws IOException {
|
||||
return reftableDatabase.hasFastTipsWithSha1();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a full compaction for GC purposes.
|
||||
* @throws IOException on I/O errors
|
||||
|
|
|
@ -98,6 +98,16 @@ public long maxUpdateIndex() throws IOException {
|
|||
: 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean hasObjectMap() throws IOException {
|
||||
boolean has = true;
|
||||
for (int i = 0; has && i < tables.length; i++) {
|
||||
has = has && tables[i].hasObjectMap();
|
||||
};
|
||||
return has;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public RefCursor allRefs() throws IOException {
|
||||
|
|
|
@ -161,6 +161,12 @@ public void setIncludeDeletes(boolean deletes) {
|
|||
*/
|
||||
public abstract RefCursor byObjectId(AnyObjectId id) throws IOException;
|
||||
|
||||
/**
|
||||
* @return whether this reftable can do a fast SHA1 => ref lookup.
|
||||
* @throws IOException on I/O problems.
|
||||
*/
|
||||
public abstract boolean hasObjectMap() throws IOException;
|
||||
|
||||
/**
|
||||
* Seek reader to read log records.
|
||||
*
|
||||
|
|
|
@ -298,6 +298,19 @@ public List<Ref> getRefsByPrefix(String prefix) throws IOException {
|
|||
return Collections.unmodifiableList(all);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether there is a fast SHA1 to ref map.
|
||||
* @throws IOException in case of I/O problems.
|
||||
*/
|
||||
public boolean hasFastTipsWithSha1() throws IOException {
|
||||
lock.lock();
|
||||
try {
|
||||
return reader().hasObjectMap();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all refs that resolve directly to the given {@link ObjectId}.
|
||||
* Includes peeled {@linkObjectId}s.
|
||||
|
|
|
@ -128,6 +128,16 @@ public int blockSize() throws IOException {
|
|||
return blockSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasObjectMap() throws IOException {
|
||||
if (objIndexPosition == -1) {
|
||||
readFileFooter();
|
||||
}
|
||||
|
||||
// We have the map, we have no refs, or the table is small.
|
||||
return (objPosition > 0 || refEnd == 24 || refIndexPosition == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum update index for log entries that appear in this
|
||||
* reftable.
|
||||
|
|
|
@ -496,6 +496,20 @@ public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
|
|||
|| id.equals(r.getPeeledObjectId())).collect(toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the ref database does not support fast inverse queries, it may
|
||||
* be advantageous to build a complete SHA1 to ref map in advance for
|
||||
* multiple uses. To let applications decide on this decision,
|
||||
* this function indicates whether the inverse map is available.
|
||||
*
|
||||
* @return whether this RefDatabase supports fast inverse ref queries.
|
||||
* @throws IOException on I/O problems.
|
||||
* @since 5.6
|
||||
*/
|
||||
public boolean hasFastTipsWithSha1() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any refs exist in the ref database.
|
||||
* <p>
|
||||
|
|
Loading…
Reference in New Issue