use of org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk.Consumer in project GeoGig by boundlessgeo.
the class PreOrderDiffWalkTest method beforeTest.
@Before
public void beforeTest() {
leftSource = new HeapObjectDatabse();
rightSource = new HeapObjectDatabse();
leftSource.open();
rightSource.open();
consumer = mock(Consumer.class);
}
use of org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk.Consumer in project GeoGig by boundlessgeo.
the class PreOrderDiffWalkTest method testLeafBucketDeeper.
private void testLeafBucketDeeper(final int leftsize, final RevTree rightRoot, final int overlapCount) {
consumer = mock(Consumer.class);
// right tree has feature nodes "f0" to "f<rightsize-1>"
final int rightsize = (int) rightRoot.size();
// the left tree feature node names start at "f<rightsize - 100>", so there's a 100 node
// overlap
RevTree leftRoot = createFeaturesTree(leftSource, "f", leftsize, rightsize - overlapCount, true).build();
PreOrderDiffWalk visitor = new PreOrderDiffWalk(leftRoot, rightRoot, leftSource, rightSource);
// consume all
when(consumer.tree(any(Node.class), any(Node.class))).thenReturn(true);
when(consumer.bucket(anyInt(), anyInt(), any(Bucket.class), any(Bucket.class))).thenReturn(true);
visitor.walk(consumer);
// there's only the root tree
verify(consumer, times(1)).tree(any(Node.class), any(Node.class));
// there shall be <overlapCount> calls to feature with both non null args
verify(consumer, times(overlapCount)).feature((Node) notNull(), (Node) notNull());
final int expectedDeletes = leftsize - overlapCount;
final int expectedAdds = rightsize - overlapCount;
verify(consumer, times(expectedDeletes)).feature((Node) notNull(), (Node) isNull());
verify(consumer, times(expectedAdds)).feature((Node) isNull(), (Node) notNull());
}
use of org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk.Consumer in project GeoGig by boundlessgeo.
the class PreOrderDiffWalkTest method testBucketLeafDeeper.
private void testBucketLeafDeeper(final RevTree left, final int rightsize, final int overlapCount) {
consumer = mock(Consumer.class);
// left tree has feature nodes "f0" to "f<leftsize-1>"
final int leftsize = (int) left.size();
// the right tree feature node names start at "f<leftsize - 100>", so there's a 100 node
// overlap
RevTree right = createFeaturesTree(rightSource, "f", rightsize, leftsize - overlapCount, true).build();
PreOrderDiffWalk visitor = new PreOrderDiffWalk(left, right, leftSource, rightSource);
// consume all
when(consumer.tree(any(Node.class), any(Node.class))).thenReturn(true);
when(consumer.bucket(anyInt(), anyInt(), any(Bucket.class), any(Bucket.class))).thenReturn(true);
visitor.walk(consumer);
// there's only the root tree
verify(consumer, times(1)).tree(any(Node.class), any(Node.class));
// there shall be <overlapCount> calls to feature with both non null args
verify(consumer, times(overlapCount)).feature((Node) notNull(), (Node) notNull());
final int expectedDeletes = leftsize - overlapCount;
final int expectedAdds = rightsize - overlapCount;
verify(consumer, times(expectedDeletes)).feature((Node) notNull(), (Node) isNull());
verify(consumer, times(expectedAdds)).feature((Node) isNull(), (Node) notNull());
}
use of org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk.Consumer in project GeoGig by boundlessgeo.
the class PreOrderDiffWalkTest method getTreeDepth.
/**
*
*/
private int getTreeDepth(RevTree tree, ObjectDatabase source, final int depth) {
PreOrderDiffWalk visitor = new PreOrderDiffWalk(tree, RevTree.EMPTY, source, source);
final AtomicInteger maxDepth = new AtomicInteger();
visitor.walk(new Consumer() {
@Override
public boolean tree(Node left, Node right) {
return true;
}
@Override
public void feature(Node left, Node right) {
//
}
@Override
public boolean bucket(int bucketIndex, int bucketDepth, Bucket left, Bucket right) {
// use +1 cause we want the
maxDepth.set(Math.max(maxDepth.get(), bucketDepth + 1));
// zero-based level index
return true;
}
@Override
public void endTree(Node left, Node right) {
// TODO Auto-generated method stub
}
@Override
public void endBucket(int bucketIndex, int bucketDepth, Bucket left, Bucket right) {
// TODO Auto-generated method stub
}
});
return maxDepth.get();
}
use of org.locationtech.geogig.api.plumbing.diff.PreOrderDiffWalk.Consumer in project GeoGig by boundlessgeo.
the class DiffTree method _call.
/**
* Finds differences between the two specified trees.
*
* @return an iterator to a set of differences between the two trees
* @see DiffEntry
*/
@Override
protected Iterator<DiffEntry> _call() throws IllegalArgumentException {
checkNotNull(oldRefSpec, "old version not specified");
checkNotNull(newRefSpec, "new version not specified");
final RevTree oldTree = resolveTree(oldRefSpec);
final RevTree newTree = resolveTree(newRefSpec);
if (oldTree.equals(newTree)) {
return Iterators.emptyIterator();
}
ObjectDatabase leftSource = resolveSource(oldTree.getId());
ObjectDatabase rightSource = resolveSource(newTree.getId());
final PreOrderDiffWalk visitor = new PreOrderDiffWalk(oldTree, newTree, leftSource, rightSource);
final BlockingQueue<DiffEntry> queue = new ArrayBlockingQueue<>(100);
final DiffEntryProducer diffProducer = new DiffEntryProducer(queue);
diffProducer.setReportTrees(this.reportTrees);
diffProducer.setRecursive(this.recursive);
final List<RuntimeException> producerErrors = new LinkedList<>();
Thread producerThread = new Thread("DiffTree producer thread") {
@Override
public void run() {
Consumer consumer = diffProducer;
if (customFilter != null) {
// evaluated the latest
consumer = new PreOrderDiffWalk.FilteringConsumer(consumer, customFilter);
}
if (changeTypeFilter != null) {
consumer = new ChangeTypeFilteringDiffConsumer(changeTypeFilter, consumer);
}
if (boundsFilter != null) {
consumer = new BoundsFilteringDiffConsumer(boundsFilter, consumer, stagingDatabase());
}
if (!pathFilters.isEmpty()) {
// evaluated the former
consumer = new PathFilteringDiffConsumer(pathFilters, consumer);
}
try {
visitor.walk(consumer);
} catch (RuntimeException e) {
LOGGER.error("Error traversing diffs", e);
producerErrors.add(e);
} finally {
diffProducer.finished = true;
}
}
};
producerThread.setDaemon(true);
producerThread.start();
Iterator<DiffEntry> consumerIterator = new AbstractIterator<DiffEntry>() {
@Override
protected DiffEntry computeNext() {
if (!producerErrors.isEmpty()) {
throw new RuntimeException("Error in producer thread", producerErrors.get(0));
}
BlockingQueue<DiffEntry> entries = queue;
boolean finished = diffProducer.isFinished();
boolean empty = entries.isEmpty();
while (!finished || !empty) {
try {
DiffEntry entry = entries.poll(10, TimeUnit.MILLISECONDS);
if (entry != null) {
return entry;
}
finished = diffProducer.isFinished();
empty = entries.isEmpty();
} catch (InterruptedException e) {
throw Throwables.propagate(e);
}
}
return endOfData();
}
@Override
protected void finalize() {
diffProducer.finished = true;
}
};
return consumerIterator;
}
Aggregations