jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1407119 [4/9] - in /jackrabbit/oak/trunk: ./ oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ oak-it/mk/src/main/java/org/apache/jackrabbit/mk/test/ oak-mk-perf/ oak-mk-perf/src/main/java/org/apache/jackrabbit/mk/tasks/ oak-...
Date Thu, 08 Nov 2012 15:18:02 GMT
Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/blob/MongoGridFsBlobStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/blob/MongoGridFsBlobStore.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/api/command/AbstractCommand.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/api/command/AbstractCommand.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/api/command/AbstractCommand.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java Thu Nov  8 15:17:50 2012
@@ -14,16 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.api.command;
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import org.apache.jackrabbit.mongomk.api.command.Command;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
 
 /**
- * Base implementation of {@link Command}.
+ * Base {@code Command} implementation.
  *
  * @param <T> The result type of the {@code Command}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
  */
-public abstract class AbstractCommand<T> implements Command<T> {
+public abstract class BaseCommand<T> implements Command<T> {
+
+    protected MongoNodeStore nodeStore;
+
+    /**
+     * Constructs a base command.
+     */
+    public BaseCommand() {
+    }
+
+    /**
+     * Constructs a base command with a mongo connection.
+     *
+     * @param nodeStore Node store.
+     */
+    public BaseCommand(MongoNodeStore nodeStore) {
+        this.nodeStore = nodeStore;
+    }
 
     @Override
     public int getNumOfRetries() {

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/BaseCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java Thu Nov  8 15:17:50 2012
@@ -14,28 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command;
 
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction;
 import org.apache.jackrabbit.mongomk.api.model.Commit;
-import org.apache.jackrabbit.mongomk.api.model.Instruction;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
-import org.apache.jackrabbit.mongomk.model.CommitCommandInstructionVisitor;
-import org.apache.jackrabbit.mongomk.model.CommitMongo;
-import org.apache.jackrabbit.mongomk.model.HeadMongo;
-import org.apache.jackrabbit.mongomk.model.NodeMongo;
-import org.apache.jackrabbit.mongomk.query.FetchNodesForRevisionQuery;
-import org.apache.jackrabbit.mongomk.query.ReadAndIncHeadRevisionQuery;
-import org.apache.jackrabbit.mongomk.query.SaveAndSetHeadRevisionQuery;
-import org.apache.jackrabbit.mongomk.query.SaveCommitQuery;
-import org.apache.jackrabbit.mongomk.query.SaveNodesQuery;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchNodesAction;
+import org.apache.jackrabbit.mongomk.impl.action.ReadAndIncHeadRevisionAction;
+import org.apache.jackrabbit.mongomk.impl.action.SaveAndSetHeadRevisionAction;
+import org.apache.jackrabbit.mongomk.impl.action.SaveCommitAction;
+import org.apache.jackrabbit.mongomk.impl.action.SaveNodesAction;
+import org.apache.jackrabbit.mongomk.impl.command.exception.ConflictingCommitException;
+import org.apache.jackrabbit.mongomk.impl.exception.NotFoundException;
+import org.apache.jackrabbit.mongomk.impl.instruction.CommitCommandInstructionVisitor;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.MongoNode;
+import org.apache.jackrabbit.mongomk.impl.model.MongoSync;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,33 +47,30 @@ import com.mongodb.QueryBuilder;
 import com.mongodb.WriteResult;
 
 /**
- * A {@code Command} for committing into {@code MongoDB}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * {@code Command} for {@code MongoMicroKernel#commit(String, String, String, String)}
  */
-public class CommitCommandMongo extends AbstractCommand<Long> {
+public class CommitCommand extends BaseCommand<Long> {
 
-    private static final Logger logger = LoggerFactory.getLogger(CommitCommandMongo.class);
+    private static final Logger logger = LoggerFactory.getLogger(CommitCommand.class);
 
-    private final Commit commit;
-    private final MongoConnection mongoConnection;
+    private final MongoCommit commit;
 
     private Set<String> affectedPaths;
-    private CommitMongo commitMongo;
-    private List<NodeMongo> existingNodes;
-    private HeadMongo headMongo;
-    private Set<NodeMongo> nodeMongos;
+    private List<MongoNode> existingNodes;
+    private MongoSync syncMongo;
+    private Set<MongoNode> nodeMongos;
     private Long revisionId;
+    private String branchId;
 
     /**
      * Constructs a new {@code CommitCommandMongo}.
      *
-     * @param mongoConnection {@link MongoConnection}
+     * @param nodeStore Node store.
      * @param commit {@link Commit}
      */
-    public CommitCommandMongo(MongoConnection mongoConnection, Commit commit) {
-        this.mongoConnection = mongoConnection;
-        this.commit = commit;
+    public CommitCommand(MongoNodeStore nodeStore, Commit commit) {
+        super(nodeStore);
+        this.commit = (MongoCommit)commit;
     }
 
     @Override
@@ -81,8 +79,9 @@ public class CommitCommandMongo extends 
 
         readAndIncHeadRevision();
         createRevision();
+        readBranchIdFromBaseCommit();
         createMongoNodes();
-        createMongoCommit();
+        prepareCommit();
         readExistingNodes();
         mergeNodes();
         prepareMongoNodes();
@@ -94,7 +93,6 @@ public class CommitCommandMongo extends 
 
         if (!success) {
             markAsFailed();
-
             throw new ConflictingCommitException();
         }
 
@@ -105,88 +103,97 @@ public class CommitCommandMongo extends 
 
     @Override
     public int getNumOfRetries() {
-        return 10;
+        return 20;
     }
 
     @Override
     public boolean needsRetry(Exception e) {
-        return e instanceof ConflictingCommitException;
+        // In createMongoNodes step, sometimes add operations could end up with
+        // not found exceptions in high concurrency situations.
+        return e instanceof ConflictingCommitException || e instanceof NotFoundException;
     }
 
     /**
+     * FIXME - Currently this assumes a conflict if there's an update but it
+     * should really check the affected paths before assuming a conflict. When
+     * this is fixed, lower the number of retries.
+     *
      * This is protected for testing purposed only.
      *
-     * @return N/A
-     * @throws Exception
+     * @return True if the operation was successful.
+     * @throws Exception If an exception happens.
      */
     protected boolean saveAndSetHeadRevision() throws Exception {
-        boolean success = true;
-
-        HeadMongo headMongo = new SaveAndSetHeadRevisionQuery(mongoConnection,
-                this.headMongo.getHeadRevisionId(), revisionId).execute();
-        if (headMongo == null) {
-            // TODO: Check for conflicts!
+        MongoSync syncMongo = new SaveAndSetHeadRevisionAction(nodeStore,
+                this.syncMongo.getHeadRevisionId(), revisionId).execute();
+        if (syncMongo == null) {
             logger.warn(String.format("Encounterd a conflicting update, thus can't commit"
                     + " revision %s and will be retried with new revision", revisionId));
-
-            success = false;
+            return false;
         }
-
-        return success;
+        return true;
     }
 
     private void addRevisionId() {
         commit.setRevisionId(revisionId);
     }
 
-    private void createMongoCommit() throws Exception {
-        commitMongo = CommitMongo.fromCommit(commit);
-        commitMongo.setRevisionId(revisionId);
-        commitMongo.setAffectedPaths(new LinkedList<String>(affectedPaths));
-        commitMongo.setBaseRevId(headMongo.getHeadRevisionId());
+    private void prepareCommit() throws Exception {
+        commit.setAffectedPaths(new LinkedList<String>(affectedPaths));
+        commit.setBaseRevisionId(syncMongo.getHeadRevisionId());
+        commit.setRevisionId(revisionId);
+        if (commit.getBranchId() == null && branchId != null) {
+            commit.setBranchId(branchId);
+        }
+        commit.removeField("_id"); // In case this is a retry.
     }
 
     private void createMongoNodes() throws Exception {
-        CommitCommandInstructionVisitor visitor = new CommitCommandInstructionVisitor(mongoConnection,
-                headMongo.getHeadRevisionId());
+        CommitCommandInstructionVisitor visitor = new CommitCommandInstructionVisitor(
+                nodeStore, syncMongo.getHeadRevisionId());
+        visitor.setBranchId(branchId);
+
         for (Instruction instruction : commit.getInstructions()) {
             instruction.accept(visitor);
         }
 
-        Map<String, NodeMongo> pathNodeMap = visitor.getPathNodeMap();
+        Map<String, MongoNode> pathNodeMap = visitor.getPathNodeMap();
 
-        affectedPaths = pathNodeMap.keySet(); // TODO Original copies and moved nodes must be included!
-        nodeMongos = new HashSet<NodeMongo>(pathNodeMap.values());
-        for (NodeMongo nodeMongo : nodeMongos) {
+        affectedPaths = pathNodeMap.keySet();
+        nodeMongos = new HashSet<MongoNode>(pathNodeMap.values());
+        for (MongoNode nodeMongo : nodeMongos) {
             nodeMongo.setRevisionId(revisionId);
+            if (branchId != null) {
+                nodeMongo.setBranchId(branchId);
+            }
         }
     }
 
     private void createRevision() {
-        revisionId = headMongo.getNextRevisionId() - 1;
+        revisionId = syncMongo.getNextRevisionId() - 1;
     }
 
     private void markAsFailed() throws Exception {
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject query = QueryBuilder.start("_id").is(commitMongo.getObjectId("_id")).get();
-        DBObject update = new BasicDBObject("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
+        DBCollection commitCollection = nodeStore.getCommitCollection();
+        DBObject query = QueryBuilder.start("_id").is(commit.getObjectId("_id")).get();
+        DBObject update = new BasicDBObject("$set", new BasicDBObject(MongoCommit.KEY_FAILED, Boolean.TRUE));
         WriteResult writeResult = commitCollection.update(query, update);
         if (writeResult.getError() != null) {
-            throw new Exception(String.format("Update wasn't successful: %s", writeResult)); // TODO now what?
+            // FIXME This is potentially a bug that we need to handle.
+            throw new Exception(String.format("Update wasn't successful: %s", writeResult));
         }
     }
 
     private void mergeNodes() {
-        for (NodeMongo existingNode : existingNodes) {
-            for (NodeMongo committingNode : nodeMongos) {
+        for (MongoNode existingNode : existingNodes) {
+            for (MongoNode committingNode : nodeMongos) {
                 if (existingNode.getPath().equals(committingNode.getPath())) {
                     logger.debug(String.format("Found existing node to merge: %s", existingNode.getPath()));
                     logger.debug(String.format("Existing node: %s", existingNode));
                     logger.debug(String.format("Committing node: %s", committingNode));
 
                     Map<String, Object> existingProperties = existingNode.getProperties();
-
-                    if (existingProperties != null) {
+                    if (!existingProperties.isEmpty()) {
                         committingNode.setProperties(existingProperties);
 
                         logger.debug(String.format("Merged properties for %s: %s", existingNode.getPath(),
@@ -194,7 +201,6 @@ public class CommitCommandMongo extends 
                     }
 
                     List<String> existingChildren = existingNode.getChildren();
-
                     if (existingChildren != null) {
                         committingNode.setChildren(existingChildren);
 
@@ -212,7 +218,7 @@ public class CommitCommandMongo extends 
     }
 
     private void prepareMongoNodes() {
-        for (NodeMongo committingNode : nodeMongos) {
+        for (MongoNode committingNode : nodeMongos) {
             logger.debug(String.format("Preparing children (added and removed) of %s", committingNode.getPath()));
             logger.debug(String.format("Committing node: %s", committingNode));
 
@@ -239,9 +245,6 @@ public class CommitCommandMongo extends 
             }
 
             Map<String, Object> properties = committingNode.getProperties();
-            if (properties == null) {
-                properties = new HashMap<String, Object>();
-            }
 
             Map<String, Object> addedProperties = committingNode.getAddedProps();
             if (addedProperties != null) {
@@ -265,25 +268,45 @@ public class CommitCommandMongo extends 
         }
     }
 
+    private void readBranchIdFromBaseCommit() throws Exception {
+        String commitBranchId = commit.getBranchId();
+        if (commitBranchId != null) {
+            // This is a newly created branch, so no need to check the base
+            // commit's branch id.
+            branchId = commitBranchId;
+            return;
+        }
+
+        Long baseRevisionId = commit.getBaseRevisionId();
+        if (baseRevisionId == null) {
+            return;
+        }
+
+        MongoCommit baseCommit = new FetchCommitAction(nodeStore, baseRevisionId).execute();
+        branchId = baseCommit.getBranchId();
+    }
+
     private void readAndIncHeadRevision() throws Exception {
-        headMongo = new ReadAndIncHeadRevisionQuery(mongoConnection).execute();
+        syncMongo = new ReadAndIncHeadRevisionAction(nodeStore).execute();
     }
 
     private void readExistingNodes() {
         Set<String> paths = new HashSet<String>();
-        for (NodeMongo nodeMongo : nodeMongos) {
+        for (MongoNode nodeMongo : nodeMongos) {
             paths.add(nodeMongo.getPath());
         }
 
-        existingNodes = new FetchNodesForRevisionQuery(mongoConnection, paths,
-                headMongo.getHeadRevisionId()).execute();
+        FetchNodesAction action = new FetchNodesAction(nodeStore, paths,
+                syncMongo.getHeadRevisionId());
+        action.setBranchId(branchId);
+        existingNodes = action.execute();
     }
 
     private void saveCommit() throws Exception {
-        new SaveCommitQuery(mongoConnection, commitMongo).execute();
+        new SaveCommitAction(nodeStore, commit).execute();
     }
 
     private void saveNodes() throws Exception {
-        new SaveNodesQuery(mongoConnection, nodeMongos).execute();
+        new SaveNodesAction(nodeStore, nodeMongos).execute();
     }
 }

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommandExecutorImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommandExecutorImpl.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommandExecutorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java Thu Nov  8 15:17:50 2012
@@ -21,10 +21,8 @@ import org.apache.jackrabbit.mongomk.api
 
 /**
  * Implementation of the {@link CommandExecutor} interface.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
  */
-public class CommandExecutorImpl implements CommandExecutor {
+public class DefaultCommandExecutor implements CommandExecutor {
 
     @Override
     public <T> T execute(Command<T> command) throws Exception {
@@ -42,7 +40,7 @@ public class CommandExecutorImpl impleme
             } catch (Exception e) {
                 needsRetry = command.needsRetry(e);
 
-                if (!needsRetry) {
+                if (!needsRetry || currentRetry >= numOfRetries) {
                     throw e;
                 }
             }

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DefaultCommandExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,89 @@
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+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.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.tree.SimpleMongoNodeStore;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+
+/**
+ * A {@code Command} for {@code MongoMicroKernel#diff(String, String, String, int)}
+ */
+public class DiffCommand extends BaseCommand<String> {
+
+    private final String fromRevision;
+    private final String toRevision;
+    private final int depth;
+
+    private String path;
+
+    /**
+     * Constructs a {@code DiffCommandCommandMongo}
+     *
+     * @param nodeStore Node store.
+     * @param fromRevision From revision id.
+     * @param toRevision To revision id.
+     * @param path Path.
+     * @param depth Depth.
+     */
+    public DiffCommand(MongoNodeStore nodeStore, String fromRevision,
+            String toRevision, String path, int depth) {
+        super(nodeStore);
+        this.fromRevision = fromRevision;
+        this.toRevision = toRevision;
+        this.path = path;
+        this.depth = depth;
+    }
+
+    @Override
+    public String execute() throws Exception {
+        path = MongoUtil.adjustPath(path);
+        checkDepth();
+
+        long fromRevisionId, toRevisionId;
+        if (fromRevision == null || toRevision == null) {
+            FetchHeadRevisionIdAction query = new FetchHeadRevisionIdAction(nodeStore);
+            query.includeBranchCommits(true);
+            long head = query.execute();
+            fromRevisionId = fromRevision == null? head : MongoUtil.toMongoRepresentation(fromRevision);
+            toRevisionId = toRevision == null ? head : MongoUtil.toMongoRepresentation(toRevision);;
+        } else {
+            fromRevisionId = MongoUtil.toMongoRepresentation(fromRevision);
+            toRevisionId = MongoUtil.toMongoRepresentation(toRevision);;
+        }
+
+        if (fromRevisionId == toRevisionId) {
+            return "";
+        }
+
+        if ("/".equals(path)) {
+            MongoCommit toCommit = new FetchCommitAction(nodeStore, toRevisionId).execute();
+            if (toCommit.getBaseRevisionId() == fromRevisionId) {
+                // Specified range spans a single commit:
+                // use diff stored in commit instead of building it dynamically
+                return toCommit.getDiff();
+            }
+        }
+
+        NodeState beforeState = MongoUtil.wrap(getNode(path, fromRevisionId));
+        NodeState afterState = MongoUtil.wrap(getNode(path, toRevisionId));
+
+        return new DiffBuilder(beforeState, afterState, path, depth,
+                new SimpleMongoNodeStore(), path).build();
+    }
+
+    private void checkDepth() {
+        if (depth < -1) {
+            throw new IllegalArgumentException("depth");
+        }
+    }
+
+    private Node getNode(String path, long revisionId) throws Exception {
+        GetNodesCommand command = new GetNodesCommand(nodeStore, path, revisionId);
+        return command.execute();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/DiffCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetHeadRevisionCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetHeadRevisionCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetHeadRevisionCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java Thu Nov  8 15:17:50 2012
@@ -14,32 +14,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command;
 
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
-import org.apache.jackrabbit.mongomk.query.FetchHeadRevisionQuery;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction;
 
 /**
- * A {@code Command} for getting the head revision from {@code MongoDB}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * {@code Command} for {@code MongoMicroKernel#getHeadRevision()}
  */
-public class GetHeadRevisionCommandMongo extends AbstractCommand<Long> {
-
-    private final MongoConnection mongoConnection;
+public class GetHeadRevisionCommand extends BaseCommand<Long> {
 
     /**
      * Constructs a new {@code GetHeadRevisionCommandMongo}.
      *
-     * @param mongoConnection The {@link MongoConnection}.
+     * @param nodeStore Node store.
      */
-    public GetHeadRevisionCommandMongo(MongoConnection mongoConnection) {
-        this.mongoConnection = mongoConnection;
+    public GetHeadRevisionCommand(MongoNodeStore nodeStore) {
+        super(nodeStore);
     }
 
     @Override
     public Long execute() throws Exception {
-        return new FetchHeadRevisionQuery(mongoConnection).execute();
+        return new FetchHeadRevisionIdAction(nodeStore).execute();
     }
 }
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetHeadRevisionCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,121 @@
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import java.util.List;
+
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitsAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.tree.SimpleMongoNodeStore;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+
+/**
+ * A {@code Command} for {@code MongoMicroKernel#getJournal(String, String, String)}
+ */
+public class GetJournalCommand extends BaseCommand<String> {
+
+    private final String fromRevisionId;
+    private final String toRevisionId;
+
+    private String path;
+
+    /**
+     * Constructs a {@code GetJournalCommandMongo}
+     *
+     * @param nodeStore Node store.
+     * @param fromRevisionId From revision.
+     * @param toRevisionId To revision.
+     * @param path Path.
+     */
+    public GetJournalCommand(MongoNodeStore nodeStore, String fromRevisionId,
+            String toRevisionId, String path) {
+        super(nodeStore);
+        this.fromRevisionId = fromRevisionId;
+        this.toRevisionId = toRevisionId;
+        this.path = path;
+    }
+
+    @Override
+    public String execute() throws Exception {
+        path = MongoUtil.adjustPath(path);
+
+        long fromRevision = MongoUtil.toMongoRepresentation(fromRevisionId);
+        long toRevision;
+        if (toRevisionId == null) {
+            FetchHeadRevisionIdAction query = new FetchHeadRevisionIdAction(nodeStore);
+            query.includeBranchCommits(true);
+            toRevision = query.execute();
+        } else {
+            toRevision = MongoUtil.toMongoRepresentation(toRevisionId);
+        }
+
+        List<MongoCommit> commits = getCommits(fromRevision, toRevision);
+
+        MongoCommit toCommit = extractCommit(commits, toRevision);
+        if (toCommit.getBranchId() != null) {
+            throw new MicroKernelException("Branch revisions are not supported: " + toRevisionId);
+        }
+
+        MongoCommit fromCommit;
+        if (toRevision == fromRevision) {
+            fromCommit = toCommit;
+        } else {
+            fromCommit = extractCommit(commits, fromRevision);
+            if (fromCommit == null || (fromCommit.getTimestamp() > toCommit.getTimestamp())) {
+                // negative range, return empty journal
+                return "[]";
+            }
+        }
+        if (fromCommit.getBranchId() != null) {
+            throw new MicroKernelException("Branch revisions are not supported: " + fromRevisionId);
+        }
+
+        JsopBuilder commitBuff = new JsopBuilder().array();
+        // Iterate over commits in chronological order, starting with oldest commit
+        for (int i = commits.size() - 1; i >= 0; i--) {
+            MongoCommit commit = commits.get(i);
+
+            String diff = commit.getDiff();
+            if (MongoUtil.isFiltered(path)) {
+                try {
+                    diff = new DiffBuilder(
+                            MongoUtil.wrap(getNode("/", commit.getBaseRevisionId())),
+                            MongoUtil.wrap(getNode("/", commit.getRevisionId())),
+                            "/", -1, new SimpleMongoNodeStore(), path).build();
+                    if (diff.isEmpty()) {
+                        continue;
+                    }
+                } catch (Exception e) {
+                    throw new MicroKernelException(e);
+                }
+            }
+            commitBuff.object()
+            .key("id").value(MongoUtil.fromMongoRepresentation(commit.getRevisionId()))
+            .key("ts").value(commit.getTimestamp())
+            .key("msg").value(commit.getMessage())
+            .key("changes").value(diff).endObject();
+        }
+        return commitBuff.endArray().toString();
+    }
+
+    private MongoCommit extractCommit(List<MongoCommit> commits, long revisionId) {
+        for (MongoCommit commit : commits) {
+            if (commit.getRevisionId() == revisionId) {
+                return commit;
+            }
+        }
+        return null;
+    }
+
+    private List<MongoCommit> getCommits(long fromRevisionId, long toRevisionId) {
+        return new FetchCommitsAction(nodeStore, fromRevisionId, toRevisionId).execute();
+    }
+
+    private Node getNode(String path, long revisionId) throws Exception {
+        return new GetNodesCommand(nodeStore, path, revisionId).execute();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetJournalCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetNodesCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetNodesCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetNodesCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java Thu Nov  8 15:17:50 2012
@@ -14,60 +14,75 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command;
 
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
-import java.util.Set;
 
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
 import org.apache.jackrabbit.mongomk.api.model.Node;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitsAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchNodesAction;
+import org.apache.jackrabbit.mongomk.impl.command.exception.InconsistentNodeHierarchyException;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
 import org.apache.jackrabbit.mongomk.impl.model.NodeImpl;
-import org.apache.jackrabbit.mongomk.model.CommitMongo;
-import org.apache.jackrabbit.mongomk.model.NodeMongo;
-import org.apache.jackrabbit.mongomk.query.FetchNodesByPathAndDepthQuery;
-import org.apache.jackrabbit.mongomk.query.FetchValidCommitsQuery;
+import org.apache.jackrabbit.mongomk.impl.model.MongoNode;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A {@code Command} for getting nodes from {@code MongoDB}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * {@code Command} for {@code MongoMicroKernel#getNodes(String, String, int, long, int, String)}
  */
-public class GetNodesCommandMongo extends AbstractCommand<Node> {
+public class GetNodesCommand extends BaseCommand<Node> {
 
-    private static final Logger LOG = LoggerFactory.getLogger(GetNodesCommandMongo.class);
+    private static final Logger LOG = LoggerFactory.getLogger(GetNodesCommand.class);
 
-    private final MongoConnection mongoConnection;
     private final String path;
-    private final int depth;
 
+    private String branchId;
+    private int depth = FetchNodesAction.LIMITLESS_DEPTH;
     private Long revisionId;
-    private List<CommitMongo> lastCommits;
-    private List<NodeMongo> nodeMongos;
+    private List<MongoCommit> lastCommits;
+    private List<MongoNode> nodeMongos;
 
-    private Map<String, NodeMongo> pathAndNodeMap;
+    private Map<String, MongoNode> pathAndNodeMap;
     private Map<String, Long> problematicNodes;
-    private Node rootOfPath;
+    private Node rootNode;
 
     /**
      * Constructs a new {@code GetNodesCommandMongo}.
      *
-     * @param mongoConnection The {@link MongoConnection}.
+     * @param nodeStore Node store.
      * @param path The root path of the nodes to get.
-     * @param revisionId The revision id or null.
-     * @param depth The depth.
+     * @param revisionId The revision id or null for head revision.
      */
-    public GetNodesCommandMongo(MongoConnection mongoConnection, String path,
-            Long revisionId, int depth) {
-        this.mongoConnection = mongoConnection;
+    public GetNodesCommand(MongoNodeStore nodeStore, String path,
+            Long revisionId) {
+        super(nodeStore);
         this.path = path;
         this.revisionId = revisionId;
+    }
+
+    /**
+     * Sets the branchId for the command.
+     *
+     * @param branchId Branch id.
+     */
+    public void setBranchId(String branchId) {
+        this.branchId = branchId;
+    }
+
+    /**
+     * Sets the depth for the command.
+     *
+     * @param depth The depth for the command or -1 for limitless depth.
+     */
+    public void setDepth(int depth) {
         this.depth = depth;
     }
 
@@ -76,18 +91,18 @@ public class GetNodesCommandMongo extend
         ensureRevisionId();
         readLastCommits();
         deriveProblematicNodes();
+        readRootNode();
+        return rootNode;
+    }
 
+    private void readRootNode() throws InconsistentNodeHierarchyException {
         readNodesByPath();
         createPathAndNodeMap();
         boolean verified = verifyProblematicNodes() && verifyNodeHierarchy();
-
         if (!verified) {
             throw new InconsistentNodeHierarchyException();
         }
-
-        this.buildNodeStructure();
-
-        return rootOfPath;
+        buildNodeStructure();
     }
 
     @Override
@@ -101,20 +116,23 @@ public class GetNodesCommandMongo extend
     }
 
     private void buildNodeStructure() {
-        NodeMongo nodeMongoRootOfPath = pathAndNodeMap.get(path);
-        rootOfPath = this.buildNodeStructure(nodeMongoRootOfPath);
+        MongoNode nodeMongoRootOfPath = pathAndNodeMap.get(path);
+        rootNode = buildNodeStructure(nodeMongoRootOfPath);
     }
 
-    private NodeImpl buildNodeStructure(NodeMongo nodeMongo) {
-        NodeImpl node = NodeMongo.toNode(nodeMongo);
-        Set<Node> children = node.getChildren();
-        if (children != null) {
-            for (Node child : children) {
-                NodeMongo nodeMongoChild = pathAndNodeMap.get(child.getPath());
-                if (nodeMongoChild != null) {
-                    NodeImpl nodeChild = this.buildNodeStructure(nodeMongoChild);
-                    node.addChild(nodeChild);
-                }
+    private NodeImpl buildNodeStructure(MongoNode nodeMongo) {
+        if (nodeMongo == null) {
+            return null;
+        }
+
+        NodeImpl node = MongoNode.toNode(nodeMongo);
+
+        for (Iterator<Node> it = node.getChildNodeEntries(0, -1); it.hasNext(); ) {
+            Node child = it.next();
+            MongoNode nodeMongoChild = pathAndNodeMap.get(child.getPath());
+            if (nodeMongoChild != null) {
+                NodeImpl nodeChild = buildNodeStructure(nodeMongoChild);
+                node.addChildNodeEntry(nodeChild);
             }
         }
 
@@ -122,8 +140,8 @@ public class GetNodesCommandMongo extend
     }
 
     private void createPathAndNodeMap() {
-        pathAndNodeMap = new HashMap<String, NodeMongo>();
-        for (NodeMongo nodeMongo : nodeMongos) {
+        pathAndNodeMap = new HashMap<String, MongoNode>();
+        for (MongoNode nodeMongo : nodeMongos) {
             pathAndNodeMap.put(nodeMongo.getPath(), nodeMongo);
         }
     }
@@ -131,12 +149,11 @@ public class GetNodesCommandMongo extend
     private void deriveProblematicNodes() {
         problematicNodes = new HashMap<String, Long>();
 
-        for (ListIterator<CommitMongo> iterator = lastCommits.listIterator(); iterator.hasPrevious();) {
-            CommitMongo commitMongo = iterator.previous();
+        for (ListIterator<MongoCommit> iterator = lastCommits.listIterator(); iterator.hasPrevious();) {
+            MongoCommit commitMongo = iterator.previous();
             long revisionId = commitMongo.getRevisionId();
-            List<String> affectedPath = commitMongo.getAffectedPaths();
-
-            for (String path : affectedPath) {
+            List<String> affectedPaths = commitMongo.getAffectedPaths();
+            for (String path : affectedPaths) {
                 problematicNodes.put(path, revisionId);
             }
         }
@@ -144,33 +161,23 @@ public class GetNodesCommandMongo extend
 
     private void ensureRevisionId() throws Exception {
         if (revisionId == null) {
-            revisionId = new GetHeadRevisionCommandMongo(mongoConnection).execute();
+            revisionId = new GetHeadRevisionCommand(nodeStore).execute();
+        } else {
+            // Ensure that commit with revision id exists.
+            new FetchCommitAction(nodeStore, revisionId).execute();
         }
     }
 
     private void readLastCommits() throws Exception {
-        lastCommits = new FetchValidCommitsQuery(mongoConnection, revisionId).execute();
-
-        // TODO Move this into the Query which should throw the exception in case the commit doesn't exist
-        if (revisionId != null) {
-            boolean revisionExists = false;
-            for (CommitMongo commitMongo : lastCommits) {
-                if (commitMongo.getRevisionId() == revisionId) {
-                    revisionExists = true;
-
-                    break;
-                }
-            }
-
-            if (!revisionExists) {
-                throw new Exception(String.format("Revision %d could not be found", revisionId));
-            }
-        }
+        lastCommits = new FetchCommitsAction(nodeStore, revisionId).execute();
     }
 
     private void readNodesByPath() {
-        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection,
-                path, revisionId, depth);
+        FetchNodesAction query = new FetchNodesAction(nodeStore,
+                path, true, revisionId);
+        query.setBranchId(branchId);
+        // FIXME - This does not work for depth > 3449.
+        //query.setDepth(depth);
         nodeMongos = query.execute();
     }
 
@@ -190,7 +197,11 @@ public class GetNodesCommandMongo extend
     private boolean verifyNodeHierarchyRec(String path, int currentDepth) {
         boolean verified = false;
 
-        NodeMongo nodeMongo = pathAndNodeMap.get(path);
+        if (pathAndNodeMap.isEmpty()) {
+            return true;
+        }
+
+        MongoNode nodeMongo = pathAndNodeMap.get(path);
         if (nodeMongo != null) {
             verified = true;
             if ((depth == -1) || (currentDepth < depth)) {
@@ -217,7 +228,7 @@ public class GetNodesCommandMongo extend
             String path = entry.getKey();
             Long revisionId = entry.getValue();
 
-            NodeMongo nodeMongo = pathAndNodeMap.get(path);
+            MongoNode nodeMongo = pathAndNodeMap.get(path);
             if (nodeMongo != null) {
                 if (!revisionId.equals(nodeMongo.getRevisionId())) {
                     verified = false;

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetNodesCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,89 @@
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitsAction;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.tree.SimpleMongoNodeStore;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+
+/**
+ * A {@code Command} for {@code MongoMicroKernel#getRevisionHistory(long, int, String)}
+ */
+public class GetRevisionHistoryCommand extends BaseCommand<String> {
+
+    private final long since;
+
+    private int maxEntries;
+    private String path;
+
+    /**
+     * Constructs a {@code GetRevisionHistoryCommandMongo}
+     *
+     * @param nodeStore Node store.
+     * @param since Timestamp (ms) of earliest revision to be returned
+     * @param maxEntries maximum #entries to be returned; if < 0, no limit will be applied.
+     * @param path optional path filter; if {@code null} or {@code ""} the
+     * default ({@code "/"}) will be assumed, i.e. no filter will be applied
+     */
+    public GetRevisionHistoryCommand(MongoNodeStore nodeStore,
+            long since, int maxEntries, String path) {
+        super(nodeStore);
+        this.since = since;
+        this.maxEntries = maxEntries;
+        this.path = path;
+    }
+
+    @Override
+    public String execute() {
+        path = MongoUtil.adjustPath(path);
+        maxEntries = maxEntries < 0 ? Integer.MAX_VALUE : maxEntries;
+
+        FetchCommitsAction action = new FetchCommitsAction(nodeStore);
+        action.setMaxEntries(maxEntries);
+        action.includeBranchCommits(false);
+
+        List<MongoCommit> commits = action.execute();
+        List<MongoCommit> history = new ArrayList<MongoCommit>();
+        for (int i = commits.size() - 1; i >= 0; i--) {
+            MongoCommit commit = commits.get(i);
+            if (commit.getTimestamp() >= since) {
+                if (MongoUtil.isFiltered(path)) {
+                    try {
+                        String diff = new DiffBuilder(
+                                MongoUtil.wrap(getNode("/", commit.getBaseRevisionId())),
+                                MongoUtil.wrap(getNode("/", commit.getRevisionId())),
+                                "/", -1, new SimpleMongoNodeStore(), path).build();
+                        if (!diff.isEmpty()) {
+                            history.add(commit);
+                        }
+                    } catch (Exception e) {
+                        throw new MicroKernelException(e);
+                    }
+                } else {
+                    history.add(commit);
+                }
+            }
+        }
+
+        JsopBuilder buff = new JsopBuilder().array();
+        for (MongoCommit commit : history) {
+            buff.object()
+            .key("id").value(MongoUtil.fromMongoRepresentation(commit.getRevisionId()))
+            .key("ts").value(commit.getTimestamp())
+            .key("msg").value(commit.getMessage())
+            .endObject();
+        }
+        return buff.endArray().toString();
+    }
+
+    private Node getNode(String path, long revisionId) throws Exception {
+        return new GetNodesCommand(nodeStore, path, revisionId).execute();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/GetRevisionHistoryCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: 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=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,188 @@
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mongomk.api.command.Command;
+import org.apache.jackrabbit.mongomk.api.model.Commit;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchBranchBaseRevisionIdAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction;
+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.NodeImpl;
+import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeDelta;
+import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeDelta.Conflict;
+import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeState;
+import org.apache.jackrabbit.mongomk.impl.model.tree.SimpleMongoNodeStore;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@code Command} for {@code MongoMicroKernel#merge(String, String)}
+ */
+public class MergeCommand extends BaseCommand<String> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MergeCommand.class);
+
+    private final String branchRevisionId;
+    private final String message;
+
+    /**
+     * Constructs a {@code MergeCommandMongo}
+     *
+     * @param nodeStore Node store.
+     * @param branchRevisionId Branch revision id.
+     * @param message Merge message.
+     */
+    public MergeCommand(MongoNodeStore nodeStore, String branchRevisionId,
+            String message) {
+        super(nodeStore);
+        this.branchRevisionId = branchRevisionId;
+        this.message = message;
+    }
+
+    @Override
+    public String execute() throws Exception {
+        MongoCommit commit = new FetchCommitAction(nodeStore,
+                MongoUtil.toMongoRepresentation(branchRevisionId)).execute();
+        String branchId = commit.getBranchId();
+        if (branchId == null) {
+            throw new Exception("Can only merge a private branch commit");
+        }
+
+        long rootNodeId = commit.getRevisionId();
+
+        FetchHeadRevisionIdAction query2 = new FetchHeadRevisionIdAction(nodeStore);
+        query2.includeBranchCommits(false);
+        long currentHead = query2.execute();
+
+        Node ourRoot = getNode("/", rootNodeId, branchId);
+
+        FetchBranchBaseRevisionIdAction branchAction = new FetchBranchBaseRevisionIdAction(nodeStore, branchId);
+        long branchRootId = branchAction.execute();
+
+        // Merge nodes from head to branch.
+        ourRoot = mergeNodes(ourRoot, currentHead, branchRootId);
+
+        Node currentHeadNode = getNode("/", currentHead);
+
+        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);
+        }
+
+        Commit newCommit = CommitBuilder.build("", diff,
+                MongoUtil.fromMongoRepresentation(currentHead), message);
+
+        Command<Long> command = new CommitCommand(nodeStore, newCommit);
+        long revision = command.execute();
+        return MongoUtil.fromMongoRepresentation(revision);
+    }
+
+    private NodeImpl mergeNodes(Node ourRoot, Long newBaseRevisionId,
+            Long commonAncestorRevisionId) throws Exception {
+
+        Node baseRoot = getNode("/", commonAncestorRevisionId);
+        Node theirRoot = getNode("/", newBaseRevisionId);
+
+        // Recursively merge 'our' changes with 'their' changes...
+        NodeImpl mergedNode = mergeNode(baseRoot, ourRoot, theirRoot, "/");
+
+        return mergedNode;
+    }
+
+    private NodeImpl mergeNode(Node baseNode, Node ourNode, Node theirNode,
+            String path) throws Exception {
+        MongoNodeDelta theirChanges = new MongoNodeDelta(new SimpleMongoNodeStore(),
+                MongoUtil.wrap(baseNode), MongoUtil.wrap(theirNode));
+        MongoNodeDelta ourChanges = new MongoNodeDelta(new SimpleMongoNodeStore(),
+                MongoUtil.wrap(baseNode), MongoUtil.wrap(ourNode));
+
+        NodeImpl stagedNode = (NodeImpl)theirNode; //new NodeImpl(path);
+
+        // Apply our changes.
+        stagedNode.getProperties().putAll(ourChanges.getAddedProperties());
+        stagedNode.getProperties().putAll(ourChanges.getChangedProperties());
+        for (String name : ourChanges.getRemovedProperties().keySet()) {
+            stagedNode.getProperties().remove(name);
+        }
+
+        for (Map.Entry<String, NodeState> entry : ourChanges.getAddedChildNodes().entrySet()) {
+            MongoNodeState nodeState = (MongoNodeState)entry.getValue();
+            stagedNode.addChildNodeEntry(nodeState.unwrap());
+        }
+        for (Map.Entry<String, NodeState> entry : ourChanges.getChangedChildNodes().entrySet()) {
+            if (!theirChanges.getChangedChildNodes().containsKey(entry.getKey())) {
+                MongoNodeState nodeState = (MongoNodeState)entry.getValue();
+                stagedNode.addChildNodeEntry(nodeState.unwrap());
+            }
+        }
+        for (String name : ourChanges.getRemovedChildNodes().keySet()) {
+            stagedNode.removeChildNodeEntry(name);
+        }
+
+        List<Conflict> conflicts = theirChanges.listConflicts(ourChanges);
+        // resolve/report merge conflicts
+        for (Conflict conflict : conflicts) {
+            String conflictName = conflict.getName();
+            String conflictPath = PathUtils.concat(path, conflictName);
+            switch (conflict.getType()) {
+                case PROPERTY_VALUE_CONFLICT:
+                    throw new Exception(
+                            "concurrent modification of property " + conflictPath
+                                    + " with conflicting values: \""
+                                    + ourNode.getProperties().get(conflictName)
+                                    + "\", \""
+                                    + theirNode.getProperties().get(conflictName));
+
+                case NODE_CONTENT_CONFLICT: {
+                    if (ourChanges.getChangedChildNodes().containsKey(conflictName)) {
+                        // modified subtrees
+                        Node baseChild = baseNode.getChildNodeEntry(conflictName);
+                        Node ourChild = ourNode.getChildNodeEntry(conflictName);
+                        Node theirChild = theirNode.getChildNodeEntry(conflictName);
+                        // merge the dirty subtrees recursively
+                        mergeNode(baseChild, ourChild, theirChild, PathUtils.concat(path, conflictName));
+                    } else {
+                        // todo handle/merge colliding node creation
+                        throw new Exception("colliding concurrent node creation: " + conflictPath);
+                    }
+                    break;
+                }
+
+                case REMOVED_DIRTY_PROPERTY_CONFLICT:
+                    stagedNode.getProperties().remove(conflictName);
+                    break;
+
+                case REMOVED_DIRTY_NODE_CONFLICT:
+                    //stagedNode.remove(conflictName);
+                    stagedNode.removeChildNodeEntry(conflictName);
+                    break;
+            }
+
+        }
+        return stagedNode;
+    }
+
+    private Node getNode(String path, long revisionId) throws Exception {
+        return getNode(path, revisionId, null);
+    }
+
+    private Node getNode(String path, long revisionId, String branchId) throws Exception {
+        GetNodesCommand command = new GetNodesCommand(nodeStore, path, revisionId);
+        command.setBranchId(branchId);
+        return command.execute();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/MergeCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/NodeExistsCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/NodeExistsCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/NodeExistsCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java Thu Nov  8 15:17:50 2012
@@ -14,52 +14,59 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command;
 
-import java.util.Set;
-
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
 import org.apache.jackrabbit.mongomk.api.model.Node;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 
 /**
- * A {@code Command} for determine whether a node exists from {@code MongoDB}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * {@code Command} for {@code MongoMicroKernel#nodeExists(String, String)}
  */
-public class NodeExistsCommandMongo extends AbstractCommand<Boolean> {
+public class NodeExistsCommand extends BaseCommand<Boolean> {
 
-    private final MongoConnection mongoConnection;
     private final Long revisionId;
 
+    private String branchId;
     private Node parentNode;
     private String path;
 
     /**
      * Constructs a new {@code NodeExistsCommandMongo}.
      *
-     * @param mongoConnection The {@link MongoConnection}.
+     * @param nodeStore Node store.
      * @param path The root path of the nodes to get.
      * @param revisionId The revision id or null.
      */
-    public NodeExistsCommandMongo(MongoConnection mongoConnection, String path,
-            Long revisionId) {
-        this.mongoConnection = mongoConnection;
+    public NodeExistsCommand(MongoNodeStore nodeStore, String path, Long revisionId) {
+        super(nodeStore);
         this.path = path;
         this.revisionId = revisionId;
     }
 
+    /**
+     * Sets the branchId for the command.
+     *
+     * @param branchId Branch id.
+     */
+    public void setBranchId(String branchId) {
+        this.branchId = branchId;
+    }
+
     @Override
     public Boolean execute() throws Exception {
         if (PathUtils.denotesRoot(path)) {
             return true;
         }
 
-        // Check that all the paths up to the parent are valid.
+        // Check that all the paths up to the root actually exist.
+        return pathExists();
+    }
+
+    private boolean pathExists() throws Exception {
         while (!PathUtils.denotesRoot(path)) {
-            readParentNode();
-            if (!childExists()) {
+            readParentNode(revisionId, branchId);
+            if (parentNode == null || !childExists()) {
                 return false;
             }
             path = PathUtils.getParentPath(path);
@@ -68,30 +75,15 @@ public class NodeExistsCommandMongo exte
         return true;
     }
 
-    private void readParentNode() throws Exception {
+    private void readParentNode(Long revisionId, String branchId) throws Exception {
         String parentPath = PathUtils.getParentPath(path);
-        // TODO - This used to be FetchNodeByPathQuery but changed to GetNodesCommandMongo to make
-        // sure nodes are in a valid commit etc. Check if GetNodesCommandMongo is really needed.
-        GetNodesCommandMongo command = new GetNodesCommandMongo(mongoConnection, parentPath, revisionId, -1);
+        GetNodesCommand command = new GetNodesCommand(nodeStore, parentPath, revisionId);
+        command.setBranchId(branchId);
         parentNode = command.execute();
     }
 
     private boolean childExists() {
-        if (parentNode == null) {
-            return false;
-        }
-
-        Set<Node> children = parentNode.getChildren();
-        if (children == null || children.isEmpty()) {
-            return false;
-        }
-
-        for (Node child : children) {
-            if (child.getName().equals(PathUtils.getName(path))) {
-                return true;
-            }
-        }
-
-        return false;
+        String childName = PathUtils.getName(path);
+        return parentNode.getChildNodeEntry(childName) != null;
     }
-}
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/NodeExistsCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,61 @@
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+
+/**
+ * A {@code Command} for {@code MongoMicroKernel#waitForCommit(String, long)}
+ */
+public class WaitForCommitCommand extends BaseCommand<Long> {
+
+    private static final long WAIT_FOR_COMMIT_POLL_MILLIS = 1000;
+
+    private final String oldHeadRevisionId;
+    private final long timeout;
+
+    /**
+     * Constructs a {@code WaitForCommitCommandMongo}
+     *
+     * @param nodeStore Node store.
+     * @param oldHeadRevisionId Id of earlier head revision
+     * @param timeout The maximum time to wait in milliseconds
+     */
+    public WaitForCommitCommand(MongoNodeStore nodeStore, String oldHeadRevisionId,
+            long timeout) {
+        super(nodeStore);
+        this.oldHeadRevisionId = oldHeadRevisionId;
+        this.timeout = timeout;
+    }
+
+    @Override
+    public Long execute() throws Exception {
+        long startTimestamp = System.currentTimeMillis();
+        Long initialHeadRevisionId = getHeadRevision();
+
+        if (timeout <= 0) {
+            return initialHeadRevisionId;
+        }
+
+        Long oldHeadRevision = MongoUtil.toMongoRepresentation(oldHeadRevisionId);
+        if (oldHeadRevision != initialHeadRevisionId) {
+            return initialHeadRevisionId;
+        }
+
+        long waitForCommitPollMillis = Math.min(WAIT_FOR_COMMIT_POLL_MILLIS, timeout);
+        while (true) {
+            long headRevisionId = getHeadRevision();
+            long now = System.currentTimeMillis();
+            if (headRevisionId != initialHeadRevisionId || now - startTimestamp >= timeout) {
+                return headRevisionId;
+            }
+            Thread.sleep(waitForCommitPollMillis);
+        }
+    }
+
+    private long getHeadRevision() throws Exception {
+        FetchHeadRevisionIdAction query = new FetchHeadRevisionIdAction(nodeStore);
+        query.includeBranchCommits(false);
+        return query.execute();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/WaitForCommitCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetBlobLengthCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetBlobLengthCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/GetBlobLengthCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java Thu Nov  8 15:17:50 2012
@@ -14,32 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command.blob;
 
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.command.BaseCommand;
 
 import com.mongodb.BasicDBObject;
 import com.mongodb.gridfs.GridFS;
 import com.mongodb.gridfs.GridFSDBFile;
 
-public class GetBlobLengthCommandMongo extends AbstractCommand<Long> {
+/**
+ * {@code Command} for {@code MongoMicroKernel#getLength(String)}
+ */
+public class GetBlobLengthCommandGridFS extends BaseCommand<Long> {
 
-    private final MongoConnection mongoConnection;
     private final String blobId;
+    private final GridFS gridFS;
 
-    public GetBlobLengthCommandMongo(MongoConnection mongoConnection, String blobId) {
-        this.mongoConnection = mongoConnection;
+    /**
+     * Constructs the command.
+     *
+     * @param gridFS GridFS instance.
+     * @param blobId Blob id.
+     */
+    public GetBlobLengthCommandGridFS(GridFS gridFS, String blobId) {
+        super();
         this.blobId = blobId;
+        this.gridFS = gridFS;
     }
 
     @Override
     public Long execute() throws Exception {
-        GridFS gridFS = mongoConnection.getGridFS();
         GridFSDBFile gridFSDBFile = gridFS.findOne(new BasicDBObject("md5", blobId));
         if (gridFSDBFile == null) {
-            throw new Exception("Blob does not exiss");
+            throw new Exception("Blob does not exist");
         }
         return gridFSDBFile.getLength();
     }
-}
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/GetBlobLengthCommandGridFS.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ReadBlobCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ReadBlobCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ReadBlobCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java Thu Nov  8 15:17:50 2012
@@ -14,30 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command.blob;
 
 import java.io.InputStream;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.command.BaseCommand;
 
 import com.mongodb.BasicDBObject;
 import com.mongodb.gridfs.GridFS;
 import com.mongodb.gridfs.GridFSDBFile;
 
-public class ReadBlobCommandMongo extends AbstractCommand<Integer> {
+/**
+ * {@code Command} for {@code MongoMicroKernel#read(String, long, byte[], int, int)}
+ * FIXME - Reading from large blobs with small increments is slow in this implementation.
+ * See if this could be improved with some kind of cache mechanism.
+ */
+public class ReadBlobCommandGridFS extends BaseCommand<Integer> {
 
-    private final MongoConnection mongoConnection;
+    private final GridFS gridFS;
     private final String blobId;
     private final long blobOffset;
     private final byte[] buffer;
     private final int bufferOffset;
     private final int length;
 
-    public ReadBlobCommandMongo(MongoConnection mongoConnection, String blobId, long blobOffset, byte[] buffer,
-            int bufferOffset, int length) {
-        this.mongoConnection = mongoConnection;
+    /**
+     * Constructs a new {@code ReadBlobCommandMongo}.
+     *
+     * @param gridFS GridFS instance.
+     * @param blobId Blob id.
+     * @param blobOffset Blob offset.
+     * @param buffer Buffer.
+     * @param bufferOffset Buffer offset.
+     * @param length Length.
+     */
+    public ReadBlobCommandGridFS(GridFS gridFS, String blobId, long blobOffset,
+            byte[] buffer, int bufferOffset, int length) {
+        super();
+        this.gridFS = gridFS;
         this.blobId = blobId;
         this.blobOffset = blobOffset;
         this.buffer = buffer;
@@ -50,10 +65,7 @@ public class ReadBlobCommandMongo extend
         return fetchBlobFromMongo();
     }
 
-    // FIXME [Mete] This takes a long time, see MicroKernelIT#readBlob. See if
-    // it can be improved.
     private int fetchBlobFromMongo() throws Exception {
-        GridFS gridFS = mongoConnection.getGridFS();
         GridFSDBFile gridFile = gridFS.findOne(new BasicDBObject("md5", blobId));
         long fileLength = gridFile.getLength();
 
@@ -63,13 +75,13 @@ public class ReadBlobCommandMongo extend
             end = fileLength;
         }
 
-        int totalBytes = -1;
         if (start < end) {
             InputStream is = gridFile.getInputStream();
             IOUtils.skipFully(is, blobOffset);
-            totalBytes = is.read(buffer, bufferOffset, length);
+            IOUtils.readFully(is, buffer, bufferOffset, length);
             is.close();
+            return length;
         }
-        return totalBytes;
+        return -1;
     }
 }

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/ReadBlobCommandGridFS.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/WriteBlobCommandMongo.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/WriteBlobCommandMongo.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/WriteBlobCommandMongo.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java Thu Nov  8 15:17:50 2012
@@ -14,28 +14,37 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command.blob;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.jackrabbit.mongomk.api.command.AbstractCommand;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.command.BaseCommand;
 
 import com.mongodb.BasicDBObject;
 import com.mongodb.gridfs.GridFS;
 import com.mongodb.gridfs.GridFSDBFile;
 import com.mongodb.gridfs.GridFSInputFile;
 
-public class WriteBlobCommandMongo extends AbstractCommand<String> {
+/**
+ * {@code Command} for {@code MongoMicroKernel#write(InputStream)}
+ */
+public class WriteBlobCommandGridFS extends BaseCommand<String> {
 
-    private final MongoConnection mongoConnection;
+    private final GridFS gridFS;
     private final InputStream is;
 
-    public WriteBlobCommandMongo(MongoConnection mongoConnection, InputStream is) {
-        this.mongoConnection = mongoConnection;
+    /**
+     * Constructs a {@code WriteBlobCommandMongo}
+     *
+     * @param gridFS GridFS instance.
+     * @param is Input stream.
+     */
+    public WriteBlobCommandGridFS(GridFS gridFS, InputStream is) {
+        super();
+        this.gridFS = gridFS;
         this.is = is;
     }
 
@@ -45,7 +54,6 @@ public class WriteBlobCommandMongo exten
     }
 
     private String saveBlob() throws IOException {
-        GridFS gridFS = mongoConnection.getGridFS();
         BufferedInputStream bis = new BufferedInputStream(is);
         String md5 = calculateMd5(bis);
         GridFSDBFile gridFile = gridFS.findOne(new BasicDBObject("md5", md5));

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/blob/WriteBlobCommandGridFS.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/ConflictingCommitException.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/ConflictingCommitException.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/ConflictingCommitException.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/ConflictingCommitException.java Thu Nov  8 15:17:50 2012
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command.exception;
 
 public class ConflictingCommitException extends Exception {
 

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/InconsistentNodeHierarchyException.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/InconsistentNodeHierarchyException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/InconsistentNodeHierarchyException.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/InconsistentNodeHierarchyException.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/InconsistentNodeHierarchyException.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/InconsistentNodeHierarchyException.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/exception/InconsistentNodeHierarchyException.java Thu Nov  8 15:17:50 2012
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.command.exception;
 
 public class InconsistentNodeHierarchyException extends Exception {
 

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/command/ConflictingCommitException.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java Thu Nov  8 15:17:50 2012
@@ -6,7 +6,7 @@
  * (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
+ *     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,
@@ -14,25 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.command;
+package org.apache.jackrabbit.mongomk.impl.exception;
 
-public class ConflictingCommitException extends Exception {
+public class NotFoundException extends RuntimeException {
 
-    private static final long serialVersionUID = -5827664000083665577L;
+    private static final long serialVersionUID = 267748774351258035L;
 
-    public ConflictingCommitException() {
+    public NotFoundException() {
         super();
     }
 
-    public ConflictingCommitException(String message) {
+    public NotFoundException(String message) {
         super(message);
     }
 
-    public ConflictingCommitException(Throwable t) {
-        super(t);
+    public NotFoundException(String message, Throwable cause) {
+        super(message, cause);
     }
 
-    public ConflictingCommitException(String message, Throwable t) {
-        super(message, t);
+    public NotFoundException(Throwable cause) {
+        super(cause);
     }
 }

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/exception/NotFoundException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/AddNodeInstructionImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/AddNodeInstructionImpl.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/AddNodeInstructionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java Thu Nov  8 15:17:50 2012
@@ -14,48 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.impl.model;
+package org.apache.jackrabbit.mongomk.impl.instruction;
 
-import org.apache.jackrabbit.mongomk.api.model.InstructionVisitor;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.AddNodeInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.InstructionVisitor;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.AddNodeInstruction;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 
-
 /**
- * Implementation of {@link AddNodeInstruction}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * Implementation of the add node operation => "+" STRING ":" (OBJECT).
  */
-public class AddNodeInstructionImpl implements AddNodeInstruction {
-
-    private final String path;
+public class AddNodeInstructionImpl extends BaseInstruction implements AddNodeInstruction {
 
     /**
-     * Constructs a new {@code AddNodeInstructionImpl}.
+     * Constructs a new {@code AddNodeInstruction}.
      *
      * @param parentPath The parent path.
      * @param name The name.
      */
     public AddNodeInstructionImpl(String parentPath, String name) {
-        this.path = PathUtils.concat(parentPath, name);
+        super(PathUtils.concat(parentPath, name));
     }
 
     @Override
     public void accept(InstructionVisitor visitor) {
         visitor.visit(this);
     }
-
-    @Override
-    public String getPath() {
-        return path;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append("AddNodeInstructionImpl [path=");
-        builder.append(path);
-        builder.append("]");
-        return builder.toString();
-    }
-}
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/instruction/AddNodeInstructionImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL



Mime
View raw message