jackrabbit-oak-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Angela Schreiber <anch...@adobe.com>
Subject Re: svn commit: r1522553 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/mongomk/ test/java/org/apache/jackrabbit/oak/plugins/mongomk/
Date Thu, 12 Sep 2013 17:12:13 GMT
hi marcel

could it be that this commit is related to the following test failure?
i experience it in a up to date checkout of the trunk.

regards
angela

concurrent[1](org.apache.jackrabbit.oak.jcr.ConcurrentFileOperationsTest)
Time elapsed: 0.473 sec  <<< ERROR!
javax.jcr.RepositoryException: OakKernel0001: Failed to merge changes to
the underlying MicroKernel
        at
org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException(C
ommitFailedException.java:242)
        at
org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException(C
ommitFailedException.java:207)
        at
org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.newRepositoryExcepti
on(SessionDelegate.java:434)
        at
org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save(SessionDelegate
.java:297)
        at
org.apache.jackrabbit.oak.jcr.session.SessionImpl$8.perform(SessionImpl.jav
a:399)
        at
org.apache.jackrabbit.oak.jcr.session.SessionImpl$8.perform(SessionImpl.jav
a:396)
        at
org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.perform(SessionDeleg
ate.java:124)
        at
org.apache.jackrabbit.oak.jcr.session.SessionImpl.perform(SessionImpl.java:
117)
        at
org.apache.jackrabbit.oak.jcr.session.SessionImpl.save(SessionImpl.java:396
)
        at
org.apache.jackrabbit.oak.jcr.ConcurrentFileOperationsTest$1.run(Concurrent
FileOperationsTest.java:103)
        at java.lang.Thread.run(Thread.java:680)
Caused by: org.apache.jackrabbit.oak.api.CommitFailedException:
OakKernel0001: Failed to merge changes to the underlying MicroKernel
        at
org.apache.jackrabbit.oak.kernel.KernelNodeStoreBranch$Persisted.merge(Kern
elNodeStoreBranch.java:384)
        at
org.apache.jackrabbit.oak.kernel.KernelNodeStoreBranch.merge(KernelNodeStor
eBranch.java:136)
        at
org.apache.jackrabbit.oak.core.AbstractRoot$2.run(AbstractRoot.java:247)
        at
org.apache.jackrabbit.oak.core.AbstractRoot$2.run(AbstractRoot.java:243)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:337)
        at
org.apache.jackrabbit.oak.core.AbstractRoot.commit(AbstractRoot.java:242)
        at
org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save(SessionDelegate
.java:295)
        ... 7 more
Caused by: org.apache.jackrabbit.mk.api.MicroKernelException: Conflicting
concurrent change. Update operation failed: key: 0:/ update
{_collisions.r1411315f24a-0-1=CONTAINS_MAP_ENTRY false,
_collisions.r1411315f251-0-1=CONTAINS_MAP_ENTRY false,
_collisions.r1411315f3f6-0-1=CONTAINS_MAP_ENTRY false,
_collisions.r1411315f402-0-1=CONTAINS_MAP_ENTRY false, _modified=SET
275800941, _revisions.r1411315f24a-0-1=SET_MAP_ENTRY c-r1411315f404-0-1,
_revisions.r1411315f251-0-1=SET_MAP_ENTRY c-r1411315f404-0-1,
_revisions.r1411315f3f6-0-1=SET_MAP_ENTRY c-r1411315f404-0-1,
_revisions.r1411315f402-0-1=SET_MAP_ENTRY c-r1411315f404-0-1}
        at
org.apache.jackrabbit.oak.plugins.mongomk.MongoMK.merge(MongoMK.java:1130)
        at
org.apache.jackrabbit.oak.kernel.KernelNodeStore.merge(KernelNodeStore.java
:208)
        at
org.apache.jackrabbit.oak.kernel.KernelNodeStoreBranch$Persisted.merge(Kern
elNodeStoreBranch.java:378)
        ... 14 more






