Return-Path: X-Original-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Delivered-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3FF3EDE6D for ; Thu, 8 Nov 2012 15:18:35 +0000 (UTC) Received: (qmail 67953 invoked by uid 500); 8 Nov 2012 15:18:34 -0000 Delivered-To: apmail-jackrabbit-oak-commits-archive@jackrabbit.apache.org Received: (qmail 67823 invoked by uid 500); 8 Nov 2012 15:18:34 -0000 Mailing-List: contact oak-commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: oak-dev@jackrabbit.apache.org Delivered-To: mailing list oak-commits@jackrabbit.apache.org Received: (qmail 67693 invoked by uid 99); 8 Nov 2012 15:18:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Nov 2012 15:18:34 +0000 X-ASF-Spam-Status: No, hits=-1999.0 required=5.0 tests=ALL_TRUSTED,FRT_ADOBE2 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Nov 2012 15:18:29 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 68E8A2388AB9; Thu, 8 Nov 2012 15:18:09 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: oak-commits@jackrabbit.apache.org From: mduerig@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121108151809.68E8A2388AB9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 The result type of the {@code Command}. - * - * @author Philipp Marx + * {@code Command} for {@code MongoMicroKernel#commit(String, String, String, String)} */ -public class CommitCommandMongo extends AbstractCommand { +public class CommitCommand extends BaseCommand { - 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 affectedPaths; - private CommitMongo commitMongo; - private List existingNodes; - private HeadMongo headMongo; - private Set nodeMongos; + private List existingNodes; + private MongoSync syncMongo; + private Set 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(affectedPaths)); - commitMongo.setBaseRevId(headMongo.getHeadRevisionId()); + private void prepareCommit() throws Exception { + commit.setAffectedPaths(new LinkedList(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 pathNodeMap = visitor.getPathNodeMap(); + Map pathNodeMap = visitor.getPathNodeMap(); - affectedPaths = pathNodeMap.keySet(); // TODO Original copies and moved nodes must be included! - nodeMongos = new HashSet(pathNodeMap.values()); - for (NodeMongo nodeMongo : nodeMongos) { + affectedPaths = pathNodeMap.keySet(); + nodeMongos = new HashSet(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 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 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 properties = committingNode.getProperties(); - if (properties == null) { - properties = new HashMap(); - } Map 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 paths = new HashSet(); - 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 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 commits, long revisionId) { + for (MongoCommit commit : commits) { + if (commit.getRevisionId() == revisionId) { + return commit; + } + } + return null; + } + + private List 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 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 { + + 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 commits = action.execute(); + List history = new ArrayList(); + 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 { + + 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 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 entry : ourChanges.getAddedChildNodes().entrySet()) { + MongoNodeState nodeState = (MongoNodeState)entry.getValue(); + stagedNode.addChildNodeEntry(nodeState.unwrap()); + } + for (Map.Entry 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 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 { +/** + * {@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 { - 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 { +/** + * {@code Command} for {@code MongoMicroKernel#write(InputStream)} + */ +public class WriteBlobCommandGridFS extends BaseCommand { - 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