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 th...@apache.org on 2013/02/19 11:29:17 UTC

svn commit: r1447659 - in /jackrabbit/oak/trunk/oak-mongomk/src: main/java/org/apache/jackrabbit/mongomk/prototype/ test/java/org/apache/jackrabbit/mongomk/prototype/

Author: thomasm
Date: Tue Feb 19 10:29:16 2013
New Revision: 1447659

URL: http://svn.apache.org/r1447659
Log:
OAK-619 Lock-free MongoMK implementation (WIP)

Modified:
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Commit.java
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Node.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/Commit.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Commit.java?rev=1447659&r1=1447658&r2=1447659&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Commit.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Commit.java Tue Feb 19 10:29:16 2013
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.mongomk.pr
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.mk.json.JsopStream;
@@ -33,6 +35,7 @@ public class Commit {
     private final Revision revision;
     private HashMap<String, UpdateOp> operations = new HashMap<String, UpdateOp>();
     private JsopWriter diff = new JsopStream();
+    private HashSet<String> changedParents = new HashSet<String>();
     
     Commit(Revision revision) {
         this.revision = revision;
@@ -58,9 +61,15 @@ public class Commit {
         }
         operations.put(n.path, n.asOperation(true));
         diff.tag('+').key(n.path);
+        diff.object();
         n.append(diff, false);
+        diff.endObject();
         diff.newline();
     }
+    
+    boolean isEmpty() {
+        return operations.isEmpty();
+    }
 
     void apply(DocumentStore store) {
         String commitRoot = null;
@@ -78,6 +87,7 @@ public class Commit {
                 }
             }
         }
+        addChangedParent(commitRoot);
         // create a "root of the commit" if there is none
         UpdateOp root = getUpdateOperationForNode(commitRoot);
         for (String p : operations.keySet()) {
@@ -112,4 +122,18 @@ public class Commit {
         return diff;
     }
 
+    private void addChangedParent(String path) {
+        while (true) {
+            changedParents.add(path);
+            if (PathUtils.denotesRoot(path)) {
+                break;
+            }
+            path = PathUtils.getParentPath(path);
+        }
+    }
+    
+    public Set<String> getChangedParents() {
+        return changedParents;
+    }
+
 }

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=1447659&r1=1447658&r2=1447659&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 Tue Feb 19 10:29:16 2013
@@ -33,6 +33,7 @@ import org.apache.jackrabbit.mk.json.Jso
 import org.apache.jackrabbit.mk.json.JsopStream;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
 import org.apache.jackrabbit.mongomk.impl.blob.MongoBlobStore;
+import org.apache.jackrabbit.mongomk.prototype.Node.Children;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 
 import com.mongodb.DB;
@@ -65,6 +66,11 @@ public class MongoMK implements MicroKer
      */
     // TODO: should be path@id
     private final Map<String, Node> nodeCache = new Cache<String, Node>(1024);
