Offer ObjectReaders advice about a RevWalk

By giving the reader information about the roots of a revision
traversal, some readers may be able to prefetch information from
their backing store using background threads in order to reduce
data access latency.  However this isn't typically necessary so
the default reader implementation doesn't react to the advice.

Change-Id: I72c6cbd05cff7d8506826015f50d9f57d5cda77e
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
Shawn O. Pearce 2010-07-29 19:52:36 -07:00
parent b85af06324
commit 11a5bef8b1
6 changed files with 70 additions and 3 deletions

View File

@ -44,9 +44,13 @@
package org.eclipse.jgit.lib;
import java.io.IOException;
import java.util.Collection;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.pack.ObjectReuseAsIs;
/**
@ -173,6 +177,44 @@ public long getObjectSize(AnyObjectId objectId, int typeHint)
return open(objectId, typeHint).getSize();
}
/**
* Advice from a {@link RevWalk} that a walk is starting from these roots.
*
* @param walk
* the revision pool that is using this reader.
* @param roots
* starting points of the revision walk. The starting points have
* their headers parsed, but might be missing bodies.
* @throws IOException
* the reader cannot initialize itself to support the walk.
*/
public void walkAdviceBeginCommits(RevWalk walk, Collection<RevCommit> roots)
throws IOException {
// Do nothing by default, most readers don't want or need advice.
}
/**
* Advice from an {@link ObjectWalk} that trees will be traversed.
*
* @param ow
* the object pool that is using this reader.
* @param min
* the first commit whose root tree will be read.
* @param max
* the last commit whose root tree will be read.
* @throws IOException
* the reader cannot initialize itself to support the walk.
*/
public void walkAdviceBeginTrees(ObjectWalk ow, RevCommit min, RevCommit max)
throws IOException {
// Do nothing by default, most readers don't want or need advice.
}
/** Advice from that a walk is over. */
public void walkAdviceEnd() {
// Do nothing by default, most readers don't want or need advice.
}
/**
* Release any resources used by this reader.
* <p>

View File

@ -137,6 +137,7 @@ RevCommit next() throws MissingObjectException,
for (;;) {
final RevCommit c = pending.next();
if (c == null) {
walker.reader.walkAdviceEnd();
walker.reader.release();
return null;
}

View File

@ -91,6 +91,10 @@ public class ObjectWalk extends RevWalk {
private RevObject last;
private RevCommit firstCommit;
private RevCommit lastCommit;
/**
* Create a new revision and object walker for a given repository.
*
@ -235,6 +239,9 @@ public RevCommit next() throws MissingObjectException,
}
continue;
}
if (firstCommit == null)
firstCommit = r;
lastCommit = r;
pendingObjects.add(r.getTree());
return r;
}
@ -295,11 +302,19 @@ public RevObject nextObject() throws MissingObjectException,
treeWalk = treeWalk.next();
}
if (firstCommit != null) {
reader.walkAdviceBeginTrees(this, firstCommit, lastCommit);
firstCommit = null;
lastCommit = null;
}
last = null;
for (;;) {
final RevObject o = pendingObjects.next();
if (o == null)
if (o == null) {
reader.walkAdviceEnd();
return null;
}
if ((o.flags & SEEN) != 0)
continue;
o.flags |= SEEN;
@ -403,6 +418,8 @@ public void dispose() {
treeWalk = new CanonicalTreeParser();
currentTree = null;
last = null;
firstCommit = null;
lastCommit = null;
}
@Override
@ -412,6 +429,8 @@ protected void reset(final int retainFlags) {
treeWalk = new CanonicalTreeParser();
currentTree = null;
last = null;
firstCommit = null;
lastCommit = null;
}
private void addObject(final RevObject o) {

View File

@ -128,7 +128,9 @@ RevCommit next() throws MissingObjectException,
for (;;) {
final RevCommit c = pending.next();
if (c == null) {
walker.reader.release();
walker.reader.walkAdviceEnd();
if (!(walker instanceof ObjectWalk))
walker.reader.release();
return null;
}
@ -174,6 +176,7 @@ else if (canDispose)
c.disposeBody();
}
} catch (StopWalkException swe) {
walker.reader.walkAdviceEnd();
walker.reader.release();
pending.clear();
return null;

View File

@ -172,7 +172,7 @@ public class RevWalk implements Iterable<RevCommit> {
int carryFlags = UNINTERESTING;
private final ArrayList<RevCommit> roots;
final ArrayList<RevCommit> roots;
AbstractRevQueue queue;

View File

@ -85,6 +85,8 @@ RevCommit next() throws MissingObjectException,
final TreeFilter tf = w.getTreeFilter();
AbstractRevQueue q = walker.queue;
w.reader.walkAdviceBeginCommits(w, w.roots);
if (rf == RevFilter.MERGE_BASE) {
// Computing for merge bases is a special case and does not
// use the bulk of the generator pipeline.