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/03/27 10:22:38 UTC
svn commit: r1461465 - in /jackrabbit/oak/trunk/oak-mongomk/src:
main/java/org/apache/jackrabbit/mongomk/prototype/
test/java/org/apache/jackrabbit/mongomk/prototype/
Author: thomasm
Date: Wed Mar 27 09:22:38 2013
New Revision: 1461465
URL: http://svn.apache.org/r1461465
Log:
OAK-619 Lock-free MongoMK implementation (detect conflicts; 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/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/UpdateOp.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Utils.java
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/ClusterTest.java
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKBranchMergeTest.java
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKCommitMoveTest.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=1461465&r1=1461464&r2=1461465&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 Wed Mar 27 09:22:38 2013
@@ -151,6 +151,7 @@ public class Commit {
}
ArrayList<UpdateOp> newNodes = new ArrayList<UpdateOp>();
ArrayList<UpdateOp> changedNodes = new ArrayList<UpdateOp>();
+ ArrayList<UpdateOp> done = new ArrayList<UpdateOp>();
for (String p : operations.keySet()) {
markChanged(p);
if (commitRootPath == null) {
@@ -212,6 +213,7 @@ public class Commit {
for (UpdateOp op : changedNodes) {
// set commit root on changed nodes
op.addMapEntry(UpdateOp.COMMIT_ROOT + "." + revision.toString(), commitRootDepth);
+ done.add(op);
createOrUpdateNode(store, op);
}
// finally write the commit root, unless it was already written
@@ -220,32 +222,57 @@ public class Commit {
// the revision, with the revision property set)
if (changedNodes.size() > 0 || !commitRoot.isNew) {
commitRoot.addMapEntry(UpdateOp.REVISIONS + "." + revision.toString(), commitValue);
+ done.add(commitRoot);
createOrUpdateNode(store, commitRoot);
operations.put(commitRootPath, commitRoot);
}
} catch (MicroKernelException e) {
+ rollback(newNodes, done);
String msg = "Exception committing " + diff.toString();
LOG.error(msg, e);
throw new MicroKernelException(msg, e);
}
}
+ private void rollback(ArrayList<UpdateOp> newDocuments, ArrayList<UpdateOp> changed) {
+ DocumentStore store = mk.getDocumentStore();
+ for (UpdateOp op : changed) {
+ UpdateOp reverse = op.getReverseOperation();
+ store.createOrUpdate(Collection.NODES, reverse);
+ }
+ for (UpdateOp op : newDocuments) {
+ store.remove(Collection.NODES, op.key);
+ }
+ }
+
+ /**
+ * Try to create or update the node. If there was a conflict, this method
+ * throws an exception, even thought the change is still applied.
+ *
+ * @param store the store
+ * @param op the operation
+ */
private void createOrUpdateNode(DocumentStore store, UpdateOp op) {
Map<String, Object> map = store.createOrUpdate(Collection.NODES, op);
if (baseRevision != null) {
- // TODO detect conflicts here
Revision newestRev = mk.getNewestRevision(map, revision, true);
- if (newestRev != null && mk.isRevisionNewer(newestRev, baseRevision)) {
- // TODO transaction rollback
- throw new MicroKernelException("The node " +
- op.path + " was changed in revision " +
- newestRev +
- ", which was applied after the base revision " +
- baseRevision);
+ if (newestRev != null) {
+ if (op.isNew) {
+ throw new MicroKernelException("The node " +
+ op.path + " was already added in revision " +
+ newestRev);
+ }
+ if (mk.isRevisionNewer(newestRev, baseRevision)) {
+ throw new MicroKernelException("The node " +
+ op.path + " was changed in revision " +
+ newestRev +
+ ", which was applied after the base revision " +
+ baseRevision);
+ }
}
}
- int size = Utils.getMapSize(map);
+ int size = Utils.estimateMemoryUsage(map);
if (size > MAX_DOCUMENT_SIZE) {
UpdateOp[] split = splitDocument(map);
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=1461465&r1=1461464&r2=1461465&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 Wed Mar 27 09:22:38 2013
@@ -71,7 +71,7 @@ public interface DocumentStore {
*
* @param collection the collection
* @param update the update operation
- * @return the new document
+ * @return the old document
* @throws MicroKernelException if the operation failed.
*/
@Nonnull
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=1461465&r1=1461464&r2=1461465&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 Wed Mar 27 09:22:38 2013
@@ -115,21 +115,20 @@ public class MemoryDocumentStore impleme
n = oldNode;
}
}
- if (oldNode != null) {
- // clone the old node
- // (document level operations are synchronized)
- Map<String, Object> old = Utils.newMap();
- synchronized (oldNode) {
- old.putAll(oldNode);
- }
- oldNode = old;
- }
- // update the document
- // (document level operations are synchronized)
synchronized (n) {
+ if (oldNode != null) {
+ // clone the old node
+ // (document level operations are synchronized)
+ Map<String, Object> oldNode2 = Utils.newMap();
+ Utils.deepCopyMap(oldNode, oldNode2);
+ oldNode = oldNode2;
+ }
+ // to return the new document:
+ // update the document
+ // (document level operations are synchronized)
applyChanges(n, update);
}
- return n;
+ return oldNode;
}
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=1461465&r1=1461464&r2=1461465&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 Wed Mar 27 09:22:38 2013
@@ -149,8 +149,8 @@ public class MongoDocumentStore implemen
for (int i = 0; i < limit && cursor.hasNext(); i++) {
DBObject o = cursor.next();
Map<String, Object> map = convertFromDBObject(o);
- String path = (String) map.get(UpdateOp.ID);
- cache.put(path, map);
+ String key = (String) map.get(UpdateOp.ID);
+ cache.put(key, map);
list.add(map);
}
return list;
@@ -183,6 +183,7 @@ public class MongoDocumentStore implemen
BasicDBObject setUpdates = new BasicDBObject();
BasicDBObject incUpdates = new BasicDBObject();
+ BasicDBObject unsetUpdates = new BasicDBObject();
for (Entry<String, Operation> entry : updateOp.changes.entrySet()) {
String k = entry.getKey();
@@ -201,7 +202,7 @@ public class MongoDocumentStore implemen
break;
}
case REMOVE_MAP_ENTRY: {
- // TODO
+ unsetUpdates.append(k, "1");
break;
}
case SET_MAP_ENTRY: {
@@ -222,19 +223,28 @@ public class MongoDocumentStore implemen
if (!incUpdates.isEmpty()) {
update.append("$inc", incUpdates);
}
+ if (!unsetUpdates.isEmpty()) {
+ update.append("$unset", unsetUpdates);
+ }
-// dbCollection.update(query, update, true /*upsert*/, false /*multi*/,
-// WriteConcern.SAFE);
-// return null;
+ // dbCollection.update(query, update, true /*upsert*/, false /*multi*/,
+ // WriteConcern.SAFE);
+ // return null;
long start = start();
try {
DBObject oldNode = dbCollection.findAndModify(query, null /*fields*/,
- null /*sort*/, false /*remove*/, update, true /*returnNew*/,
+ null /*sort*/, false /*remove*/, update, false /*returnNew*/,
true /*upsert*/);
Map<String, Object> map = convertFromDBObject(oldNode);
- String path = (String) map.get(UpdateOp.ID);
- cache.put(path, map);
+
+ // cache the new document
+ Map<String, Object> newMap = Utils.newMap();
+ Utils.deepCopyMap(map, newMap);
+ String key = updateOp.getKey();
+ MemoryDocumentStore.applyChanges(newMap, updateOp);
+ cache.put(key, newMap);
+
log("createOrUpdate returns ", map);
return map;
} catch (Exception e) {
@@ -291,8 +301,8 @@ public class MongoDocumentStore implemen
return false;
}
for (Map<String, Object> map : maps) {
- String path = (String) map.get(UpdateOp.ID);
- cache.put(path, map);
+ String id = (String) map.get(UpdateOp.ID);
+ cache.put(id, map);
}
return true;
} catch (MongoException e) {
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=1461465&r1=1461464&r2=1461465&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 27 09:22:38 2013
@@ -341,8 +341,9 @@ public class MongoMK implements MicroKer
boolean isValidRevision(@Nonnull Revision rev,
@Nonnull Revision readRevision,
@Nonnull Map<String, Object> nodeMap) {
- //noinspection unchecked
- if (isCommitted(rev, readRevision, (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS))) {
+ @SuppressWarnings("unchecked")
+ Map<String, String> revisions = (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS);
+ if (isCommitted(rev, readRevision, revisions)) {
return true;
}
// check commit root
@@ -372,8 +373,9 @@ public class MongoMK implements MicroKer
if (nodeMap == null) {
return false;
}
- //noinspection unchecked
- return isCommitted(rev, readRevision, (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS));
+ @SuppressWarnings("unchecked")
+ Map<String, String> rootRevisions = (Map<String, String>) nodeMap.get(UpdateOp.REVISIONS);
+ return isCommitted(rev, readRevision, rootRevisions);
}
/**
@@ -847,6 +849,9 @@ public class MongoMK implements MicroKer
.get(UpdateOp.DELETED);
Revision firstRev = null;
String value = null;
+ if (valueMap == null) {
+ return null;
+ }
for (String r : valueMap.keySet()) {
Revision propRev = Revision.fromString(r);
if (isRevisionNewer(propRev, maxRev)
@@ -879,7 +884,11 @@ public class MongoMK implements MicroKer
@SuppressWarnings("unchecked")
Map<String, String> valueMap = (Map<String, String>) nodeMap
.get(UpdateOp.DELETED);
+ if (valueMap == null) {
+ return null;
+ }
Revision newestRev = null;
+ String newestValue = null;
for (String r : valueMap.keySet()) {
Revision propRev = Revision.fromString(r);
if (newestRev == null || isRevisionNewer(propRev, newestRev)) {
@@ -887,9 +896,14 @@ public class MongoMK implements MicroKer
if (!onlyCommitted || isValidRevision(propRev, before, nodeMap)) {
newestRev = propRev;
}
+ newestValue = valueMap.get(r);
}
}
}
+ if ("true".equals(newestValue)) {
+ // deleted in the newest revision
+ return null;
+ }
return newestRev;
}
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=1461465&r1=1461464&r2=1461465&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 Wed Mar 27 09:22:38 2013
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.mongomk.prototype;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.TreeMap;
/**
@@ -92,6 +93,10 @@ public class UpdateOp {
return path;
}
+ String getKey() {
+ return key;
+ }
+
boolean isNew() {
return isNew;
}
@@ -172,6 +177,17 @@ public class UpdateOp {
return (Long) op.value;
}
+ public UpdateOp getReverseOperation() {
+ UpdateOp reverse = new UpdateOp(path, key, isNew);
+ for (Entry<String, Operation> e : changes.entrySet()) {
+ Operation r = e.getValue().getReverse();
+ if (r != null) {
+ reverse.changes.put(e.getKey(), r);
+ }
+ }
+ return reverse;
+ }
+
public String toString() {
return "key: " + key + " " + (isNew ? "new" : "update") + " " + changes;
}
@@ -232,6 +248,27 @@ public class UpdateOp {
public String toString() {
return type + " " + value;
}
+
+ public Operation getReverse() {
+ Operation reverse = null;
+ switch (type) {
+ case INCREMENT:
+ reverse = new Operation();
+ reverse.type = Type.INCREMENT;
+ reverse.value = -(Long) value;
+ break;
+ case SET:
+ case REMOVE_MAP_ENTRY:
+ case SET_MAP_ENTRY:
+ // nothing to do
+ break;
+ case ADD_MAP_ENTRY:
+ reverse = new Operation();
+ reverse.type = Type.REMOVE_MAP_ENTRY;
+ break;
+ }
+ return reverse;
+ }
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Utils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Utils.java?rev=1461465&r1=1461464&r2=1461465&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Utils.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/Utils.java Wed Mar 27 09:22:38 2013
@@ -45,7 +45,10 @@ public class Utils {
}
@SuppressWarnings("unchecked")
- public static int getMapSize(Map<String, Object> map) {
+ public static int estimateMemoryUsage(Map<String, Object> map) {
+ if (map == null) {
+ return 0;
+ }
int size = 0;
for (Entry<String, Object> e : map.entrySet()) {
size += e.getKey().length();
@@ -55,7 +58,7 @@ public class Utils {
} else if (o instanceof Long) {
size += 8;
} else if (o instanceof Map) {
- size += 8 + getMapSize((Map<String, Object>) o);
+ size += 8 + estimateMemoryUsage((Map<String, Object>) o);
}
}
return size;
@@ -103,5 +106,25 @@ public class Utils {
int index = id.indexOf(':');
return id.substring(index + 1);
}
+
+ /**
+ * Deep copy of a map that may contain map values.
+ *
+ * @param source the source map
+ * @param target the target map
+ */
+ public static <K> void deepCopyMap(Map<K, Object> source, Map<K, Object> target) {
+ for (Entry<K, Object> e : source.entrySet()) {
+ Object value = e.getValue();
+ if (value instanceof Map<?, ?>) {
+ @SuppressWarnings("unchecked")
+ Map<Object, Object> old = (Map<Object, Object>) value;
+ Map<Object, Object> c = newMap();
+ deepCopyMap(old, c);
+ value = c;
+ }
+ target.put(e.getKey(), value);
+ }
+ }
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/ClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/ClusterTest.java?rev=1461465&r1=1461464&r2=1461465&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/ClusterTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/ClusterTest.java Wed Mar 27 09:22:38 2013
@@ -30,7 +30,7 @@ import com.mongodb.DB;
public class ClusterTest {
private static final boolean MONGO_DB = false;
-// private static final boolean MONGO_DB = true;
+ // private static final boolean MONGO_DB = true;
private MemoryDocumentStore ds;
private MemoryBlobStore bs;
@@ -43,12 +43,9 @@ public class ClusterTest {
String m1r0 = mk1.getHeadRevision();
String m2r0 = mk2.getHeadRevision();
-// String m1r1 = mk1.commit("/", "+\"testa\":{}", m1r0, null);
-// String m2r1 = mk2.commit("/", "+\"testb\":{}", m2r0, null);
-
- String m1r2 = mk1.commit("/", "+\"test\":{}", m1r0, null);
+ mk1.commit("/", "+\"test\":{}", m1r0, null);
try {
- String m2r2 = mk2.commit("/", "+\"test\":{}", m2r0, null);
+ mk2.commit("/", "+\"test\":{}", m2r0, null);
fail();
} catch (MicroKernelException e) {
// expected
@@ -57,6 +54,28 @@ public class ClusterTest {
mk1.dispose();
mk2.dispose();
}
+
+ @Test
+ public void rollbackAfterConflict() {
+ MongoMK mk1 = createMK(1);
+ MongoMK mk2 = createMK(2);
+
+ String m1r0 = mk1.getHeadRevision();
+ String m2r0 = mk2.getHeadRevision();
+
+ mk1.commit("/", "+\"test\":{}", m1r0, null);
+ try {
+ mk2.commit("/", "+\"a\": {} +\"test\":{}", m2r0, null);
+ fail();
+ } catch (MicroKernelException e) {
+ // expected
+ }
+ mk2.commit("/", "+\"a\": {}", null, null);
+
+ mk1.dispose();
+ mk2.dispose();
+ }
+
private MongoMK createMK(int clusterId) {
if (MONGO_DB) {
Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKBranchMergeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKBranchMergeTest.java?rev=1461465&r1=1461464&r2=1461465&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKBranchMergeTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKBranchMergeTest.java Wed Mar 27 09:22:38 2013
@@ -80,7 +80,7 @@ public class MongoMKBranchMergeTest exte
assertNodesExist(null, "/root", "/root/child1");
String branchRev = mk.branch(null);
- System.out.println("branchRev: " + branchRev);
+ // System.out.println("branchRev: " + branchRev);
addNodes(null, "/root/child2");
assertNodesExist(null, "/root", "/root/child1", "/root/child2");
Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKCommitMoveTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKCommitMoveTest.java?rev=1461465&r1=1461464&r2=1461465&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKCommitMoveTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/MongoMKCommitMoveTest.java Wed Mar 27 09:22:38 2013
@@ -16,15 +16,15 @@
*/
package org.apache.jackrabbit.mongomk.prototype;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import org.apache.jackrabbit.mongomk.impl.MongoMicroKernel;
import org.json.simple.JSONObject;
import org.junit.Ignore;
import org.junit.Test;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
/**
* Tests for {@link MongoMicroKernel#commit(String, String, String, String)}
* with emphasis on move operations.
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=1461465&r1=1461464&r2=1461465&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 27 09:22:38 2013
@@ -22,7 +22,9 @@ import static org.junit.Assert.assertEqu
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
import org.apache.jackrabbit.mongomk.prototype.DocumentStore.Collection;
import org.apache.jackrabbit.mongomk.prototype.Node.Children;
import org.junit.Test;
@@ -36,7 +38,7 @@ import com.mongodb.DB;
public class SimpleTest {
private static final boolean MONGO_DB = false;
-// private static final boolean MONGO_DB = true;
+ // private static final boolean MONGO_DB = true;
@Test
public void test() {
@@ -128,6 +130,22 @@ public class SimpleTest {
}
@Test
+ public void conflict() {
+ MongoMK mk = createMK();
+ mk.commit("/", "+\"a\": {}", null, null);
+ try {
+ mk.commit("/", "+\"b\": {} +\"a\": {}", null, null);
+ fail();
+ } catch (MicroKernelException e) {
+ // expected
+ }
+ // the previous commit should be rolled back now,
+ // so this should work
+ mk.commit("/", "+\"b\": {}", null, null);
+ mk.dispose();
+ }
+
+ @Test
public void diff() {
MongoMK mk = createMK();