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 mr...@apache.org on 2013/07/04 16:35:33 UTC
svn commit: r1499769 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/mongomk/
test/java/org/apache/jackrabbit/oak/plugins/mongomk/
Author: mreutegg
Date: Thu Jul 4 14:35:32 2013
New Revision: 1499769
URL: http://svn.apache.org/r1499769
Log:
OAK-619 Lock-free MongoMK implementation
- More branch isolation tests
- Do not update _lastRev for branch commits
- Apply _lastRev of branch commits on merge
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Branch.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Commit.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMK.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnmergedBranches.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ClusterTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKBranchTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKTestBase.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Branch.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Branch.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Branch.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Branch.java Thu Jul 4 14:35:32 2013
@@ -17,8 +17,10 @@
package org.apache.jackrabbit.oak.plugins.mongomk;
import java.util.SortedSet;
+import java.util.TreeMap;
import java.util.TreeSet;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import static com.google.common.base.Preconditions.checkArgument;
@@ -32,17 +34,19 @@ class Branch {
/**
* The commits to the branch
*/
- private final SortedSet<Revision> commits;
+ private final TreeMap<Revision, UnsavedModifications> commits;
private final Revision base;
- Branch(@Nonnull SortedSet<Revision> commits, @Nonnull Revision base) {
- this.commits = checkNotNull(commits);
- this.base = base;
- }
-
- synchronized Revision getHead() {
- return commits.last();
+ Branch(@Nonnull SortedSet<Revision> commits,
+ @Nonnull Revision base,
+ @Nonnull Revision.RevisionComparator comparator) {
+ this.base = checkNotNull(base);
+ this.commits = new TreeMap<Revision, UnsavedModifications>(
+ checkNotNull(comparator));
+ for (Revision r : commits) {
+ this.commits.put(r, new UnsavedModifications());
+ }
}
Revision getBase() {
@@ -50,19 +54,83 @@ class Branch {
}
synchronized void addCommit(@Nonnull Revision r) {
- checkArgument(commits.comparator().compare(r, commits.last()) > 0);
- commits.add(r);
+ checkArgument(commits.comparator().compare(r, commits.lastKey()) > 0);
+ commits.put(r, new UnsavedModifications());
}
synchronized SortedSet<Revision> getCommits() {
- return new TreeSet<Revision>(commits);
+ SortedSet<Revision> revisions = new TreeSet<Revision>(commits.comparator());
+ revisions.addAll(commits.keySet());
+ return revisions;
+ }
+
+ synchronized boolean hasCommits() {
+ return !commits.isEmpty();
}
synchronized boolean containsCommit(@Nonnull Revision r) {
- return commits.contains(r);
+ return commits.containsKey(r);
}
public synchronized void removeCommit(@Nonnull Revision rev) {
commits.remove(rev);
}
+
+ /**
+ * Gets the unsaved modifications for the given branch commit revision.
+ *
+ * @param r a branch commit revision.
+ * @return the unsaved modification for the given branch commit.
+ * @throws IllegalArgumentException if there is no commit with the given
+ * revision.
+ */
+ @Nonnull
+ public synchronized UnsavedModifications getModifications(@Nonnull Revision r) {
+ UnsavedModifications modifications = commits.get(r);
+ if (modifications == null) {
+ throw new IllegalArgumentException(
+ "Revision " + r + " is not a commit in this branch");
+ }
+ return modifications;
+ }
+
+ /**
+ * Applies all unsaved modification of this branch to the given collection
+ * of unsaved trunk modifications. A modification is only applied if there
+ * is no modification in <code>trunk</code> for a given path or if the
+ * <code>trunk</code> modification is earlier.
+ *
+ * @param trunk the unsaved trunk modifications.
+ */
+ public synchronized void applyTo(@Nonnull UnsavedModifications trunk) {
+ checkNotNull(trunk);
+ for (UnsavedModifications modifications : commits.values()) {
+ modifications.applyTo(trunk);
+ }
+ }
+
+ /**
+ * Gets the most recent unsaved last revision at <code>readRevision</code>
+ * or earlier in this branch for the given <code>path</code>.
+ *
+ * @param path the path of a node.
+ * @param readRevision the read revision.
+ * @return the most recent unsaved last revision or <code>null</code> if
+ * there is none in this branch.
+ */
+ @CheckForNull
+ public synchronized Revision getUnsavedLastRevision(String path,
+ Revision readRevision) {
+ for (Revision r : commits.descendingKeySet()) {
+ if (readRevision.compareRevisionTime(r) < 0) {
+ continue;
+ }
+ UnsavedModifications modifications = commits.get(r);
+ Revision modRevision = modifications.get(path);
+ if (modRevision != null) {
+ return modRevision;
+ }
+ }
+ return null;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Commit.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Commit.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Commit.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Commit.java Thu Jul 4 14:35:32 2013
@@ -117,7 +117,6 @@ public class Commit {
UpdateOp op = getUpdateOperationForNode(path);
String key = Utils.escapePropertyName(propertyName);
op.setMapEntry(key, revision.toString(), value);
- op.setMapEntry(UpdateOp.LAST_REV, "" + revision.getClusterId(), revision.toString());
}
void addNode(Node n) {
@@ -136,14 +135,14 @@ public class Commit {
void apply() {
if (!operations.isEmpty()) {
applyToDocumentStore();
- applyToCache();
+ applyToCache(false);
}
}
void prepare(Revision baseRevision) {
if (!operations.isEmpty()) {
applyToDocumentStore(baseRevision);
- applyToCache();
+ applyToCache(true);
}
}
@@ -197,7 +196,11 @@ public class Commit {
UpdateOp commitRoot = getUpdateOperationForNode(commitRootPath);
for (String p : operations.keySet()) {
UpdateOp op = operations.get(p);
- op.setMapEntry(UpdateOp.LAST_REV, "" + revision.getClusterId(), revision.toString());
+ if (baseBranchRevision == null) {
+ // only apply _lastRev for trunk commits, _lastRev for
+ // branch commits only become visible on merge
+ op.setMapEntry(UpdateOp.LAST_REV, "" + revision.getClusterId(), revision.toString());
+ }
if (op.isNew) {
op.setMapEntry(UpdateOp.DELETED, revision.toString(), "false");
}
@@ -465,7 +468,7 @@ public class Commit {
/**
* Apply the changes to the MongoMK (to update the cache).
*/
- public void applyToCache() {
+ public void applyToCache(boolean isBranchCommit) {
HashMap<String, ArrayList<String>> nodesWithChangedChildren = new HashMap<String, ArrayList<String>>();
ArrayList<String> addOrRemove = new ArrayList<String>();
addOrRemove.addAll(addedNodes);
@@ -497,7 +500,7 @@ public class Commit {
boolean isWritten = op != null;
boolean isDelete = op != null && op.isDelete;
mk.applyChanges(revision, path,
- isNew, isDelete, isWritten,
+ isNew, isDelete, isWritten, isBranchCommit,
added, removed);
}
}
@@ -536,7 +539,6 @@ public class Commit {
UpdateOp op = getUpdateOperationForNode(path);
op.setDelete(true);
op.setMapEntry(UpdateOp.DELETED, revision.toString(), "true");
- op.setMapEntry(UpdateOp.LAST_REV, "" + revision.getClusterId(), revision.toString());
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMK.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMK.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMK.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMK.java Thu Jul 4 14:35:32 2013
@@ -21,6 +21,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -171,8 +172,7 @@ public class MongoMK implements MicroKer
*
* Key: path, value: revision.
*/
- private final Map<String, Revision> unsavedLastRevisions =
- new ConcurrentHashMap<String, Revision>();
+ private final UnsavedModifications unsavedLastRevisions = new UnsavedModifications();
/**
* The last known revision for each cluster instance.
@@ -365,10 +365,10 @@ public class MongoMK implements MicroKer
}
void backgroundWrite() {
- if (unsavedLastRevisions.size() == 0) {
+ if (unsavedLastRevisions.getPaths().size() == 0) {
return;
}
- ArrayList<String> paths = new ArrayList<String>(unsavedLastRevisions.keySet());
+ ArrayList<String> paths = new ArrayList<String>(unsavedLastRevisions.getPaths());
// sort by depth (high depth first), then path
Collections.sort(paths, new Comparator<String>() {
@@ -655,43 +655,19 @@ public class MongoMK implements MicroKer
return c;
}
- private Node readNode(String path, Revision rev) {
+ private Node readNode(String path, Revision readRevision) {
String id = Utils.getIdFromPath(path);
Map<String, Object> map = store.find(DocumentStore.Collection.NODES, id);
if (map == null) {
return null;
}
- Revision min = getLiveRevision(map, rev);
+ Revision min = getLiveRevision(map, readRevision);
if (min == null) {
// deleted
return null;
}
- Node n = new Node(path, rev);
- Revision lastRevision = null;
- Revision revision = unsavedLastRevisions.get(path);
- if (revision != null) {
- if (isRevisionNewer(revision, rev)) {
- // at most the read revision
- revision = rev;
- }
- lastRevision = revision;
- }
+ Node n = new Node(path, readRevision);
for (String key : map.keySet()) {
- if (key.equals(UpdateOp.LAST_REV)) {
- Object v = map.get(key);
- @SuppressWarnings("unchecked")
- Map<String, String> valueMap = (Map<String, String>) v;
- for (String r : valueMap.keySet()) {
- revision = Revision.fromString(valueMap.get(r));
- if (isRevisionNewer(revision, rev)) {
- // at most the read revision
- revision = rev;
- }
- if (lastRevision == null || isRevisionNewer(revision, lastRevision)) {
- lastRevision = revision;
- }
- }
- }
if (!Utils.isPropertyName(key)) {
continue;
}
@@ -704,11 +680,65 @@ public class MongoMK implements MicroKer
// use descending keys (newest first) if map is sorted
valueMap = ((TreeMap<String, String>) valueMap).descendingMap();
}
- String value = getLatestValue(valueMap, min, rev);
+ String value = getLatestValue(valueMap, min, readRevision);
String propertyName = Utils.unescapePropertyName(key);
n.setProperty(propertyName, value);
}
}
+
+ // when was this node last modified?
+ Revision lastRevision = null;
+ Map<String, Revision> lastRevs = new HashMap<String, Revision>();
+ @SuppressWarnings("unchecked")
+ Map<String, String> valueMap = (Map<String, String>) map.get(UpdateOp.LAST_REV);
+ if (valueMap != null) {
+ for (String clusterId : valueMap.keySet()) {
+ lastRevs.put(clusterId, Revision.fromString(valueMap.get(clusterId)));
+ }
+ }
+ // overlay with unsaved last modified from this instance
+ Revision lastModified = unsavedLastRevisions.get(path);
+ Branch branch = branches.getBranch(readRevision);
+ if (lastModified != null) {
+ if (branch != null) {
+ // visible from this branch if revision is
+ // not newer than base of branch
+ if (!isRevisionNewer(lastModified, branch.getBase())) {
+ lastRevs.put(String.valueOf(clusterId), lastModified);
+ }
+ } else {
+ // non-branch read -> check if newer
+ if (isRevisionNewer(lastModified, readRevision)) {
+ // at most readRevision
+ lastRevs.put(String.valueOf(clusterId), readRevision);
+ } else {
+ lastRevs.put(String.valueOf(clusterId), lastModified);
+ }
+ }
+ }
+ if (branch != null) {
+ // read from a branch
+ // -> overlay with unsaved last revs from branch
+ Revision r = branch.getUnsavedLastRevision(path, readRevision);
+ if (r != null) {
+ lastRevs.put(String.valueOf(clusterId), r);
+ }
+ }
+
+ for (String r : lastRevs.keySet()) {
+ lastModified = lastRevs.get(r);
+ if (isRevisionNewer(lastModified, readRevision)) {
+ // at most the read revision
+ lastModified = readRevision;
+ }
+ if (lastRevision == null || isRevisionNewer(lastModified, lastRevision)) {
+ lastRevision = lastModified;
+ }
+ }
+ if (lastRevision == null) {
+ // use readRevision if none found
+ lastRevision = readRevision;
+ }
n.setLastRevision(lastRevision);
return n;
}
@@ -1089,7 +1119,7 @@ public class MongoMK implements MicroKer
} finally {
if (!success) {
b.removeCommit(rev);
- if (b.getCommits().isEmpty()) {
+ if (!b.hasCommits()) {
branches.remove(b);
}
}
@@ -1432,6 +1462,7 @@ public class MongoMK implements MicroKer
}
if (store.findAndUpdate(DocumentStore.Collection.NODES, op) != null) {
// remove from branchCommits map after successful update
+ b.applyTo(unsavedLastRevisions);
branches.remove(b);
} else {
throw new MicroKernelException("Conflicting concurrent change. Update operation failed: " + op);
@@ -1499,18 +1530,28 @@ public class MongoMK implements MicroKer
* @param isNew whether this is a new node
* @param isDelete whether the node is deleted
* @param isWritten whether the MongoDB documented was added / updated
+ * @param isBranchCommit whether this is from a branch commit
* @param added the list of added child nodes
* @param removed the list of removed child nodes
+ *
*/
public void applyChanges(Revision rev, String path,
- boolean isNew, boolean isDelete, boolean isWritten,
- ArrayList<String> added, ArrayList<String> removed) {
- if (!isWritten) {
- Revision prev = unsavedLastRevisions.put(path, rev);
+ boolean isNew, boolean isDelete, boolean isWritten,
+ boolean isBranchCommit, ArrayList<String> added,
+ ArrayList<String> removed) {
+ UnsavedModifications unsaved = unsavedLastRevisions;
+ if (isBranchCommit) {
+ unsaved = branches.getBranch(rev).getModifications(rev);
+ }
+ // track unsaved modifications of nodes that were not
+ // written in the commit (implicitly modified parent)
+ // or any modification if this is a branch commit
+ if (!isWritten || isBranchCommit) {
+ Revision prev = unsaved.put(path, rev);
if (prev != null) {
if (isRevisionNewer(prev, rev)) {
// revert
- unsavedLastRevisions.put(path, prev);
+ unsaved.put(path, prev);
String msg = String.format("Attempt to update " +
"unsavedLastRevision for %s with %s, which is " +
"older than current %s.",
@@ -1521,7 +1562,7 @@ public class MongoMK implements MicroKer
} else {
// the document was updated:
// we no longer need to update it in a background process
- unsavedLastRevisions.remove(path);
+ unsaved.remove(path);
}
Children c = nodeChildrenCache.getIfPresent(path + "@" + rev);
if (isNew || (!isDelete && c != null)) {
@@ -1555,7 +1596,7 @@ public class MongoMK implements MicroKer
}
public int getPendingWriteCount() {
- return unsavedLastRevisions.size();
+ return unsavedLastRevisions.getPaths().size();
}
public boolean isCached(String path) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java Thu Jul 4 14:35:32 2013
@@ -79,7 +79,6 @@ public class Node implements CacheValue
op.set(UpdateOp.ID, id);
Commit.setModified(op, rev);
op.setMapEntry(UpdateOp.DELETED, rev.toString(), "false");
- op.setMapEntry(UpdateOp.LAST_REV, "" + rev.getClusterId(), rev.toString());
for (String p : properties.keySet()) {
String key = Utils.escapePropertyName(p);
op.setMapEntry(key, rev.toString(), properties.get(p));
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnmergedBranches.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnmergedBranches.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnmergedBranches.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnmergedBranches.java Thu Jul 4 14:35:32 2013
@@ -93,7 +93,7 @@ class UnmergedBranches {
commits.add(base);
base = tmp.remove(base);
}
- branches.add(new Branch(commits, base));
+ branches.add(new Branch(commits, base, comparator));
}
}
}
@@ -109,7 +109,7 @@ class UnmergedBranches {
Branch create(@Nonnull Revision base, @Nonnull Revision initial) {
SortedSet<Revision> commits = new TreeSet<Revision>(comparator);
commits.add(checkNotNull(initial));
- Branch b = new Branch(commits, checkNotNull(base));
+ Branch b = new Branch(commits, checkNotNull(base), comparator);
synchronized (branches) {
branches.add(b);
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java?rev=1499769&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java Thu Jul 4 14:35:32 2013
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.mongomk;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Keeps track of when nodes where last modified. To be persisted later by
+ * a background thread.
+ */
+class UnsavedModifications {
+
+ private final ConcurrentHashMap<String, Revision> map = new ConcurrentHashMap<String, Revision>();
+
+ @CheckForNull
+ public Revision put(@Nonnull String path, @Nonnull Revision revision) {
+ return map.put(checkNotNull(path), checkNotNull(revision));
+ }
+
+ @CheckForNull
+ public Revision get(String path) {
+ return map.get(path);
+ }
+
+ @CheckForNull
+ public Revision remove(String path) {
+ return map.remove(path);
+ }
+
+ @Nonnull
+ public Collection<String> getPaths() {
+ return map.keySet();
+ }
+
+ /**
+ * Applies all modifications from this instance to the <code>other</code>.
+ * A modification is only applied if there is no modification in other
+ * for a given path or if the other modification is earlier.
+ *
+ * @param other the other <code>UnsavedModifications</code>.
+ */
+ public void applyTo(UnsavedModifications other) {
+ for (Map.Entry<String, Revision> entry : map.entrySet()) {
+ Revision r = other.map.putIfAbsent(entry.getKey(), entry.getValue());
+ if (r != null) {
+ if (r.compareRevisionTime(entry.getValue()) < 0) {
+ other.map.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/UnsavedModifications.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ClusterTest.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ClusterTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ClusterTest.java Thu Jul 4 14:35:32 2013
@@ -168,20 +168,23 @@ public class ClusterTest {
}
@Test
- public void clusterBranchInVisibility() {
- MongoMK mk1 = createMK(0);
+ public void clusterBranchInVisibility() throws InterruptedException {
+ MongoMK mk1 = createMK(1);
mk1.commit("/", "+\"regular\": {}", null, null);
String b1 = mk1.branch(null);
String b2 = mk1.branch(null);
b1 = mk1.commit("/", "+\"branchVisible\": {}", b1, null);
b2 = mk1.commit("/", "+\"branchInvisible\": {}", b2, null);
mk1.merge(b1, null);
-
- MongoMK mk2 = createMK(0);
+ // mk1.merge only becomes visible to mk2 after async delay
+ // therefore dispose mk1 now to make sure it flushes
+ // unsaved last revisions
+ mk1.dispose();
+
+ MongoMK mk2 = createMK(2);
String nodes = mk2.getNodes("/", null, 0, 0, 100, null);
assertEquals("{\"branchVisible\":{},\"regular\":{},\":childNodeCount\":2}", nodes);
- mk1.dispose();
mk2.dispose();
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKBranchTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKBranchTest.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKBranchTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKBranchTest.java Thu Jul 4 14:35:32 2013
@@ -20,6 +20,7 @@ import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -74,4 +75,55 @@ public class MongoMKBranchTest extends B
JSONObject obj = (JSONObject) parser.parse(json);
assertTrue(obj.containsKey("foo"));
}
+
+ @Test
+ public void branchIsolation1() throws Exception {
+ String filter = "{\"properties\":[\"*\",\":hash\",\":id\"]}";
+ String baseRev = mk.commit("/", "+\"test\":{\"node\":{}}", null, null);
+
+ // branch commit under /test/node
+ String branchRev = mk.branch(baseRev);
+ String branchRev1 = mk.commit("/test/node", "+\"branch-node\":{}", branchRev, null);
+
+ // trunk commit under /test/node
+ String rev1 = mk.commit("/test/node", "+\"trunk-node\":{}", null, null);
+
+ // branch commit on /
+ String branchRev2 = mk.commit("/", "+\"other\":{}", branchRev1, null);
+
+ // get /test on branch and use returned identifier to get next level
+ String json = mk.getNodes("/test", branchRev2, 0, 0, 1000, filter);
+
+ JSONObject test = parseJSONObject(json);
+ String id = resolveValue(test, ":id").toString();
+ String revision = id.split("@")[1];
+ assertNodesExist(revision, "/test/node/branch-node");
+ assertNodesNotExist(revision, "/test/node/trunk-node");
+ }
+
+ @Test
+ public void branchIsolation2() throws Exception {
+ String filter = "{\"properties\":[\"*\",\":hash\",\":id\"]}";
+ String baseRev = mk.commit("/", "+\"test\":{\"node\":{}}", null, null);
+ String branchRev = mk.branch(baseRev);
+
+ // trunk commit under /test/node
+ String rev1 = mk.commit("/test/node", "+\"trunk-node\":{}", null, null);
+
+ // branch commit under /test/node
+ String branchRev1 = mk.commit("/test/node", "+\"branch-node\":{}", branchRev, null);
+
+ // trunk commit on /
+ String rev2 = mk.commit("/", "+\"other\":{}", null, null);
+
+ // get /test on trunk and use returned identifier to get next level
+ String json = mk.getNodes("/test", rev2, 0, 0, 1000, filter);
+
+ JSONObject test = parseJSONObject(json);
+ String id = resolveValue(test, ":id").toString();
+ String revision = id.split("@")[1];
+ assertEquals(rev1, revision);
+ assertNodesExist(revision, "/test/node/trunk-node");
+ assertNodesNotExist(revision, "/test/node/branch-node");
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKTestBase.java?rev=1499769&r1=1499768&r2=1499769&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKTestBase.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoMKTestBase.java Thu Jul 4 14:35:32 2013
@@ -163,7 +163,7 @@ public abstract class MongoMKTestBase {
throw new AssertionError("failed to resolve JSONObject value at " + relPath + ": " + val);
}
- private static Object resolveValue(JSONObject obj, String relPath) {
+ protected static Object resolveValue(JSONObject obj, String relPath) {
String[] names = relPath.split("/");
Object val = obj;
for (String name : names) {