+    
+    /**
+     * The unsaved write count increments.
+     */
+    private final Map<String, Long> writeCountIncrements = new HashMap<String, Long>();
 
     /**
      * For revisions that are older than this many seconds, the MongoMK will
@@ -202,7 +208,7 @@ public class MongoMK implements MicroKer
                 requestRevision.getClusterId() == this.clusterId) {
             // both revisions were created by this cluster node: 
             // compare timestamps only
-            return x.compareRevisionTime(requestRevision) >= 0;
+            return requestRevision.compareRevisionTime(x) >= 0;
         }
         // TODO currently we only compare the timestamps
         return x.compareRevisionTime(requestRevision) >= 0;
@@ -212,9 +218,9 @@ public class MongoMK implements MicroKer
         String from = PathUtils.concat(path, "a");
         from = Node.convertPathToDocumentId(from);
         from = from.substring(0, from.length() - 1);
-        String to = PathUtils.concat(path, "z/z");
+        String to = PathUtils.concat(path, "z");
         to = Node.convertPathToDocumentId(to);
-        to = to.substring(0, to.length() - 3);
+        to = to.substring(0, to.length() - 2) + "0";
         List<Map<String, Object>> list = store.query(DocumentStore.Collection.NODES, from, to, limit);
         Node.Children c = new Node.Children(path, rev);
         for (Map<String, Object> e : list) {
@@ -233,16 +239,17 @@ public class MongoMK implements MicroKer
             return null;
         }
         Node n = new Node(path, rev);
+        Long w = writeCountIncrements.get(path);
+        long writeCount = w == null ? 0 : w;
         for(String key : map.keySet()) {
+            if (key.equals("_writeCount")) {
+                writeCount += (Long) map.get(key);
+            }
             if (key.startsWith("_")) {
                 // TODO property name escaping
                 continue;
             }
             Object v = map.get(key);
-            if (!(v instanceof Map)) {
-                int test;
-                System.out.println("??");
-            }
             @SuppressWarnings("unchecked")
             Map<String, String> valueMap = (Map<String, String>) v;
             if (valueMap != null) {
@@ -254,6 +261,7 @@ public class MongoMK implements MicroKer
                 }
             }
         }
+        n.setWriteCount(writeCount);
         return n;
     }
 
@@ -290,7 +298,7 @@ public class MongoMK implements MicroKer
             return "";
         }
         // TODO implement if needed
-        return null;
+        return "{}";
     }
 
     @Override
@@ -321,10 +329,27 @@ public class MongoMK implements MicroKer
         }
         Revision rev = Revision.fromString(revisionId);
         Node n = getNode(path, rev);
+        if (n == null) {
+            return null;
+            // throw new MicroKernelException("Node not found at path " + path);
+        }
         JsopStream json = new JsopStream();
         boolean includeId = filter != null && filter.contains(":id");
+        includeId = filter != null && filter.contains(":hash");
+        json.object();
         n.append(json, includeId);
-        return json.toString();
+        Children c = readChildren(path, rev, maxChildNodes);
+        for (String s : c.children) {
+            String name = PathUtils.getName(s);
+            json.key(name).object().endObject();
+        }
+        json.key(":childNodeCount").value(c.children.size());
+        json.endObject();
+        String result = json.toString();
+        if (filter != null && filter.contains(":hash")) {
+            result = result.replaceAll("\":id\"", "\":hash\"");
+        }
+        return result;
     }
 
     @Override
@@ -364,6 +389,7 @@ public class MongoMK implements MicroKer
                 String propertyName = PathUtils.getName(path);
                 UpdateOp op = commit.getUpdateOperationForNode(p);
                 op.addMapEntry(propertyName, rev.toString(), value);
+                op.increment("_writeCount", 1);
                 break;
             case '>': {
                 t.read(':');
@@ -437,8 +463,7 @@ public class MongoMK implements MicroKer
         }
         if (revisionId.startsWith("b")) {
             // just commit to head currently
-            commit.apply(store);
-            headRevision = rev;
+            applyCommit(commit);
             return "b" + rev.toString();
             
             // String jsonBranch = branchCommits.remove(revisionId);
@@ -447,11 +472,23 @@ public class MongoMK implements MicroKer
             // branchCommits.put(branchRev, jsonBranch);
             // return branchRev;
         }
-        commit.apply(store);
-        headRevision = rev;
+        applyCommit(commit);
         return rev.toString();
     }    
     
+    private void applyCommit(Commit commit) {
+        headRevision = commit.getRevision();
+        if (commit.isEmpty()) {
+            return;
+        }
+        commit.apply(store);
+        for(String path : commit.getChangedParents()) {
+            Long value = writeCountIncrements.get(path);
+            value = value == null ? 1 : value + 1;
+            writeCountIncrements.put(path, value);
+        }
+    }
+    
     public static void parseAddNode(Commit commit, JsopReader t, String path) {
         Node n = new Node(path, commit.getRevision());
         if (!t.matches('}')) {

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Node.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Node.java?rev=1447659&r1=1447658&r2=1447659&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Node.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Node.java Tue Feb 19 10:29:16 2013
@@ -29,6 +29,7 @@ public class Node {
     final String path;
     final Revision rev;
     final Map<String, String> properties = Utils.newMap();
+    private long writeCount;
     
     Node(String path, Revision rev) {
         this.path = path;
@@ -74,14 +75,12 @@ public class Node {
     }
 
     public void append(JsopWriter json, boolean includeId) {
-        json.object();
         if (includeId) {
-            json.key(":id").value(path + "@" + rev);
+            json.key(":id").value(path + "@" + writeCount);
         }
         for (String p : properties.keySet()) {
             json.key(p).encodedValue(properties.get(p));
         }
-        json.endObject();
     }
     
     static class Children {
@@ -102,4 +101,8 @@ public class Node {
         
     }
 
+    public void setWriteCount(long writeCount) {
+        this.writeCount = writeCount;
+    }
+
 }

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=1447659&r1=1447658&r2=1447659&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 Tue Feb 19 10:29:16 2013
@@ -65,10 +65,11 @@ public class SimpleTest {
     @Test
     public void commit() {
         MongoMK mk = new MongoMK();
-        
-        String rev = mk.commit("/", "+\"test\":{\"name\": \"Hello\"}", null, null);
+
+        String rev;
+        rev = mk.commit("/", "+\"test\":{\"name\": \"Hello\"}", null, null);
         String test = mk.getNodes("/test", rev, 0, 0, Integer.MAX_VALUE, null);
-        assertEquals("{\"name\":\"Hello\"}", test);
+        assertEquals("{\"name\":\"Hello\",\":childNodeCount\":0}", test);
         
         rev = mk.commit("/test", "+\"a\":{\"name\": \"World\"}", null, null);
         rev = mk.commit("/test", "+\"b\":{\"name\": \"!\"}", null, null);
@@ -80,8 +81,12 @@ public class SimpleTest {
         c = mk.readChildren("/test", 
                 Revision.fromString(rev), Integer.MAX_VALUE);
         assertEquals("/test: [/test/a, /test/b]", c.toString());
-        
-        // System.out.println(test);
+
+        rev = mk.commit("", "^\"/test\":1", null, null);
+        test = mk.getNodes("/", rev, 0, 0, Integer.MAX_VALUE, null);
+        assertEquals("{\"test\":1,\"test\":{},\":childNodeCount\":1}", test);
+
+        System.out.println(test);
         mk.dispose();
     }