Index: oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java =================================================================== --- oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java (revision 1421326) +++ oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java (working copy) @@ -1,5 +1,6 @@ package org.apache.jackrabbit.mongomk.impl.command; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -13,6 +14,7 @@ import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction; import org.apache.jackrabbit.mongomk.impl.model.CommitBuilder; import org.apache.jackrabbit.mongomk.impl.model.MongoCommit; +import org.apache.jackrabbit.mongomk.impl.model.MongoNode; import org.apache.jackrabbit.mongomk.impl.model.NodeImpl; import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeDelta; import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeDelta.Conflict; @@ -23,6 +25,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.DBObject; +import com.mongodb.QueryBuilder; + /** * A {@code Command} for {@code MongoMicroKernel#merge(String, String)} */ @@ -33,6 +41,10 @@ private final String branchRevisionId; private final String message; + private int branchDepth = -1; + //private String branchRootPath; + private Map nodes = new HashMap(); + /** * Constructs a {@code MergeCommandMongo} * @@ -45,6 +57,7 @@ super(nodeStore); this.branchRevisionId = branchRevisionId; this.message = message; + nodes = new HashMap(); } @Override @@ -56,6 +69,8 @@ throw new Exception("Can only merge a private branch commit"); } + getBranchRootAndDepth(branchId); + long rootNodeId = commit.getRevisionId(); FetchHeadRevisionIdAction query2 = new FetchHeadRevisionIdAction(nodeStore); @@ -69,7 +84,7 @@ // Merge nodes from head to branch. ourRoot = mergeNodes(ourRoot, currentHead, branchRootId); - Node currentHeadNode = getNode("/", currentHead); + Node currentHeadNode = getNode("/", currentHead, false); String diff = new DiffBuilder(MongoUtil.wrap(currentHeadNode), MongoUtil.wrap(ourRoot), "/", -1, @@ -108,7 +123,7 @@ MongoNodeDelta ourChanges = new MongoNodeDelta(new SimpleMongoNodeStore(), MongoUtil.wrap(baseNode), MongoUtil.wrap(ourNode)); - NodeImpl stagedNode = (NodeImpl)theirNode; //new NodeImpl(path); + NodeImpl stagedNode = (NodeImpl)theirNode; // Apply our changes. stagedNode.getProperties().putAll(ourChanges.getAddedProperties()); @@ -178,9 +193,50 @@ return getNode(path, revisionId, null); } + private Node getNode(String path, long revisionId, boolean getFromCache) throws Exception { + return getNode(path, revisionId, null, getFromCache); + } + private Node getNode(String path, long revisionId, String branchId) throws Exception { + return getNode(path, revisionId, branchId, true); + } + + private Node getNode(String path, long revisionId, String branchId, boolean getFromCache) throws Exception { + String key = path + "*" + branchId + "*" + revisionId; + if (getFromCache && nodes.containsKey(key)) { + return nodes.get(key); + } GetNodesCommandNew command = new GetNodesCommandNew(nodeStore, path, revisionId); command.setBranchId(branchId); - return command.execute(); + command.setDepth(branchDepth); + Node node = command.execute(); + nodes.put(key, node); + return node; + } + + private void getBranchRootAndDepth(String branchId) { + DBCollection collection = nodeStore.getNodeCollection(); + DBObject query = QueryBuilder.start(MongoNode.KEY_BRANCH_ID).is(branchId).get(); + DBObject keys = new BasicDBObject(MongoNode.KEY_DEPTH, 1); + //DBObject orderBy = new BasicDBObject(MongoNode.KEY_DEPTH, -1); + // DBCursor dbCursor = collection.find(query, keys).sort(orderBy).limit(1); + DBCursor dbCursor = collection.find(query, keys).limit(1); + if (dbCursor.hasNext()) { + MongoNode node = (MongoNode)dbCursor.next(); + branchDepth = node.getDepth() + 1; + System.out.println(branchDepth); + } else { + branchDepth = -1; + } +// +// keys.put(MongoNode.KEY_PATH, 1); +// orderBy = new BasicDBObject(MongoNode.KEY_DEPTH, 1); +// dbCursor = collection.find(query, keys).sort(orderBy).limit(1); +// if (dbCursor.hasNext()) { +// MongoNode node = (MongoNode)dbCursor.next(); +// branchRootPath = node.getPath(); +// } else { +// branchRootPath = "/"; +// } } } \ No newline at end of file Index: oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKBranchMergeTest.java =================================================================== --- oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKBranchMergeTest.java (revision 1421704) +++ oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKBranchMergeTest.java (working copy) @@ -15,6 +15,59 @@ public class MongoMKBranchMergeTest extends BaseMongoMicroKernelTest { @Test + public void test1() { + String rev = mk.commit("", "+\"/a\":{}", null, null); + String branchRev = mk.branch(rev); + + rev = mk.commit("", "+\"/a/b1\":{}", null, null); + + branchRev = mk.commit("", "+\"/a/a1\":{}", branchRev, null); + branchRev = mk.commit("", "+\"/a/a1/a2\":{}", branchRev, null); + branchRev = mk.commit("", "+\"/a/a1/a2/a3\":{}", branchRev, null); + + rev = mk.merge(branchRev, null); + + assertTrue(mk.nodeExists("/a/a1/a2/a3", null)); + assertTrue(mk.nodeExists("/a/b1", null)); + } + + @Test + public void test2() { + String rev = mk.commit("", "+\"/a\":{}", null, null); + String branchRev = mk.branch(rev); + + branchRev = mk.commit("", "+\"/a/b1\":{}", branchRev, null); + + rev = mk.commit("", "+\"/a/a1\":{}", null, null); + rev = mk.commit("", "+\"/a/a1/a2\":{}", null, null); + rev = mk.commit("", "+\"/a/a1/a2/a3\":{}", null, null); + + rev = mk.merge(branchRev, null); + + assertTrue(mk.nodeExists("/a/a1/a2/a3", null)); + assertTrue(mk.nodeExists("/a/b1", null)); + } + + @Test + public void foo() { + String rev = mk.commit("", "+\"/a\":{}", null, null); + String branchRev = mk.branch(rev); + branchRev = mk.commit("", "+\"/a/b\":{}", branchRev, null); + branchRev = mk.commit("", "+\"/a/b/b2\":{}", branchRev, null); + rev = mk.commit("", "+\"/a/c\":{}", rev, null); + rev = mk.commit("", "+\"/a/c/c2\":{}", rev, null); + rev = mk.commit("", "+\"/a/c/c2/c3\":{}", rev, null); + //rev = mk.commit("", "+\"/a/c\":{}", rev, null); + rev = mk.merge(branchRev, ""); + + assertTrue(mk.nodeExists("/a/b", null)); + assertTrue(mk.nodeExists("/a/b/b2", null)); + assertTrue(mk.nodeExists("/a/c", null)); + assertTrue(mk.nodeExists("/a/c/c2", null)); + assertTrue(mk.nodeExists("/a/c/c2/c3", null)); + } + + @Test public void oneBranchAddedChildren1() { addNodes(null, "/trunk", "/trunk/child1"); assertNodesExist(null, "/trunk", "/trunk/child1"); Index: oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/MongoNode.java =================================================================== --- oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/MongoNode.java (revision 1421326) +++ oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/MongoNode.java (working copy) @@ -32,6 +32,7 @@ public class MongoNode extends BasicDBObject { public static final String KEY_CHILDREN = "children"; + public static final String KEY_DEPTH = "depth"; public static final String KEY_PATH = "path"; public static final String KEY_PROPERTIES = "props"; public static final String KEY_REVISION_ID = "revId"; @@ -107,6 +108,11 @@ public void setPath(String path) { put(KEY_PATH, path); + put(KEY_DEPTH, PathUtils.getDepth(path)); + } + + public int getDepth() { + return getInt(KEY_DEPTH); } @SuppressWarnings("unchecked") Index: oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java =================================================================== --- oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java (revision 1421786) +++ oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java (working copy) @@ -252,12 +252,16 @@ return; } DBCollection commitCollection = getCommitCollection(); + DBObject index = new BasicDBObject(); - index.put(MongoCommit.KEY_REVISION_ID, 1L); + index.put(MongoCommit.KEY_REVISION_ID, -1L); index.put(MongoCommit.KEY_BRANCH_ID, 1L); + DBObject options = new BasicDBObject(); options.put("unique", Boolean.TRUE); + commitCollection.ensureIndex(index, options); + MongoCommit commit = new MongoCommit(); commit.setAffectedPaths(Arrays.asList(new String[] { "/" })); commit.setBaseRevisionId(0L); @@ -278,12 +282,19 @@ index.put(MongoNode.KEY_PATH, 1L); index.put(MongoNode.KEY_REVISION_ID, -1L); index.put(MongoNode.KEY_BRANCH_ID, 1L); + //index.put(MongoNode.KEY_DEPTH, -1L); DBObject options = new BasicDBObject(); options.put("unique", Boolean.TRUE); nodeCollection.ensureIndex(index, options); + DBObject index2 = new BasicDBObject(); + index2.put(MongoNode.KEY_BRANCH_ID, 1L); + index2.put(MongoNode.KEY_DEPTH, -1L); + + nodeCollection.ensureIndex(index2); + MongoNode root = new MongoNode(); root.setRevisionId(0L); root.setPath("/");