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/01/15 11:09:57 UTC
svn commit: r1433336 - in /jackrabbit/oak/trunk/oak-mongomk/src:
main/java/org/apache/jackrabbit/mongomk/impl/command/
main/java/org/apache/jackrabbit/mongomk/impl/json/
main/java/org/apache/jackrabbit/mongomk/impl/model/
test/java/org/apache/jackrabbi...
Author: mreutegg
Date: Tue Jan 15 10:09:56 2013
New Revision: 1433336
URL: http://svn.apache.org/viewvc?rev=1433336&view=rev
Log:
OAK-535: MergeCommand reads complete tree into memory
- special case trivial merges when there were no commits to trunk in the meantime
Modified:
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/DefaultJsopHandler.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/JsopParser.java
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/CommitBuilder.java
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/json/JsopParserTest.java
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java?rev=1433336&r1=1433335&r2=1433336&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java Tue Jan 15 10:09:56 2013
@@ -4,6 +4,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
import org.apache.jackrabbit.mk.model.tree.NodeState;
import org.apache.jackrabbit.mongomk.api.command.Command;
@@ -12,6 +13,8 @@ import org.apache.jackrabbit.mongomk.api
import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction;
import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction;
+import org.apache.jackrabbit.mongomk.impl.json.DefaultJsopHandler;
+import org.apache.jackrabbit.mongomk.impl.json.JsopParser;
import org.apache.jackrabbit.mongomk.impl.model.CommitBuilder;
import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
import org.apache.jackrabbit.mongomk.impl.model.NodeImpl;
@@ -62,34 +65,67 @@ public class MergeCommand extends BaseCo
FetchHeadRevisionIdAction query2 = new FetchHeadRevisionIdAction(nodeStore);
long currentHead = query2.execute();
- Node ourRoot = getNode("/", rootNodeId, branchId);
-
long branchRootId = Long.parseLong(branchId.substring(0, branchId.indexOf("-")));
- // Merge changes, if any, from trunk to branch.
- Node currentHeadNode = getNode("/", currentHead);
- if (currentHead != branchRootId) {
- ourRoot = mergeNodes(ourRoot, currentHeadNode, branchRootId);
- }
+ Commit newCommit;
+ if (currentHead <= branchRootId) {
+ // no commits to trunk since branch was created
+ StringBuilder diff = new StringBuilder();
+ for (long rev = branchRootId + 1; rev <= commit.getRevisionId(); rev++) {
+ try {
+ Commit c = new FetchCommitAction(nodeStore, rev).execute();
+ if (branchId.equals(c.getBranchId())) {
+ diff.append(normalizeDiff(c.getPath(), c.getDiff()));
+ }
+ } catch (Exception e) {
+ // commit does not exist
+ }
+ }
+ newCommit = CommitBuilder.build("", diff.toString(),
+ MongoUtil.fromMongoRepresentation(currentHead), message);
- String diff = new DiffBuilder(MongoUtil.wrap(currentHeadNode),
- MongoUtil.wrap(ourRoot), "/", -1,
- new SimpleMongoNodeStore(), "").build();
+ } else {
+ Node ourRoot = getNode("/", rootNodeId, branchId);
- if (diff.isEmpty()) {
- LOG.debug("Merge of empty branch {} with differing content hashes encountered, " +
- "ignore and keep current head {}", branchRevisionId, currentHead);
- return MongoUtil.fromMongoRepresentation(currentHead);
- }
+ // Merge changes, if any, from trunk to branch.
+ Node currentHeadNode = getNode("/", currentHead);
+ if (currentHead != branchRootId) {
+ ourRoot = mergeNodes(ourRoot, currentHeadNode, branchRootId);
+ }
- Commit newCommit = CommitBuilder.build("", diff,
- MongoUtil.fromMongoRepresentation(currentHead), message);
+ String diff = new DiffBuilder(MongoUtil.wrap(currentHeadNode),
+ MongoUtil.wrap(ourRoot), "/", -1,
+ new SimpleMongoNodeStore(), "").build();
+
+ if (diff.isEmpty()) {
+ LOG.debug("Merge of empty branch {} with differing content hashes encountered, " +
+ "ignore and keep current head {}", branchRevisionId, currentHead);
+ return MongoUtil.fromMongoRepresentation(currentHead);
+ }
+
+ newCommit = CommitBuilder.build("", diff,
+ MongoUtil.fromMongoRepresentation(currentHead), message);
+ }
Command<Long> command = new CommitCommandNew(nodeStore, newCommit);
long revision = command.execute();
return MongoUtil.fromMongoRepresentation(revision);
}
+ /**
+ * Normalizes a JSOP diff by appending the path to all pathStrings of the
+ * operations.
+ *
+ * @param path the root path of the diff.
+ * @param diff the JSOP diff.
+ * @return the JSOP diff based on an empty root path.
+ */
+ private String normalizeDiff(String path, String diff) throws Exception {
+ NormalizingJsopHandler handler = new NormalizingJsopHandler();
+ new JsopParser(path, diff, handler).parse();
+ return handler.getDiff();
+ }
+
private NodeImpl mergeNodes(Node ourRoot, Node theirRoot,
Long commonAncestorRevisionId) throws Exception {
@@ -97,9 +133,7 @@ public class MergeCommand extends BaseCo
Node theirRootCopy = copy(theirRoot);
// Recursively merge 'our' changes with 'their' changes...
- NodeImpl mergedNode = mergeNode(baseRoot, ourRoot, theirRootCopy, "/");
-
- return mergedNode;
+ return mergeNode(baseRoot, ourRoot, theirRootCopy, "/");
}
private NodeImpl mergeNode(Node baseNode, Node ourNode, Node theirNode,
@@ -197,4 +231,60 @@ public class MergeCommand extends BaseCo
}
return copy;
}
+
+ private static class NormalizingJsopHandler extends DefaultJsopHandler {
+
+ private final StringBuilder builder = new StringBuilder();
+
+ @Override
+ public void nodeAdded(String parentPath, String name) {
+ builder.append("+");
+ builder.append(JsopBuilder.encode(concatPath(parentPath, name)));
+ builder.append(":{}");
+ }
+
+ @Override
+ public void nodeCopied(String rootPath,
+ String oldPath,
+ String newPath) {
+ builder.append("*");
+ builder.append(JsopBuilder.encode(concatPath(rootPath, oldPath)));
+ builder.append(":");
+ builder.append(JsopBuilder.encode(concatPath(rootPath, newPath)));
+ }
+
+ @Override
+ public void nodeMoved(String rootPath, String oldPath, String newPath) {
+ builder.append(">");
+ builder.append(JsopBuilder.encode(oldPath));
+ builder.append(":");
+ builder.append(JsopBuilder.encode(newPath));
+ }
+
+ @Override
+ public void nodeRemoved(String parentPath, String name) {
+ builder.append("-");
+ builder.append(JsopBuilder.encode(concatPath(parentPath, name)));
+ }
+
+ @Override
+ public void propertySet(String path, String key, Object value, String rawValue) {
+ builder.append("^");
+ builder.append(JsopBuilder.encode(concatPath(path, key)));
+ builder.append(":");
+ builder.append(rawValue);
+ }
+
+ private String concatPath(String parent, String child) {
+ if (parent.length() == 0) {
+ return child;
+ } else {
+ return PathUtils.concat(parent, child);
+ }
+ }
+
+ String getDiff() {
+ return builder.toString();
+ }
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/DefaultJsopHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/DefaultJsopHandler.java?rev=1433336&r1=1433335&r2=1433336&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/DefaultJsopHandler.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/DefaultJsopHandler.java Tue Jan 15 10:09:56 2013
@@ -74,8 +74,9 @@ public class DefaultJsopHandler {
* @param path The path of the node where the property was set.
* @param key The key of the property.
* @param value The value of the property.
+ * @param rawValue The raw value of the property.
*/
- public void propertySet(String path, String key, Object value) {
+ public void propertySet(String path, String key, Object value, String rawValue) {
// No-op
}
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/JsopParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/JsopParser.java?rev=1433336&r1=1433335&r2=1433336&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/JsopParser.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/json/JsopParser.java Tue Jan 15 10:09:56 2013
@@ -123,7 +123,7 @@ public class JsopParser {
else { // Property.
String valueAsString = tokenizer.readRawValue().trim();
Object value = JsonUtil.toJsonValue(valueAsString);
- defaultHandler.propertySet(path, propName, value);
+ defaultHandler.propertySet(path, propName, value, valueAsString);
}
} while (tokenizer.matches(','));
@@ -185,7 +185,7 @@ public class JsopParser {
}
String parentPath = PathUtils.getParentPath(targetPath);
String propName = PathUtils.getName(targetPath);
- defaultHandler.propertySet(parentPath, propName, JsonUtil.toJsonValue(value));
+ defaultHandler.propertySet(parentPath, propName, JsonUtil.toJsonValue(value), value);
}
private void parseOpRemoved() throws Exception {
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/CommitBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/CommitBuilder.java?rev=1433336&r1=1433335&r2=1433336&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/CommitBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/CommitBuilder.java Tue Jan 15 10:09:56 2013
@@ -73,7 +73,7 @@ public class CommitBuilder {
}
/**
- * The {@link DefaultJaopHandler} for the {@code JSOP} diff.
+ * The {@link DefaultJsopHandler} for the {@code JSOP} diff.
*/
private static class CommitHandler extends DefaultJsopHandler {
private final MongoCommit commit;
@@ -103,7 +103,7 @@ public class CommitBuilder {
}
@Override
- public void propertySet(String path, String key, Object value) {
+ public void propertySet(String path, String key, Object value, String rawValue) {
commit.addInstruction(new SetPropertyInstructionImpl(path,
MongoUtil.toMongoPropertyKey(key), value));
}
Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/json/JsopParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/json/JsopParserTest.java?rev=1433336&r1=1433335&r2=1433336&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/json/JsopParserTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/json/JsopParserTest.java Tue Jan 15 10:09:56 2013
@@ -277,7 +277,7 @@ public class JsopParserTest {
}
@Override
- public void propertySet(String path, String key, Object value) {
+ public void propertySet(String path, String key, Object value, String rawValue) {
this.propertiesSet.add(new Property(path, key, value));
}