You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2013/03/20 15:23:03 UTC

svn commit: r1458849 - in /jackrabbit/oak/trunk/oak-mongomk/src: main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java

Author: mreutegg
Date: Wed Mar 20 14:23:03 2013
New Revision: 1458849

URL: http://svn.apache.org/r1458849
Log:
OAK-619 Lock-free MongoMK implementation
- when reading, validate revision against commit root

Modified:
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java
    jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java?rev=1458849&r1=1458848&r2=1458849&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java Wed Mar 20 14:23:03 2013
@@ -53,6 +53,8 @@ import com.mongodb.DB;
  */
 public class MongoMK implements MicroKernel {
 
+    private static final Logger log = LoggerFactory.getLogger(MongoMK.class);
+
     /**
      * The number of documents to cache.
      */
@@ -260,7 +262,56 @@ public class MongoMK implements MicroKer
         // TODO currently we only compare the timestamps
         return x.compareRevisionTime(previous) > 0;
     }
-    
+
+    /**
+     * Checks if the revision is valid for the given node map. A revision is
+     * considered valid if the given node map is the root of the commit, or the
+     * commit root has the revision set. This method may read further nodes to
+     * perform this check.
+     *
+     * @param rev     revision to check.
+     * @param nodeMap the node to check.
+     * @return <code>true</code> if the revision is valid; <code>false</code>
+     *         otherwise.
+     */
+    boolean isValidRevision(Revision rev, Map<String, Object> nodeMap) {
+        @SuppressWarnings("unchecked")
+        Map<String, String> revisions = (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS);
+        if (revisions != null && revisions.containsKey(rev.toString())) {
+            return true;
+        }
+        // check commit root
+        @SuppressWarnings("unchecked")
+        Map<String, Integer> commitRoot = (Map<String, Integer>) nodeMap.get(UpdateOp.COMMIT_ROOT);
+        String commitRootId = null;
+        if (commitRoot != null) {
+            Integer depth = commitRoot.get(rev.toString());
+            if (depth != null) {
+                String p = Utils.getPathFromId((String) nodeMap.get(UpdateOp.ID));
+                StringBuilder sb = new StringBuilder();
+                sb.append(depth).append(":");
+                sb.append(PathUtils.getAncestorPath(p, PathUtils.getDepth(p) - depth));
+                commitRootId = sb.toString();
+            }
+        }
+        if (commitRootId == null) {
+            // shouldn't happen, either node is commit root for a revision
+            // or has a reference to the commit root
+            log.warn("Node {} does not have commit root reference for revision {}",
+                    nodeMap.get(UpdateOp.ID), rev);
+            log.warn(nodeMap.toString());
+            return false;
+        }
+        // get root of commit
+        nodeMap = store.find(DocumentStore.Collection.NODES, commitRootId);
+        if (nodeMap == null) {
+            return false;
+        }
+        //noinspection unchecked
+        revisions = (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS);
+        return revisions != null && revisions.containsKey(rev.toString());
+    }
+
     public Children getChildren(String path, Revision rev, int limit) {
         checkRevisionAge(rev, path);
         String key = path + "@" + rev;
@@ -667,7 +718,7 @@ public class MongoMK implements MicroKer
     }
     
     /**
-     * Get the latest revision where the node was alive at or before the the
+     * Get the latest revision where the node was alive at or before the
      * provided revision.
      * 
      * @param nodeMap the node map
@@ -684,7 +735,8 @@ public class MongoMK implements MicroKer
         String value = null;
         for (String r : valueMap.keySet()) {
             Revision propRev = Revision.fromString(r);
-            if (isRevisionNewer(propRev, maxRev)) {
+            if (isRevisionNewer(propRev, maxRev)
+                    || !isValidRevision(propRev, nodeMap)) {
                 continue;
             }
             String v = valueMap.get(r);

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java?rev=1458849&r1=1458848&r2=1458849&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java Wed Mar 20 14:23:03 2013
@@ -84,6 +84,8 @@ public class SimpleTest {
         Node n = new Node("/test", rev);
         n.setProperty("name", "Hello");
         UpdateOp op = n.asOperation(true);
+        // mark as commit root
+        op.addMapEntry(UpdateOp.REVISIONS + "." + rev, "true");
         DocumentStore s = mk.getDocumentStore();
         assertTrue(s.create(Collection.NODES, Lists.newArrayList(op)));
         Node n2 = mk.getNode("/test", rev);