use of org.locationtech.geogig.api.Bucket in project GeoGig by boundlessgeo.
the class PreOrderDiffWalk method traverseBucketBucket.
/**
* Traverse two bucket trees and notify their differences to the {@code consumer}.
* <p>
* If this method is called than its guaranteed that the two bucket trees are note equal (one of
* them may be empty though), and that {@link Consumer#bucket} returned {@code true}
* <p>
* For each bucket index present in the joint set of the two trees buckets,
* {@link #traverseTree(Consumer, RevTree, RevTree, int)} will be called for the bucket trees
* that are not equal with {@code bucketDepth} incremented by one.
*
* @param consumer the callback object to receive diff events from the comparison of the two
* trees
* @param left the bucket tree at the left side of the comparison
* @param right the bucket tree at the right side of the comparison
* @param bucketDepth the current depth at which the comparison is evaluating these two bucket
* trees
* @see #traverseTree(Consumer, RevTree, RevTree, int)
* @precondition {@code !left.equals(right)}
* @precondition {@code left.isEmpty() || left.buckets().isPresent()}
* @precondition {@code right.isEmpty() || right.buckets().isPresent()}
*/
private void traverseBucketBucket(Consumer consumer, final RevTree left, final RevTree right, final int bucketDepth) {
checkState(left.isEmpty() || left.buckets().isPresent());
checkState(right.isEmpty() || right.buckets().isPresent());
ImmutableSortedMap<Integer, Bucket> lb = left.buckets().get();
ImmutableSortedMap<Integer, Bucket> rb = right.buckets().get();
TreeSet<Integer> availableIndexes = newTreeSet(union(lb.keySet(), rb.keySet()));
@Nullable Bucket lbucket;
@Nullable Bucket rbucket;
for (Integer index : availableIndexes) {
lbucket = lb.get(index);
rbucket = rb.get(index);
if (Objects.equal(lbucket, rbucket)) {
continue;
}
if (consumer.bucket(index.intValue(), bucketDepth, lbucket, rbucket)) {
RevTree ltree = lbucket == null ? RevTree.EMPTY : leftSource.getTree(lbucket.id());
RevTree rtree = rbucket == null ? RevTree.EMPTY : rightSource.getTree(rbucket.id());
traverseTree(consumer, ltree, rtree, bucketDepth + 1);
}
consumer.endBucket(index.intValue(), bucketDepth, lbucket, rbucket);
}
}
use of org.locationtech.geogig.api.Bucket in project GeoGig by boundlessgeo.
the class PreOrderDiffWalk method traverseBucketLeaf.
/**
* Compares a bucket tree (i.e. its size is greater than {@link RevTree#NORMALIZED_SIZE_LIMIT}
* and hence has been split into buckets) at the left side of the comparison, and a the
* {@link RevTree#children() children} nodes of a leaf tree at the right side of the comparison.
* <p>
* This happens when the left tree is much larger than the right tree
* <p>
* This traversal is symmetric to {@link #traverseLeafBucket} so be careful that any change made
* to this method shall have a matching change at {@link #traverseLeafBucket}
*
* @precondition {@code left.buckets().isPresent()}
*/
private void traverseBucketLeaf(final Consumer consumer, final RevTree left, final Iterator<Node> right, final int bucketDepth) {
checkState(left.buckets().isPresent());
final SortedMap<Integer, Bucket> leftBuckets = left.buckets().get();
final ListMultimap<Integer, Node> nodesByBucket = splitNodesToBucketsAtDepth(right, bucketDepth);
final SortedSet<Integer> bucketIndexes = Sets.newTreeSet(Sets.union(leftBuckets.keySet(), nodesByBucket.keySet()));
// get all buckets at once, to leverage ObjectDatabase optimizations
final Map<ObjectId, RevObject> bucketTrees;
bucketTrees = uniqueIndex(leftSource.getAll(transform(leftBuckets.values(), BUCKET_ID)), OBJECT_ID);
for (Integer bucketIndex : bucketIndexes) {
Bucket leftBucket = leftBuckets.get(bucketIndex);
// never returns null, but empty
List<Node> rightNodes = nodesByBucket.get(bucketIndex);
if (null == leftBucket) {
traverseLeafLeaf(consumer, Iterators.<Node>emptyIterator(), rightNodes.iterator());
} else if (rightNodes.isEmpty()) {
if (consumer.bucket(bucketIndex, bucketDepth, leftBucket, null)) {
RevTree leftTree = (RevTree) bucketTrees.get(leftBucket.id());
// traverseBucketBucket(consumer, leftTree, RevTree.EMPTY, bucketDepth);
traverseTree(consumer, leftTree, RevTree.EMPTY, bucketDepth + 1);
}
consumer.endBucket(bucketIndex, bucketDepth, leftBucket, null);
} else {
RevTree leftTree = (RevTree) bucketTrees.get(leftBucket.id());
if (leftTree.buckets().isPresent()) {
traverseBucketLeaf(consumer, leftTree, rightNodes.iterator(), bucketDepth + 1);
} else {
traverseLeafLeaf(consumer, leftTree.children(), rightNodes.iterator());
}
}
}
}
use of org.locationtech.geogig.api.Bucket in project GeoGig by boundlessgeo.
the class WriteTree2 method applyChanges.
private RevTree applyChanges(@Nullable final NodeRef leftTreeRef, @Nullable final NodeRef rightTreeRef) {
Preconditions.checkArgument(leftTreeRef != null || rightTreeRef != null, "either left or right tree shall be non null");
final ObjectDatabase repositoryDatabase = objectDatabase();
final String treePath = rightTreeRef == null ? leftTreeRef.path() : rightTreeRef.path();
final List<String> strippedPathFilters = stripParentAndFiltersThatDontApply(this.pathFilters, treePath);
// find the diffs that apply to the path filters
final ObjectId leftTreeId = leftTreeRef == null ? RevTree.EMPTY_TREE_ID : leftTreeRef.objectId();
final ObjectId rightTreeId = rightTreeRef == null ? RevTree.EMPTY_TREE_ID : rightTreeRef.objectId();
final Predicate<Bounded> existsFilter = new Predicate<Bounded>() {
private final ObjectDatabase targetDb = repositoryDatabase;
@Override
public boolean apply(Bounded input) {
ObjectId id = null;
if (input instanceof Node && TYPE.TREE.equals(((Node) input).getType())) {
id = ((Node) input).getObjectId();
} else if (input instanceof Bucket) {
Bucket b = (Bucket) input;
id = b.id();
}
if (id != null) {
if (targetDb.exists(id)) {
LOGGER.trace("Ignoring {}. Already exists in target database.", input);
return false;
}
}
return true;
}
};
DiffTree diffs = command(DiffTree.class).setRecursive(false).setReportTrees(false).setOldTree(leftTreeId).setNewTree(rightTreeId).setPathFilter(strippedPathFilters).setCustomFilter(existsFilter);
// move new blobs from the index to the repository (note: this could be parallelized)
Supplier<Iterator<Node>> nodesToMove = asNodeSupplierOfNewContents(diffs, strippedPathFilters);
command(DeepMove.class).setObjects(nodesToMove).call();
final StagingDatabase stagingDatabase = stagingDatabase();
final RevTree currentLeftTree = stagingDatabase.getTree(leftTreeId);
final RevTreeBuilder builder = currentLeftTree.builder(repositoryDatabase);
// remove the exists filter, we need to create the new trees taking into account all the
// nodes
diffs.setCustomFilter(null);
Iterator<DiffEntry> iterator = diffs.get();
if (!strippedPathFilters.isEmpty()) {
final Set<String> expected = Sets.newHashSet(strippedPathFilters);
iterator = Iterators.filter(iterator, new Predicate<DiffEntry>() {
@Override
public boolean apply(DiffEntry input) {
boolean applies;
if (input.isDelete()) {
applies = expected.contains(input.oldName());
} else {
applies = expected.contains(input.newName());
}
return applies;
}
});
}
for (; iterator.hasNext(); ) {
final DiffEntry diff = iterator.next();
if (diff.isDelete()) {
builder.remove(diff.oldName());
} else {
NodeRef newObject = diff.getNewObject();
Node node = newObject.getNode();
builder.put(node);
}
}
final RevTree newTree = builder.build();
repositoryDatabase.put(newTree);
return newTree;
}
Aggregations