Search in sources :

Example 21 with Bucket

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);
    }
}
Also used : Bucket(org.locationtech.geogig.api.Bucket) Nullable(javax.annotation.Nullable) RevTree(org.locationtech.geogig.api.RevTree)

Example 22 with Bucket

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());
            }
        }
    }
}
Also used : Bucket(org.locationtech.geogig.api.Bucket) ObjectId(org.locationtech.geogig.api.ObjectId) RevObject(org.locationtech.geogig.api.RevObject) Node(org.locationtech.geogig.api.Node) RevTree(org.locationtech.geogig.api.RevTree)

Example 23 with Bucket

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;
}
Also used : ObjectId(org.locationtech.geogig.api.ObjectId) Node(org.locationtech.geogig.api.Node) RevTreeBuilder(org.locationtech.geogig.api.RevTreeBuilder) Predicate(com.google.common.base.Predicate) NodeRef(org.locationtech.geogig.api.NodeRef) Bounded(org.locationtech.geogig.api.Bounded) ObjectDatabase(org.locationtech.geogig.storage.ObjectDatabase) Bucket(org.locationtech.geogig.api.Bucket) Iterator(java.util.Iterator) RevTree(org.locationtech.geogig.api.RevTree) StagingDatabase(org.locationtech.geogig.storage.StagingDatabase) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry)

Aggregations

Bucket (org.locationtech.geogig.api.Bucket)23 Node (org.locationtech.geogig.api.Node)18 RevTree (org.locationtech.geogig.api.RevTree)15 Test (org.junit.Test)8 TreeTestSupport.featureNode (org.locationtech.geogig.api.plumbing.diff.TreeTestSupport.featureNode)8 ObjectId (org.locationtech.geogig.api.ObjectId)6 Envelope (com.vividsolutions.jts.geom.Envelope)3 TreeMap (java.util.TreeMap)3 Bounded (org.locationtech.geogig.api.Bounded)3 Predicate (com.google.common.base.Predicate)2 ImmutableList (com.google.common.collect.ImmutableList)2 Builder (com.google.common.collect.ImmutableList.Builder)2 Map (java.util.Map)2 Nullable (javax.annotation.Nullable)2 SimpleFeatureTypeBuilder (org.geotools.feature.simple.SimpleFeatureTypeBuilder)2 RevObject (org.locationtech.geogig.api.RevObject)2 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)2 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1