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