On 9/12/13 2:45 PM, "mreutegg@apache.org" <mreutegg@apache.org> wrote:

>Author: mreutegg
>Date: Thu Sep 12 12:45:19 2013
>New Revision: 1522553
>
>URL: http://svn.apache.org/r1522553
>Log:
>OAK-926: MongoMK: split documents when they are too large
>- Generalize access to previous documents (WIP)
>
>Added:
>
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java   (with props)
>
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java   (with props)
>Modified:
>
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/NodeDocument.java
>
>jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/DocumentSplitTest.java
>
>Modified:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/NodeDocument.java
>URL:
>http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/o
>rg/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java?rev=1522553&r1=
>1522552&r2=1522553&view=diff
>==========================================================================
>====
>---
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/NodeDocument.java (original)
>+++
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/NodeDocument.java Thu Sep 12 12:45:19 2013
>@@ -16,8 +16,6 @@
>  */
> package org.apache.jackrabbit.oak.plugins.mongomk;
>
>-import java.util.AbstractMap;
>-import java.util.AbstractSet;
> import java.util.ArrayList;
> import java.util.Collections;
> import java.util.Comparator;
>@@ -44,10 +42,8 @@ import org.slf4j.LoggerFactory;
> import com.google.common.base.Function;
> import com.google.common.base.Predicate;
> import com.google.common.collect.Iterables;
>-import com.google.common.collect.Iterators;
> import com.google.common.collect.Maps;
>
>-import static com.google.common.base.Preconditions.checkArgument;
> import static com.google.common.base.Preconditions.checkNotNull;
>
> /**
>@@ -186,7 +182,7 @@ public class NodeDocument extends Docume
>      */
>     public boolean containsRevision(@Nonnull Revision revision) {
>         String rev = checkNotNull(revision).toString();
>-        if (getRevisionsMap().containsKey(rev)) {
>+        if (getLocalRevisions().containsKey(rev)) {
>             return true;
>         }
>         for (NodeDocument prev : getPreviousDocs(revision)) {
>@@ -219,7 +215,7 @@ public class NodeDocument extends Docume
>     public SortedMap<Revision, Revision>
>getUncommittedRevisions(RevisionContext context) {
>         // only look at revisions in this document.
>         // uncommitted revisions are not split off
>-        Map<String, String> valueMap = getRevisionsMap();
>+        Map<String, String> valueMap = getLocalRevisions();
>         SortedMap<Revision, Revision> revisions =
>                 new TreeMap<Revision,
>Revision>(context.getRevisionComparator());
>         for (Map.Entry<String, String> commit : valueMap.entrySet()) {
>@@ -244,11 +240,7 @@ public class NodeDocument extends Docume
>      */
>     @CheckForNull
>     public String getCommitRootPath(String revision) {
>-        @SuppressWarnings("unchecked")
>-        Map<String, Integer> valueMap = (Map<String, Integer>)
>get(COMMIT_ROOT);
>-        if (valueMap == null) {
>-            return null;
>-        }
>+        Map<String, Integer> valueMap = getCommitRoot();
>         Integer depth = valueMap.get(revision);
>         if (depth != null) {
>             String p = Utils.getPathFromId(getId());
>@@ -274,13 +266,9 @@ public class NodeDocument extends Docume
>                                       CollisionHandler handler) {
>         SortedSet<String> revisions = new
>TreeSet<String>(Collections.reverseOrder());
>         revisions.addAll(getRevisions().keySet());
>-        if (data.containsKey(COMMIT_ROOT)) {
>-            revisions.addAll(((Map<String, Integer>)
>get(COMMIT_ROOT)).keySet());
>-        }
>-        Map<String, String> deletedMap = (Map<String, String>)
>get(DELETED);
>-        if (deletedMap != null) {
>-            revisions.addAll(deletedMap.keySet());
>-        }
>+        revisions.addAll(getCommitRoot().keySet());
>+        Map<String, String> deletedMap = getDeleted();
>+        revisions.addAll(deletedMap.keySet());
>         Revision newestRev = null;
>         for (String r : revisions) {
>             Revision propRev = Revision.fromString(r);
>@@ -304,12 +292,10 @@ public class NodeDocument extends Docume
>         if (newestRev == null) {
>             return null;
>         }
>-        if (deletedMap != null) {
>-            String value = deletedMap.get(newestRev.toString());
>-            if ("true".equals(value)) {
>-                // deleted in the newest revision
>-                return null;
>-            }
>+        String value = deletedMap.get(newestRev.toString());
>+        if ("true".equals(value)) {
>+            // deleted in the newest revision
>+            return null;
>         }
>         return newestRev;
>     }
>@@ -444,9 +430,8 @@ public class NodeDocument extends Docume
>     public boolean isDeleted(RevisionContext context,
>                              Revision readRevision,
>                              Set<Revision> validRevisions) {
>-        @SuppressWarnings("unchecked")
>-        Map<String, String> valueMap = (Map<String, String>)
>get(NodeDocument.DELETED);
>-        if (valueMap == null) {
>+        Map<String, String> valueMap = getDeleted();
>+        if (valueMap.isEmpty()) {
>             return false;
>         }
>         if (valueMap instanceof NavigableMap) {
>@@ -487,9 +472,8 @@ public class NodeDocument extends Docume
>     @CheckForNull
>     public Revision getLiveRevision(RevisionContext context, Revision
>maxRev,
>                                     Set<Revision> validRevisions) {
>-        @SuppressWarnings("unchecked")
>-        Map<String, String> valueMap = (Map<String, String>)
>get(NodeDocument.DELETED);
>-        if (valueMap == null) {
>+        Map<String, String> valueMap = getDeleted();
>+        if (valueMap.isEmpty()) {
>             return null;
>         }
>         // first, search the newest deleted revision
>@@ -552,13 +536,10 @@ public class NodeDocument extends Docume
>                                  @Nonnull Revision baseRevision,
>                                  @Nonnull RevisionContext context) {
>         // did existence of node change after baseRevision?
>-        @SuppressWarnings("unchecked")
>-        Map<String, String> deleted = (Map<String, String>) get(DELETED);
>-        if (deleted != null) {
>-            for (Map.Entry<String, String> entry : deleted.entrySet()) {
>-                if (isRevisionNewer(context,
>Revision.fromString(entry.getKey()), baseRevision)) {
>-                    return true;
>-                }
>+        Map<String, String> deleted = getDeleted();
>+        for (Map.Entry<String, String> entry : deleted.entrySet()) {
>+            if (isRevisionNewer(context,
>Revision.fromString(entry.getKey()), baseRevision)) {
>+                return true;
>             }
>         }
>
>@@ -615,7 +596,7 @@ public class NodeDocument extends Docume
>         }
>         NavigableMap<Revision, String> splitRevs
>                 = new TreeMap<Revision,
>String>(context.getRevisionComparator());
>-        Map<String, String> revisions = getRevisionsMap();
>+        Map<String, String> revisions = getLocalRevisions();
>         // only consider if there are enough revisions
>         if (revisions.size() > REVISIONS_SPLIT_OFF_SIZE) {
>             // collect commits of this cluster node after the
>@@ -690,6 +671,88 @@ public class NodeDocument extends Docume
>         return super.transformAndSeal(map, key, level);
>     }
>
>+    /**
>+     * Returns previous revision ranges for this document. The revision
>keys are
>+     * sorted descending, newest first!
>+     *
>+     * @return the previous ranges for this document.
>+     */
>+    @Nonnull
>+    SortedMap<Revision, Range> getPreviousRanges() {
>+        @SuppressWarnings("unchecked")
>+        SortedMap<Revision, Range> previous = (SortedMap<Revision,
>Range>) get(PREVIOUS);
>+        if (previous == null) {
>+            previous = EMPTY_RANGE_MAP;
>+        }
>+        return previous;
>+    }
>+
>+    /**
>+     * Returns previous {@link NodeDocument}, which include the given
>revision.
>+     * If the <code>revision</code> is <code>null</code>, then
all
>previous
>+     * documents are returned.
>+     *
>+     * @param revision the revision to match or <code>null</code>.
>+     * @return previous documents.
>+     */
>+    Iterable<NodeDocument> getPreviousDocs(final @Nullable Revision
>revision) {
>+        Iterable<NodeDocument> docs = Iterables.transform(
>+                Iterables.filter(getPreviousRanges().entrySet(),
>+                        new Predicate<Map.Entry<Revision, Range>>() {
>+                            @Override
>+                            public boolean apply(Map.Entry<Revision,
>Range> input) {
>+                                return revision == null ||
>input.getValue().includes(revision);
>+                            }
>+                        }), new Function<Map.Entry<Revision, Range>,
>NodeDocument>() {
>+            @Nullable
>+            @Override
>+            public NodeDocument apply(Map.Entry<Revision, Range> input) {
>+                Revision r = input.getKey();
>+                String prevId = Utils.getPreviousIdFor(getId(), r);
>+                NodeDocument prev = store.find(Collection.NODES, prevId);
>+                if (prev == null) {
>+                    LOG.warn("Document with previous revisions not
>found: " + prevId);
>+                }
>+                return prev;
>+            }
>+        });
>+        // filter out null docs and check if the revision is actually in
>there
>+        return Iterables.filter(docs, new Predicate<NodeDocument>() {
>+            @Override
>+            public boolean apply(@Nullable NodeDocument input) {
>+                if (input == null) {
>+                    return false;
>+                }
>+                return revision == null ||
>input.containsRevision(revision.toString());
>+            }
>+        });
>+    }
>+
>+    /**
>+     * Returns the local value map for the given key. Returns
><code>null</code>
>+     * if no such value map exists.
>+     *
>+     * @param key the key.
>+     * @return local value map.
>+     */
>+    @Nonnull
>+    Map<String, String> getLocalMap(String key) {
>+        @SuppressWarnings("unchecked")
>+        Map<String, String> map = (Map<String, String>) get(key);
>+        if (map == null) {
>+            map = Collections.emptyMap();
>+        }
>+        return map;
>+    }
>+
>+    /**
>+     * @return the {@link #REVISIONS} stored on this document.
>+     */
>+    @Nonnull
>+    Map<String, String> getLocalRevisions() {
>+        return getLocalMap(REVISIONS);
>+    }
>+
>     //-------------------------< UpdateOp modifiers
>>---------------------------
>
>     public static void setModified(@Nonnull UpdateOp op,
>@@ -745,15 +808,12 @@ public class NodeDocument extends Docume
>             return this;
>         }
>         // check commit root
>-        @SuppressWarnings("unchecked")
>-        Map<String, Integer> commitRoot = (Map<String, Integer>)
>get(COMMIT_ROOT);
>+        Map<String, Integer> commitRoot = getCommitRoot();
>         String commitRootPath = null;
>-        if (commitRoot != null) {
>-            Integer depth = commitRoot.get(rev.toString());
>-            if (depth != null) {
>-                String p = Utils.getPathFromId(getId());
>-                commitRootPath = PathUtils.getAncestorPath(p,
>PathUtils.getDepth(p) - depth);
>-            }
>+        Integer depth = commitRoot.get(rev.toString());
>+        if (depth != null) {
>+            String p = Utils.getPathFromId(getId());
>+            commitRootPath = PathUtils.getAncestorPath(p,
>PathUtils.getDepth(p) - depth);
>         }
>         if (commitRootPath == null) {
>             // shouldn't happen, either node is commit root for a
>revision
>@@ -835,11 +895,11 @@ public class NodeDocument extends Docume
>     @CheckForNull
>     private String getCommitValue(Revision revision) {
>         String r = revision.toString();
>-        String value = getRevisionsMap().get(r);
>+        String value = getLocalRevisions().get(r);
>         if (value == null) {
>             // check previous
>             for (NodeDocument prev : getPreviousDocs(revision)) {
>-                value = prev.getRevisionsMap().get(r);
>+                value = prev.getLocalRevisions().get(r);
>                 if (value != null) {
>                     break;
>                 }
>@@ -907,193 +967,23 @@ public class NodeDocument extends Docume
>         return value;
>     }
>
>-    Map<String, String> getRevisions() {
>-        final Map<String, String> map = getRevisionsMap();
>-        if (!data.containsKey(PREVIOUS)) {
>-            return map;
>-        }
>-        final Set<Map.Entry<String, String>> revisions
>-                = new AbstractSet<Map.Entry<String, String>>() {
>-
>-            @Override
>-            @Nonnull
>-            public Iterator<Map.Entry<String, String>> iterator() {
>-                return Iterators.concat(map.entrySet().iterator(),
>-                        Iterators.concat(new
>Iterator<Iterator<Map.Entry<String, String>>>() {
>-                            private final Iterator<NodeDocument> previous
>-                                    = getPreviousDocs(null).iterator();
>-
>-                            @Override
>-                            public boolean hasNext() {
>-                                return previous.hasNext();
>-                            }
>-
>-                            @Override
>-                            public Iterator<Map.Entry<String, String>>
>next() {
>-                                return
>previous.next().getRevisions().entrySet().iterator();
>-                            }
>-
>-                            @Override
>-                            public void remove() {
>-                                throw new
>UnsupportedOperationException();
>-                            }
>-                        }));
>-            }
>-
>-            @Override
>-            public int size() {
>-                int size = map.size();
>-                for (NodeDocument prev : getPreviousDocs(null)) {
>-                    size += prev.getRevisions().size();
>-                }
>-                return size;
>-            }
>-        };
>-        return new AbstractMap<String, String>() {
>-
>-            private final Map<String, String> map = getRevisionsMap();
>-
>-            @Override
>-            @Nonnull
>-            public Set<Entry<String, String>> entrySet() {
>-                return revisions;
>-            }
>-
>-            @Override
>-            public String get(Object key) {
>-                // first check revisions map of this document
>-                String value = map.get(key);
>-                if (value != null) {
>-                    return value;
>-                }
>-                Revision r = Revision.fromString(key.toString());
>-                for (NodeDocument prev : getPreviousDocs(r)) {
>-                    value = prev.getRevisions().get(key);
>-                    if (value != null) {
>-                        return value;
>-                    }
>-                }
>-                // not found
>-                return null;
>-            }
>-
>-            @Override
>-            public boolean containsKey(Object key) {
>-                // can use get()
>-                // the revisions map does not have null values
>-                return get(key) != null;
>-            }
>-
>-        };
>-    }
>-
>     @Nonnull
>-    Map<String, String> getRevisionsMap() {
>-        @SuppressWarnings("unchecked")
>-        Map<String, String> map = (Map<String, String>) get(REVISIONS);
>-        if (map == null) {
>-            map = Collections.emptyMap();
>-        }
>-        return map;
>+    private Map<String, String> getRevisions() {
>+        return ValueMap.create(this, REVISIONS);
>     }
>
>-    /**
>-     * Returns previous {@link NodeDocument}, which include the given
>revision.
>-     * If the <code>revision</code> is <code>null</code>, then
all
>previous
>-     * documents are returned.
>-     *
>-     * @param revision the revision to match or <code>null</code>.
>-     * @return previous documents.
>-     */
>-    Iterable<NodeDocument> getPreviousDocs(@Nullable final Revision
>revision) {
>-        Iterable<NodeDocument> docs = Iterables.transform(
>-                Iterables.filter(getPreviousRanges().entrySet(),
>-                new Predicate<Map.Entry<Revision, Range>>() {
>-            @Override
>-            public boolean apply(Map.Entry<Revision, Range> input) {
>-                return revision == null ||
>input.getValue().includes(revision);
>-            }
>-        }), new Function<Map.Entry<Revision, Range>, NodeDocument>() {
>-            @Nullable
>-            @Override
>-            public NodeDocument apply(Map.Entry<Revision, Range> input) {
>-                Revision r = input.getKey();
>-                String prevId = Utils.getPreviousIdFor(getId(), r);
>-                NodeDocument prev = store.find(Collection.NODES, prevId);
>-                if (prev == null) {
>-                    LOG.warn("Document with previous revisions not
>found: " + prevId);
>-                }
>-                return prev;
>-            }
>-        });
>-        // filter out null docs and check if the revision is actually in
>there
>-        return Iterables.filter(docs, new Predicate<NodeDocument>() {
>-            @Override
>-            public boolean apply(@Nullable NodeDocument input) {
>-                if (input == null) {
>-                    return false;
>-                }
>-                return revision == null ||
>input.containsRevision(revision.toString());
>-            }
>-        });
>+    @Nonnull
>+    private Map<String, String> getDeleted() {
>+        return ValueMap.create(this, DELETED);
>     }
>
>-    /**
>-     * Returns previous revision ranges for this document. The revision
>keys are
>-     * sorted descending, newest first!
>-     *
>-     * @return the previous ranges for this document.
>-     */
>     @Nonnull
>-    private SortedMap<Revision, Range> getPreviousRanges() {
>+    private Map<String, Integer> getCommitRoot() {
>         @SuppressWarnings("unchecked")
>-        SortedMap<Revision, Range> previous = (SortedMap<Revision,
>Range>) get(PREVIOUS);
>-        if (previous == null) {
>-            previous = EMPTY_RANGE_MAP;
>-        }
>-        return previous;
>-    }
>-
>-    /**
>-     * A range of revisions.
>-     */
>-    private static final class Range {
>-
>-        final Revision high;
>-        final Revision low;
>-
>-        /**
>-         * A range of revisions, with both inclusive bounds.
>-         *
>-         * @param high the high bound.
>-         * @param low the low bound.
>-         */
>-        Range(@Nonnull Revision high, @Nonnull Revision low) {
>-            this.high = checkNotNull(high);
>-            this.low = checkNotNull(low);
>-            checkArgument(high.getClusterId() == low.getClusterId(),
>-                    "Revisions from have the same clusterId");
>-            checkArgument(high.compareRevisionTime(low) > 0,
>-                    "High Revision must be later than low Revision");
>-        }
>-
>-        /**
>-         * Returns <code>true</code> if the given revision is within
>this range.
>-         *
>-         * @param r the revision to check.
>-         * @return <code>true</code> if within this range;
><code>false</code>
>-         * otherwise.
>-         */
>-        boolean includes(Revision r) {
>-            return high.compareRevisionTime(r) >= 0
>-                    && low.compareRevisionTime(r) <= 0;
>-        }
>-
>-        @Override
>-        public String toString() {
>-            return low.toString();
>+        Map<String, Integer> commitRoot = (Map<String, Integer>)
>get(COMMIT_ROOT);
>+        if (commitRoot == null) {
>+            commitRoot = Collections.emptyMap();
>         }
>-
>+        return commitRoot;
>     }
>-
> }
>
>Added:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java
>URL:
>http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/o
>rg/apache/jackrabbit/oak/plugins/mongomk/Range.java?rev=1522553&view=auto
>==========================================================================
>====
>---
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java (added)
>+++
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java Thu Sep 12 12:45:19 2013
>@@ -0,0 +1,63 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one or more
>+ * contributor license agreements.  See the NOTICE file distributed with
>+ * this work for additional information regarding copyright ownership.
>+ * The ASF licenses this file to You under the Apache License, Version
>2.0
>+ * (the "License"); you may not use this file except in compliance with
>+ * the License.  You may obtain a copy of the License at
>+ *
>+ *      http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing, software
>+ * distributed under the License is distributed on an "AS IS" BASIS,
>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>implied.
>+ * See the License for the specific language governing permissions and
>+ * limitations under the License.
>+ */
>+package org.apache.jackrabbit.oak.plugins.mongomk;
>+
>+import javax.annotation.Nonnull;
>+
>+import static com.google.common.base.Preconditions.checkArgument;
>+import static com.google.common.base.Preconditions.checkNotNull;
>+
>+/**
>+* A revision range for {@link NodeDocument#PREVIOUS} documents.
>+*/
>+final class Range {
>+
>+    final Revision high;
>+    final Revision low;
>+
>+    /**
>+     * A range of revisions, with both inclusive bounds.
>+     *
>+     * @param high the high bound.
>+     * @param low the low bound.
>+     */
>+    Range(@Nonnull Revision high, @Nonnull Revision low) {
>+        this.high = checkNotNull(high);
>+        this.low = checkNotNull(low);
>+        checkArgument(high.getClusterId() == low.getClusterId(),
>+                "Revisions from have the same clusterId");
>+        checkArgument(high.compareRevisionTime(low) > 0,
>+                "High Revision must be later than low Revision");
>+    }
>+
>+    /**
>+     * Returns <code>true</code> if the given revision is within this
>range.
>+     *
>+     * @param r the revision to check.
>+     * @return <code>true</code> if within this range; <code>false</code>
>+     * otherwise.
>+     */
>+    boolean includes(Revision r) {
>+        return high.compareRevisionTime(r) >= 0
>+                && low.compareRevisionTime(r) <= 0;
>+    }
>+
>+    @Override
>+    public String toString() {
>+        return low.toString();
>+    }
>+}
>
>Propchange:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java
>--------------------------------------------------------------------------
>----
>    svn:eol-style = native
>
>Propchange:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/Range.java
>--------------------------------------------------------------------------
>----
>    svn:keywords = Author Date Id Revision Rev URL
>
>Added:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java
>URL:
>http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/o
>rg/apache/jackrabbit/oak/plugins/mongomk/ValueMap.java?rev=1522553&view=au
>to
>==========================================================================
>====
>---
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java (added)
>+++
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java Thu Sep 12 12:45:19 2013
>@@ -0,0 +1,113 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one or more
>+ * contributor license agreements.  See the NOTICE file distributed with
>+ * this work for additional information regarding copyright ownership.
>+ * The ASF licenses this file to You under the Apache License, Version
>2.0
>+ * (the "License"); you may not use this file except in compliance with
>+ * the License.  You may obtain a copy of the License at
>+ *
>+ *      http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing, software
>+ * distributed under the License is distributed on an "AS IS" BASIS,
>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>implied.
>+ * See the License for the specific language governing permissions and
>+ * limitations under the License.
>+ */
>+package org.apache.jackrabbit.oak.plugins.mongomk;
>+
>+import java.util.AbstractMap;
>+import java.util.AbstractSet;
>+import java.util.Iterator;
>+import java.util.Map;
>+import java.util.Set;
>+
>+import javax.annotation.Nonnull;
>+
>+import com.google.common.collect.Iterators;
>+
>+/**
>+ * A value map contains the versioned values of a property. The key into
>this
>+ * map is the revision when the value was set.
>+ */
>+class ValueMap {
>+
>+    @Nonnull
>+    static Map<String, String> create(final @Nonnull NodeDocument doc,
>+                                      final @Nonnull String property) {
>+        final Map<String, String> map = doc.getLocalMap(property);
>+        if (doc.getPreviousRanges().isEmpty()) {
>+            return map;
>+        }
>+        final Set<Map.Entry<String, String>> values
>+                = new AbstractSet<Map.Entry<String, String>>() {
>+
>+            @Override
>+            @Nonnull
>+            public Iterator<Map.Entry<String, String>> iterator() {
>+                return Iterators.concat(map.entrySet().iterator(),
>Iterators.concat(new Iterator<Iterator<Map.Entry<String, String>>>()
{
>+                    private final Iterator<NodeDocument> previous =
>doc.getPreviousDocs(null).iterator();
>+
>+                    @Override
>+                    public boolean hasNext() {
>+                        return previous.hasNext();
>+                    }
>+
>+                    @Override
>+                    public Iterator<Map.Entry<String, String>> next() {
>+                        return
>previous.next().getLocalMap(property).entrySet().iterator();
>+                    }
>+
>+                    @Override
>+                    public void remove() {
>+                        throw new UnsupportedOperationException();
>+                    }
>+                }));
>+            }
>+
>+            @Override
>+            public int size() {
>+                int size = map.size();
>+                for (NodeDocument prev : doc.getPreviousDocs(null)) {
>+                    size += prev.getLocalMap(property).size();
>+                }
>+                return size;
>+            }
>+        };
>+        return new AbstractMap<String, String>() {
>+
>+            private final Map<String, String> map =
>doc.getLocalMap(property);
>+
>+            @Override
>+            @Nonnull
>+            public Set<Entry<String, String>> entrySet() {
>+                return values;
>+            }
>+
>+            @Override
>+            public String get(Object key) {
>+                // first check values map of this document
>+                String value = map.get(key);
>+                if (value != null) {
>+                    return value;
>+                }
>+                Revision r = Revision.fromString(key.toString());
>+                for (NodeDocument prev : doc.getPreviousDocs(r)) {
>+                    value = prev.getLocalMap(property).get(key);
>+                    if (value != null) {
>+                        return value;
>+                    }
>+                }
>+                // not found
>+                return null;
>+            }
>+
>+            @Override
>+            public boolean containsKey(Object key) {
>+                // can use get()
>+                // the values map does not have null values
>+                return get(key) != null;
>+            }
>+        };
>+    }
>+}
>
>Propchange:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java
>--------------------------------------------------------------------------
>----
>    svn:eol-style = native
>
>Propchange:
>jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/ValueMap.java
>--------------------------------------------------------------------------
>----
>    svn:keywords = Author Date Id Revision Rev URL
>
>Modified:
>jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/DocumentSplitTest.java
>URL:
>http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/o
>rg/apache/jackrabbit/oak/plugins/mongomk/DocumentSplitTest.java?rev=152255
>3&r1=1522552&r2=1522553&view=diff
>==========================================================================
>====
>---
>jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/DocumentSplitTest.java (original)
>+++
>jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plug
>ins/mongomk/DocumentSplitTest.java Thu Sep 12 12:45:19 2013
>@@ -39,7 +39,7 @@ public class DocumentSplitTest extends B
>         Set<String> revisions = Sets.newHashSet();
>         NodeDocument doc = store.find(Collection.NODES,
>Utils.getIdFromPath("/"));
>         assertNotNull(doc);
>-        revisions.addAll(doc.getRevisionsMap().keySet());
>+        revisions.addAll(doc.getLocalRevisions().keySet());
>
>         // MongoMK initializes with a root node with a single revision
>         int numRevs = 1;
>@@ -55,7 +55,7 @@ public class DocumentSplitTest extends B
>         String head = mk.getHeadRevision();
>         doc = store.find(Collection.NODES, Utils.getIdFromPath("/"));
>         assertNotNull(doc);
>-        Map<String, String> revs = doc.getRevisionsMap();
>+        Map<String, String> revs = doc.getLocalRevisions();
>         // one remaining in the local revisions map
>         assertEquals(1, revs.size());
>         for (String r : revisions) {
>
>


Mime
View raw message