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);