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/26 10:10:07 UTC
svn commit: r1450089 - 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 26 09:10:06 2013
New Revision: 1450089
URL: http://svn.apache.org/r1450089
Log:
OAK-619 Lock-free MongoMK implementation (cache)
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/DocumentStore.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MemoryDocumentStore.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStore.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/main/java/org/apache/jackrabbit/mongomk/prototype/UpdateOp.java
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStoreTest.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=1450089&r1=1450088&r2=1450089&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 26 09:10:06 2013
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.mongomk.pr
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import org.apache.jackrabbit.mk.api.MicroKernelException;
import org.apache.jackrabbit.mk.json.JsopStream;
@@ -31,20 +32,27 @@ import org.apache.jackrabbit.oak.commons
*/
public class Commit {
+ private final MongoMK mk;
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>();
+ private HashSet<String> changedNodes = new HashSet<String>();
- Commit(Revision revision) {
+ private HashSet<String> addedNodes = new HashSet<String>();
+ private HashSet<String> removedNodes = new HashSet<String>();
+
+ private HashMap<String, Long> writeCounts = new HashMap<String, Long>();
+
+ Commit(MongoMK mk, Revision revision) {
this.revision = revision;
+ this.mk = mk;
}
- UpdateOp getUpdateOperationForNode(String path) {
+ private UpdateOp getUpdateOperationForNode(String path) {
UpdateOp op = operations.get(path);
if (op == null) {
String id = Node.convertPathToDocumentId(path);
- op = new UpdateOp(id, false);
+ op = new UpdateOp(path, id, false);
operations.put(path, op);
}
return op;
@@ -53,33 +61,46 @@ public class Commit {
public Revision getRevision() {
return revision;
}
+
+ void addNodeDiff(Node n) {
+ diff.tag('+').key(n.path);
+ diff.object();
+ n.append(diff, false);
+ diff.endObject();
+ diff.newline();
+ }
+
+ void updateProperty(String path, String propertyName, String value) {
+ UpdateOp op = getUpdateOperationForNode(path);
+ op.addMapEntry(propertyName, revision.toString(), value);
+ long increment = mk.getWriteCountIncrement(path);
+ op.increment("_writeCount", 1 + increment);
+ }
void addNode(Node n) {
if (operations.containsKey(n.path)) {
throw new MicroKernelException("Node already added: " + n.path);
}
operations.put(n.path, n.asOperation(true));
+ addedNodes.add(n.path);
}
- void addNodeWithDiff(Node n) {
- addNode(n);
- diff.tag('+').key(n.path);
- diff.object();
- n.append(diff, false);
- diff.endObject();
- diff.newline();
- }
-
boolean isEmpty() {
return operations.isEmpty();
}
- void apply(DocumentStore store) {
+ /**
+ * Apply the changes to the document store (to update MongoDB).
+ *
+ * @param store the store
+ */
+ void applyToDocumentStore() {
+ DocumentStore store = mk.getDocumentStore();
String commitRoot = null;
ArrayList<UpdateOp> newNodes = new ArrayList<UpdateOp>();
ArrayList<UpdateOp> changedNodes = new ArrayList<UpdateOp>();
for (String p : operations.keySet()) {
- addChangedParent(p);
+ markChanged(p);
if (commitRoot == null) {
commitRoot = p;
} else {
@@ -112,24 +133,80 @@ public class Commit {
store.create(Collection.NODES, newNodes);
}
for (UpdateOp op : changedNodes) {
- store.createOrUpdate(Collection.NODES, op);
+ createOrUpdateNode(store, op);
}
if (root != null) {
+ long increment = mk.getWriteCountIncrement(commitRoot);
+ root.increment("_writeCount", 1 + increment);
root.addMapEntry("_revisions", revision.toString(), "true");
- store.createOrUpdate(Collection.NODES, root);
+ createOrUpdateNode(store, root);
+ operations.put(commitRoot, root);
}
}
- public void apply(MongoMK mk) {
- // increment write counters
- for (String path : changedParents) {
- mk.incrementWriteCount(path);
+ private void createOrUpdateNode(DocumentStore store, UpdateOp op) {
+ Map<String, Object> map = store.createOrUpdate(Collection.NODES, op);
+ // TODO detect conflicts here
+ Long count = (Long) map.get("_writeCount");
+ if (count == null) {
+ count = 0L;
}
- // TODO update the cache
+ String path = op.getPath();
+ writeCounts.put(path, count);
}
-
- public void removeNode(String path) {
- diff.tag('-').value(path).newline();
+
+ /**
+ * Apply the changes to the MongoMK (to update the cache).
+ */
+ public void applyToCache() {
+ HashMap<String, ArrayList<String>> nodesWithChangedChildren = new HashMap<String, ArrayList<String>>();
+ ArrayList<String> addOrRemove = new ArrayList<String>();
+ addOrRemove.addAll(addedNodes);
+ addOrRemove.addAll(removedNodes);
+ for (String p : addOrRemove) {
+ String parent = PathUtils.getParentPath(p);
+ ArrayList<String> list = nodesWithChangedChildren.get(parent);
+ if (list == null) {
+ list = new ArrayList<String>();
+ nodesWithChangedChildren.put(parent, list);
+ }
+ list.add(p);
+ }
+ for (String path : changedNodes) {
+ ArrayList<String> added = new ArrayList<String>();
+ ArrayList<String> removed = new ArrayList<String>();
+ ArrayList<String> changed = nodesWithChangedChildren.get(path);
+ if (changed != null) {
+ for (String s : changed) {
+ if (addedNodes.contains(s)) {
+ added.add(s);
+ } else if (removedNodes.contains(s)) {
+ removed.add(s);
+ }
+ }
+ }
+ UpdateOp op = operations.get(path);
+ boolean isNew = op != null && op.isNew;
+ boolean isWritten = op != null;
+ long writeCountInc = mk.getWriteCountIncrement(path);
+ Long writeCount = writeCounts.get(path);
+ if (writeCount == null) {
+ if (isNew) {
+ writeCount = 0L;
+ writeCountInc = 0;
+ } else {
+ writeCountInc++;
+ String id = Node.convertPathToDocumentId(path);
+ Map<String, Object> map = mk.getDocumentStore().find(Collection.NODES, id);
+ Long oldWriteCount = (Long) map.get("_writeCount");
+ writeCount = oldWriteCount == null ? 0 : oldWriteCount;
+ }
+ }
+ mk.applyChanges(revision, path,
+ isNew, isWritten,
+ writeCount, writeCountInc,
+ added, removed);
+ }
}
public void moveNode(String sourcePath, String targetPath) {
@@ -140,14 +217,9 @@ public class Commit {
return diff;
}
- private void addChangedParent(String path) {
+ private void markChanged(String path) {
while (true) {
- UpdateOp op = operations.get(path);
- if (op == null || !op.isNew) {
- // no need to update the write count
- // for new nodes
- changedParents.add(path);
- }
+ changedNodes.add(path);
if (PathUtils.denotesRoot(path)) {
break;
}
@@ -155,5 +227,20 @@ public class Commit {
}
}
+ public void updatePropertyDiff(String path, String propertyName, String value) {
+ diff.tag('^').key(PathUtils.concat(path, propertyName)).value(value);
+ }
+
+ public void removeNodeDiff(String path) {
+ diff.tag('-').value(path).newline();
+ }
+
+ public void removeNode(String path) {
+ removedNodes.add(path);
+ UpdateOp op = getUpdateOperationForNode(path);
+ op.addMapEntry("_deleted", revision.toString(), "true");
+ long increment = mk.getWriteCountIncrement(path);
+ op.increment("_writeCount", 1 + increment);
+ }
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/DocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/DocumentStore.java?rev=1450089&r1=1450088&r2=1450089&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/DocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/DocumentStore.java Tue Feb 26 09:10:06 2013
@@ -29,14 +29,36 @@ public interface DocumentStore {
*/
enum Collection { NODES }
+ /**
+ * Get a document. The returned map is a clone (the caller
+ * can modify it without affecting the stored version).
+ *
+ * @param collection the collection
+ * @param path the path
+ * @return the map, or null if not found
+ */
Map<String, Object> find(Collection collection, String key);
List<Map<String, Object>> query(Collection collection, String fromKey, String toKey, int limit);
+ /**
+ * Remove a document.
+ *
+ * @param collection the collection
+ * @param path the path
+ */
void remove(Collection collection, String key);
void create(Collection collection, List<UpdateOp> updateOps);
+ /**
+ * Create or update a document. For MongoDb, this is using "findAndModify" with
+ * the "upsert" flag (insert or update).
+ *
+ * @param collection the collection
+ * @param update the update operation
+ * @return the new document
+ */
Map<String, Object> createOrUpdate(Collection collection, UpdateOp update);
void dispose();
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MemoryDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MemoryDocumentStore.java?rev=1450089&r1=1450088&r2=1450089&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MemoryDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MemoryDocumentStore.java Tue Feb 26 09:10:06 2013
@@ -45,14 +45,6 @@ public class MemoryDocumentStore impleme
private ConcurrentSkipListMap<String, Map<String, Object>> nodes =
new ConcurrentSkipListMap<String, Map<String, Object>>();
- /**
- * Get a document. The returned map is a clone (the caller
- * can modify it without affecting the stored version).
- *
- * @param collection the collection
- * @param path the path
- * @return the map, or null if not found
- */
public Map<String, Object> find(Collection collection, String path) {
ConcurrentSkipListMap<String, Map<String, Object>> map = getMap(collection);
Map<String, Object> n = map.get(path);
@@ -83,12 +75,6 @@ public class MemoryDocumentStore impleme
return list;
}
- /**
- * Remove a document.
- *
- * @param collection the collection
- * @param path the path
- */
public void remove(Collection collection, String path) {
getMap(collection).remove(path);
}
@@ -108,14 +94,6 @@ public class MemoryDocumentStore impleme
}
}
- /**
- * Create or update a document. For MongoDb, this is using "findAndModify" with
- * the "upsert" flag (insert or update).
- *
- * @param collection the collection
- * @param update the update operation
- * @return the old document, or null if there was no
- */
public Map<String, Object> createOrUpdate(Collection collection, UpdateOp update) {
ConcurrentSkipListMap<String, Map<String, Object>> map = getMap(collection);
Map<String, Object> n;
@@ -147,7 +125,7 @@ public class MemoryDocumentStore impleme
synchronized (n) {
applyChanges(n, update);
}
- return oldNode;
+ return n;
}
public static void applyChanges(Map<String, Object> target, UpdateOp update) {
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStore.java?rev=1450089&r1=1450088&r2=1450089&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStore.java Tue Feb 26 09:10:06 2013
@@ -42,7 +42,7 @@ public class MongoDocumentStore implemen
public static final String KEY_PATH = "_id";
- private static final boolean LOG = true;
+ private static final boolean LOG = false;
private static final boolean LOG_TIME = true;
private final DBCollection nodesCollection;
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=1450089&r1=1450088&r2=1450089&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 26 09:10:06 2013
@@ -18,10 +18,12 @@ package org.apache.jackrabbit.mongomk.pr
import java.io.InputStream;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
@@ -82,13 +84,19 @@ public class MongoMK implements MicroKer
* Key: path@rev
* Value: node
*/
- // TODO: should be path@id
private final Map<String, Node> nodeCache = new Cache<String, Node>(1024);
/**
+ * Child node cache.
+ */
+ private Cache<String, Node.Children> nodeChildrenCache =
+ new Cache<String, Node.Children>(1024);
+
+ /**
* The unsaved write count increments.
*/
private final Map<String, Long> writeCountIncrements = new HashMap<String, Long>();
+
/**
* The set of known valid revision.
* The key is the revision id, the value is 1 (because a cache can't be a set).
@@ -104,9 +112,6 @@ public class MongoMK implements MicroKer
private final Map<String, String> branchCommits = new HashMap<String, String>();
- private Cache<String, Node.Children> nodeChildrenCache =
- new Cache<String, Node.Children>(1024);
-
/**
* Create a new in-memory MongoMK used for testing.
*/
@@ -146,10 +151,10 @@ public class MongoMK implements MicroKer
Node n = readNode("/", headRevision);
if (n == null) {
// root node is missing: repository is not initialized
- Commit commit = new Commit(headRevision);
+ Commit commit = new Commit(this, headRevision);
n = new Node("/", headRevision);
commit.addNode(n);
- commit.apply(store);
+ commit.applyToDocumentStore();
}
}
@@ -349,7 +354,7 @@ public class MongoMK implements MicroKer
}
JsopStream json = new JsopStream();
boolean includeId = filter != null && filter.contains(":id");
- includeId = filter != null && filter.contains(":hash");
+ includeId |= filter != null && filter.contains(":hash");
json.object();
n.append(json, includeId);
Children c = readChildren(path, n.getId(), rev, maxChildNodes);
@@ -372,7 +377,7 @@ public class MongoMK implements MicroKer
revisionId = revisionId == null ? headRevision.toString() : revisionId;
JsopReader t = new JsopTokenizer(json);
Revision rev = Revision.newRevision(clusterId);
- Commit commit = new Commit(rev);
+ Commit commit = new Commit(this, rev);
while (true) {
int r = t.read();
if (r == JsopReader.END) {
@@ -387,7 +392,8 @@ public class MongoMK implements MicroKer
break;
case '-':
commit.removeNode(path);
- markAsDeleted(path, commit,true);
+ markAsDeleted(path, commit, true);
+ commit.removeNodeDiff(path);
break;
case '^':
t.read(':');
@@ -397,13 +403,12 @@ public class MongoMK implements MicroKer
commit.getDiff().tag('^').key(path).value(null);
} else {
value = t.readRawValue().trim();
- commit.getDiff().tag('^').key(path).value(null);
+ commit.getDiff().tag('^').key(path).value(value);
}
String p = PathUtils.getParentPath(path);
String propertyName = PathUtils.getName(path);
- UpdateOp op = commit.getUpdateOperationForNode(p);
- op.addMapEntry(propertyName, rev.toString(), value);
- op.increment("_writeCount", 1);
+ commit.updateProperty(p, propertyName, value);
+ commit.updatePropertyDiff(p, propertyName, value);
break;
case '>': {
t.read(':');
@@ -447,52 +452,56 @@ public class MongoMK implements MicroKer
}
private void moveNode(String sourcePath, String targetPath, Commit commit) {
- //TODO Optimize - Move logic would not work well with very move of very large subtrees
- //At minimum we can optimize by traversing breadth wise and collect node id
- //and fetch them via '$in' queries
-
- //TODO Transient Node - Current logic does not account for operations which are part
- //of this commit i.e. transient nodes. If its required it would need to be looked
- //into
+ // TODO Optimize - Move logic would not work well with very move of very large subtrees
+ // At minimum we can optimize by traversing breadth wise and collect node id
+ // and fetch them via '$in' queries
+
+ // TODO Transient Node - Current logic does not account for operations which are part
+ // of this commit i.e. transient nodes. If its required it would need to be looked
+ // into
Node n = getNode(sourcePath, commit.getRevision());
- //Node might be deleted already
- if(n == null){
+ // Node might be deleted already
+ if (n == null) {
return;
}
- Node newNode = new Node(targetPath,commit.getRevision());
+ Node newNode = new Node(targetPath, commit.getRevision());
n.copyTo(newNode);
commit.addNode(newNode);
- markAsDeleted(sourcePath,commit,false);
+ markAsDeleted(sourcePath, commit, false);
Node.Children c = readChildren(sourcePath, n.getId(),
commit.getRevision(), Integer.MAX_VALUE);
for (String srcChildPath : c.children) {
String childName = PathUtils.getName(srcChildPath);
String destChildPath = PathUtils.concat(targetPath, childName);
- moveNode(srcChildPath,destChildPath,commit);
+ moveNode(srcChildPath, destChildPath, commit);
}
}
private void markAsDeleted(String path, Commit commit, boolean subTreeAlso) {
Revision rev = commit.getRevision();
- UpdateOp op = commit.getUpdateOperationForNode(path);
- op.addMapEntry("_deleted", rev.toString(), "true");
- op.increment("_writeCount", 1);
-
- if(subTreeAlso){
- // TODO Would cause issue with large number of children.
- // Need to be changed
+ commit.removeNode(path);
+
+ if (subTreeAlso) {
+
+ // recurse down the tree
+ // TODO causes issue with large number of children
Node n = getNode(path, rev);
- Node.Children c = readChildren(path, n.getId(), rev, Integer.MAX_VALUE);
+
+ // remove from the cache
+ nodeCache.remove(path + "@" + rev);
+
+ Node.Children c = readChildren(path, n.getId(), rev,
+ Integer.MAX_VALUE);
for (String childPath : c.children) {
- markAsDeleted(childPath, commit,true);
+ markAsDeleted(childPath, commit, true);
}
}
- //Remove the node from the cache
+ // Remove the node from the cache
nodeCache.remove(path + "@" + rev);
}
@@ -521,8 +530,8 @@ public class MongoMK implements MicroKer
if (commit.isEmpty()) {
return;
}
- commit.apply(store);
- commit.apply(this);
+ commit.applyToDocumentStore();
+ commit.applyToCache();
}
public static void parseAddNode(Commit commit, JsopReader t, String path) {
@@ -541,7 +550,8 @@ public class MongoMK implements MicroKer
} while (t.matches(','));
t.read('}');
}
- commit.addNodeWithDiff(n);
+ commit.addNode(n);
+ commit.addNodeDiff(n);
}
@Override
@@ -627,6 +637,10 @@ public class MongoMK implements MicroKer
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > size;
}
+
+ public String toString() {
+ return super.toString().replace(',', '\n');
+ }
}
@@ -657,10 +671,41 @@ public class MongoMK implements MicroKer
}
}
- public void incrementWriteCount(String path) {
- Long value = writeCountIncrements.get(path);
- value = value == null ? 1 : value + 1;
- writeCountIncrements.put(path, value);
+ public void applyChanges(Revision rev, String path,
+ boolean isNew, boolean isWritten,
+ long oldWriteCount, long writeCountInc,
+ ArrayList<String> added, ArrayList<String> removed) {
+ if (!isWritten) {
+ if (writeCountInc == 0) {
+ writeCountIncrements.remove(path);
+ } else {
+ writeCountIncrements.put(path, writeCountInc);
+ }
+ } else {
+ writeCountIncrements.remove(path);
+ }
+ long newWriteCount = oldWriteCount + writeCountInc;
+ Children c = nodeChildrenCache.get(path + "@" + (newWriteCount - 1));
+ if (isNew || c != null) {
+ String id = path + "@" + newWriteCount;
+ Children c2 = new Children(path, id, rev);
+ TreeSet<String> set = new TreeSet<String>();
+ if (c != null) {
+ set.addAll(c.children);
+ }
+ set.removeAll(removed);
+ set.addAll(added);
+ c2.children.addAll(set);
+ if (nodeChildrenCache.get(id) != null) {
+ throw new AssertionError("New child list already cached");
+ }
+ nodeChildrenCache.put(id, c2);
+ }
+ }
+
+ public long getWriteCountIncrement(String path) {
+ Long x = writeCountIncrements.get(path);
+ return x == null ? 0 : x;
}
}
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=1450089&r1=1450088&r2=1450089&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 26 09:10:06 2013
@@ -44,10 +44,10 @@ public class Node {
return properties.get(propertyName);
}
- public void copyTo(Node newNode){
- for(Map.Entry<String,String> e : properties.entrySet()){
- if(!filter(e.getKey())){
- newNode.setProperty(e.getKey(),e.getValue());
+ public void copyTo(Node newNode) {
+ for (Map.Entry<String, String> e : properties.entrySet()) {
+ if (!filter(e.getKey())) {
+ newNode.setProperty(e.getKey(), e.getValue());
}
}
}
@@ -56,6 +56,7 @@ public class Node {
StringBuilder buff = new StringBuilder();
buff.append("path: ").append(path).append('\n');
buff.append("rev: ").append(rev).append('\n');
+ buff.append("writeCount: ").append(writeCount).append('\n');
buff.append(properties);
buff.append('\n');
return buff.toString();
@@ -66,7 +67,7 @@ public class Node {
*/
UpdateOp asOperation(boolean isNew) {
String id = convertPathToDocumentId(path);
- UpdateOp op = new UpdateOp(id, isNew);
+ UpdateOp op = new UpdateOp(path, id, isNew);
op.set("_id", id);
if (!isNew) {
op.increment("_changeCount", 1L);
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/UpdateOp.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/UpdateOp.java?rev=1450089&r1=1450088&r2=1450089&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/UpdateOp.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/UpdateOp.java Tue Feb 26 09:10:06 2013
@@ -24,6 +24,8 @@ import java.util.TreeMap;
*/
public class UpdateOp {
+ final String path;
+
final String key;
final boolean isNew;
@@ -34,15 +36,21 @@ public class UpdateOp {
* Create an update operation for the given document. The commit root is assumed
* to be the path, unless this is changed later on.
*
+ * @param path the node path (for nodes)
* @param key the primary key
* @param isNew whether this is a new document
* @param rev the revision
*/
- UpdateOp(String key, boolean isNew) {
+ UpdateOp(String path, String key, boolean isNew) {
+ this.path = path;
this.key = key;
this.isNew = isNew;
}
+ String getPath() {
+ return path;
+ }
+
boolean isNew() {
return isNew;
}
@@ -87,6 +95,17 @@ public class UpdateOp {
changes.put(property, op);
}
+ public Long getIncrement(String property) {
+ Operation op = changes.get(property);
+ if (op == null) {
+ return null;
+ }
+ if (op.type != Operation.Type.INCREMENT) {
+ throw new IllegalArgumentException("Not an increment operation");
+ }
+ return (Long) op.value;
+ }
+
public String toString() {
return "key: " + key + " " + (isNew ? "new" : "update") + " " + changes;
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStoreTest.java?rev=1450089&r1=1450088&r2=1450089&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoDocumentStoreTest.java Tue Feb 26 09:10:06 2013
@@ -63,7 +63,7 @@ public class MongoDocumentStoreTest {
dropCollections();
DocumentStore docStore = openDocumentStore();
- UpdateOp updateOp = new UpdateOp("/", true);
+ UpdateOp updateOp = new UpdateOp("/", "/", true);
updateOp.addMapEntry("property1", "key1", "value1");
updateOp.increment("property2", 1);
updateOp.set("property3", "value3");
@@ -94,7 +94,8 @@ public class MongoDocumentStoreTest {
int nUpdates = 10;
List<UpdateOp> updateOps = new ArrayList<UpdateOp>();
for (int i = 0; i < nUpdates; i++) {
- UpdateOp updateOp = new UpdateOp("/node" + i, true);
+ String path = "/node" + i;
+ UpdateOp updateOp = new UpdateOp(path, path, true);
updateOp.set(MongoDocumentStore.KEY_PATH, "/node" + i);
updateOp.addMapEntry("property1", "key1", "value1");
updateOp.increment("property2", 1);
@@ -209,7 +210,8 @@ public class MongoDocumentStoreTest {
private void addNodes() {
for (int i = 0; i < nNodes; i++) {
- UpdateOp updateOp = new UpdateOp("/" + nodeName + i, true);
+ String path = "/" + nodeName + i;
+ UpdateOp updateOp = new UpdateOp(path, path, true);
updateOp.addMapEntry("property1", "key1", "value1");
updateOp.set("property3", "value3");
docStore.createOrUpdate(Collection.NODES, updateOp);
@@ -218,7 +220,8 @@ public class MongoDocumentStoreTest {
private void updateNodes() {
for (int i = 0; i < nNodes; i++) {
- UpdateOp updateOp = new UpdateOp("/" + nodeName + i, false);
+ String path = "/" + nodeName + i;
+ UpdateOp updateOp = new UpdateOp(path, path, false);
updateOp.addMapEntry("property1", "key2", "value2");
updateOp.set("property4", "value4");
docStore.createOrUpdate(Collection.NODES, updateOp);
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=1450089&r1=1450088&r2=1450089&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 26 09:10:06 2013
@@ -33,8 +33,8 @@ import com.mongodb.DB;
*/
public class SimpleTest {
-// private static final boolean MONGO_DB = true;
private static final boolean MONGO_DB = false;
+// private static final boolean MONGO_DB = true;
@Test
public void test() {
@@ -94,6 +94,57 @@ public class SimpleTest {
// System.out.println(test);
mk.dispose();
}
+
+ @Test
+ public void cache() {
+ MongoMK mk = createMK();
+
+ // BAD
+ String rev = mk.commit("/", "+\"testRoot\":{} +\"index\":{}", null, null);
+
+ // GOOD
+// String rev = mk.commit("/", "+\"testRoot\":{} ", null, null);
+
+ String test = mk.getNodes("/", rev, 0, 0, Integer.MAX_VALUE, ":id");
+ // System.out.println(" " + test);
+// test = mk.getNodes("/testRoot", rev, 0, 0, Integer.MAX_VALUE, ":id");
+// System.out.println(" " + test);
+ rev = mk.commit("/testRoot", "+\"a\":{}", null, null);
+// test = mk.getNodes("/testRoot", rev, 0, 0, Integer.MAX_VALUE, ":id");
+// System.out.println(" " + test);
+// rev = mk.commit("/testRoot/a", "+\"b\":{}", null, null);
+// rev = mk.commit("/testRoot/a/b", "+\"c\":{} +\"d\":{}", null, null);
+// test = mk.getNodes("/testRoot", rev, 0, 0, Integer.MAX_VALUE, ":id");
+// System.out.println(" " + test);
+// test = mk.getNodes("/", rev, 0, 0, Integer.MAX_VALUE, ":id");
+// System.out.println(" " + test);
+// rev = mk.commit("/index", "+\"a\":{}", null, null);
+ test = mk.getNodes("/", rev, 0, 0, Integer.MAX_VALUE, ":id");
+ // System.out.println(" " + test);
+// test = mk.getNodes("/testRoot", rev, 0, 0, Integer.MAX_VALUE, ":id");
+// System.out.println(" " + test);
+
+// assertEquals("{\"name\":\"Hello\",\":childNodeCount\":0}", test);
+//
+// rev = mk.commit("/test", "+\"a\":{\"name\": \"World\"}", null, null);
+// rev = mk.commit("/test", "+\"b\":{\"name\": \"!\"}", null, null);
+// test = mk.getNodes("/test", rev, 0, 0, Integer.MAX_VALUE, null);
+// Children c;
+// c = mk.readChildren("/", "1",
+// Revision.fromString(rev), Integer.MAX_VALUE);
+// assertEquals("/: [/test]", c.toString());
+// c = mk.readChildren("/test", "2",
+// Revision.fromString(rev), Integer.MAX_VALUE);
+// assertEquals("/test: [/test/a, /test/b]", c.toString());
+//
+// 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();
+ }
+
@Test
public void testDeletion() {