RefTreeDatabase: Expose bootstrap refs in getAdditionalRefs

By showing the bootstrap layer in getAdditionalRefs() garbage
collector code can be more RefDatabase agnostic and not care about
the special case of RefTree and RefTreeNames for the purposes of
building up the roots to GC. Instead they can combine getRefs(ALL)
and getAdditionalRefs() and have a clean set of roots.

Change-Id: I665cd2456e9316640215b6a08bc728d1356f36d8
This commit is contained in:
Shawn Pearce 2016-01-14 16:11:15 -08:00
parent f52581c6a5
commit a290b822ab
5 changed files with 48 additions and 41 deletions

View File

@ -124,6 +124,17 @@ public void testGetRefs_EmptyDatabase() throws IOException {
assertTrue("no references", refdb.getRefs(ALL).isEmpty());
assertTrue("no references", refdb.getRefs(R_HEADS).isEmpty());
assertTrue("no references", refdb.getRefs(R_TAGS).isEmpty());
assertTrue("no references", refdb.getAdditionalRefs().isEmpty());
}
@Test
public void testGetAdditionalRefs() throws IOException {
update("refs/heads/master", A);
List<Ref> addl = refdb.getAdditionalRefs();
assertEquals(1, addl.size());
assertEquals("refs/txn/committed", addl.get(0).getName());
assertEquals(getTxnCommitted(), addl.get(0).getObjectId());
}
@Test

View File

@ -194,7 +194,7 @@ public boolean pack(ProgressMonitor pm) throws IOException {
refdb.refresh();
objdb.clearCache();
Collection<Ref> refsBefore = RefTreeNames.allRefs(refdb);
Collection<Ref> refsBefore = getAllRefs();
packsBefore = packsToRebuild();
if (packsBefore.isEmpty())
return true;
@ -235,6 +235,18 @@ else if (RefTreeNames.isRefTree(refdb, ref.getName()))
}
}
private Collection<Ref> getAllRefs() throws IOException {
Collection<Ref> refs = refdb.getRefs(RefDatabase.ALL).values();
List<Ref> addl = refdb.getAdditionalRefs();
if (!addl.isEmpty()) {
List<Ref> all = new ArrayList<>(refs.size() + addl.size());
all.addAll(refs);
all.addAll(addl);
return all;
}
return refs;
}
private List<DfsPackFile> packsToRebuild() throws IOException {
DfsPackFile[] packs = objdb.getPacks();
List<DfsPackFile> out = new ArrayList<DfsPackFile>(packs.length);

View File

@ -629,15 +629,16 @@ private Set<ObjectId> listRefLogObjects(Ref ref, long minTime) throws IOExceptio
}
/**
* Returns a map of all refs and additional refs (e.g. FETCH_HEAD,
* Returns a collection of all refs and additional refs (e.g. FETCH_HEAD,
* MERGE_HEAD, ...)
*
* @return a map where names of refs point to ref objects
* @return a collection of refs pointing to live objects.
* @throws IOException
*/
private Collection<Ref> getAllRefs() throws IOException {
Collection<Ref> refs = RefTreeNames.allRefs(repo.getRefDatabase());
List<Ref> addl = repo.getRefDatabase().getAdditionalRefs();
RefDatabase refdb = repo.getRefDatabase();
Collection<Ref> refs = refdb.getRefs(RefDatabase.ALL).values();
List<Ref> addl = refdb.getAdditionalRefs();
if (!addl.isEmpty()) {
List<Ref> all = new ArrayList<>(refs.size() + addl.size());
all.addAll(refs);

View File

@ -47,6 +47,8 @@
import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -250,7 +252,23 @@ private static ObjectId idOf(@Nullable Ref src) {
@Override
public List<Ref> getAdditionalRefs() throws IOException {
return Collections.emptyList();
Collection<Ref> txnRefs;
if (txnNamespace != null) {
txnRefs = bootstrap.getRefs(txnNamespace).values();
} else {
Ref r = bootstrap.exactRef(txnCommitted);
if (r != null && r.getObjectId() != null) {
txnRefs = Collections.singleton(r);
} else {
txnRefs = Collections.emptyList();
}
}
List<Ref> otherRefs = bootstrap.getAdditionalRefs();
List<Ref> all = new ArrayList<>(txnRefs.size() + otherRefs.size());
all.addAll(txnRefs);
all.addAll(otherRefs);
return all;
}
@Override

View File

@ -43,14 +43,6 @@
package org.eclipse.jgit.internal.storage.reftree;
import static org.eclipse.jgit.lib.RefDatabase.ALL;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
/** Magic reference name logic for RefTrees. */
@ -92,33 +84,6 @@ public static boolean isRefTree(RefDatabase refdb, String ref) {
return false;
}
/**
* Snapshot all references from a RefTreeDatabase and its bootstrap.
* <p>
* There may be name conflicts with multiple {@link Ref} objects containing
* the same name in the returned collection.
*
* @param refdb
* database instance.
* @return all known references.
* @throws IOException
* references cannot be enumerated.
*/
public static Collection<Ref> allRefs(RefDatabase refdb)
throws IOException {
Collection<Ref> refs = refdb.getRefs(ALL).values();
if (!(refdb instanceof RefTreeDatabase)) {
return refs;
}
RefDatabase bootstrap = ((RefTreeDatabase) refdb).getBootstrap();
Collection<Ref> br = bootstrap.getRefs(ALL).values();
List<Ref> all = new ArrayList<>(refs.size() + br.size());
all.addAll(refs);
all.addAll(br);
return all;
}
private RefTreeNames() {
}
}