Author: mreutegg
Date: Thu Dec 20 14:20:39 2012
New Revision: 1424481

URL: http://svn.apache.org/viewvc?rev=1424481&view=rev
Log:
OAK-534: Inefficient NodeState comparison with MongoMK

Added:
    
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/OneLevelDiffCommand.java
   (with props)
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
    
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java
    
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKGetRevisionHistoryTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java?rev=1424481&r1=1424480&r2=1424481&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
 Thu Dec 20 14:20:39 2012
@@ -236,9 +236,11 @@ public final class KernelNodeState exten
                     kbase.init();
                     if (hash != null && hash.equals(kbase.hash)) {
                         return; // no differences
-                    } else if (path.equals(kbase.path)) {
-                        // TODO: Parse the JSON diff returned by the kernel
-                        // kernel.diff(kbase.revision, revision, path);
+                    } else if (path.equals(kbase.path) && !path.equals("/")) {
+                        String jsonDiff = kernel.diff(kbase.getRevision(), 
revision, path, 0);
+                        if (!hasChanges(jsonDiff)) {
+                            return; // no differences
+                        }
                     }
                 }
             }
@@ -271,6 +273,9 @@ public final class KernelNodeState exten
                     that.init();
                     if (hash != null && that.hash != null) {
                         return hash.equals(that.hash);
+                    } else if (path.equals(that.path) && !path.equals("/")) {
+                        String jsonDiff = kernel.diff(that.getRevision(), 
revision, path, 0);
+                        return !hasChanges(jsonDiff);
                     }
                 }
             }
@@ -293,6 +298,10 @@ public final class KernelNodeState exten
 
     //------------------------------------------------------------< private 
>---
 
+    private boolean hasChanges(String journal) {
+        return !journal.trim().isEmpty();
+    }
+
     private Iterable<ChildNodeEntry> getChildNodeEntries(
             final long offset, final int count) {
         return new Iterable<ChildNodeEntry>() {

Modified: 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java?rev=1424481&r1=1424480&r2=1424481&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/MongoNodeStore.java
 Thu Dec 20 14:20:39 2012
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.mongomk.imp
 import org.apache.jackrabbit.mongomk.impl.command.GetRevisionHistoryCommand;
 import org.apache.jackrabbit.mongomk.impl.command.MergeCommand;
 import org.apache.jackrabbit.mongomk.impl.command.NodeExistsCommand;
+import org.apache.jackrabbit.mongomk.impl.command.OneLevelDiffCommand;
 import org.apache.jackrabbit.mongomk.impl.command.WaitForCommitCommand;
 import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
 import org.apache.jackrabbit.mongomk.impl.model.MongoNode;
@@ -91,7 +92,12 @@ public class MongoNodeStore implements N
     @Override
     public String diff(String fromRevision, String toRevision, String path, 
int depth)
             throws Exception {
-        Command<String> command = new DiffCommand(this, fromRevision, 
toRevision, path, depth);
+        Command<String> command;
+        if (depth == 0) {
+            command = new OneLevelDiffCommand(this, fromRevision, toRevision, 
path);
+        } else {
+            command = new DiffCommand(this, fromRevision, toRevision, path, 
depth);
+        }
         return commandExecutor.execute(command);
     }
 

Added: 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/OneLevelDiffCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/OneLevelDiffCommand.java?rev=1424481&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/OneLevelDiffCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/command/OneLevelDiffCommand.java
 Thu Dec 20 14:20:39 2012
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.mongomk.impl.command;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.model.tree.DiffBuilder;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction;
+import org.apache.jackrabbit.mongomk.impl.action.FetchNodesActionNew;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.MongoNode;
+import org.apache.jackrabbit.mongomk.impl.model.NodeImpl;
+import org.apache.jackrabbit.mongomk.impl.model.tree.SimpleMongoNodeStore;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * <code>OneLevelDiffCommand</code> implements a specialized {@link 
DiffCommand}
+ * with a fixed depth of 0.
+ */
+public class OneLevelDiffCommand extends BaseCommand<String> {
+
+    private final long fromRevision;
+    private final long toRevision;
+    private final String path;
+    private final int pathDepth;
+
+    public OneLevelDiffCommand(MongoNodeStore nodeStore, String fromRevision,
+                       String toRevision, String path) throws Exception {
+        super(nodeStore);
+        this.fromRevision = 
MongoUtil.toMongoRepresentation(checkNotNull(fromRevision));
+        this.toRevision = 
MongoUtil.toMongoRepresentation(checkNotNull(toRevision));
+        this.path = MongoUtil.adjustPath(path);
+        this.pathDepth = PathUtils.getDepth(this.path);
+    }
+
+    @Override
+    public String execute() throws Exception {
+        MongoCommit fromCommit = new FetchCommitAction(
+                nodeStore, fromRevision).execute();
+        MongoCommit toCommit = new FetchCommitAction(
+                nodeStore, toRevision).execute();
+        FetchNodesActionNew action = new FetchNodesActionNew(
+                nodeStore, path, 0, fromRevision);
+        action.setBranchId(fromCommit.getBranchId());
+        NodeImpl fromNode = MongoNode.toNode(action.execute().get(path));
+        action = new FetchNodesActionNew(
+                nodeStore, path, 0, toRevision);
+        action.setBranchId(toCommit.getBranchId());
+        NodeImpl toNode = MongoNode.toNode(action.execute().get(path));
+
+        String diff = "";
+        if (!fromNode.getRevisionId().equals(toNode.getRevisionId())) {
+            // diff of node at given path
+            DiffBuilder diffBuilder = new DiffBuilder(MongoUtil.wrap(fromNode),
+                    MongoUtil.wrap(toNode), path, 0, new 
SimpleMongoNodeStore(), path);
+            diff = diffBuilder.build();
+        }
+
+        // find out what changed below path
+        List<MongoCommit> commits = getCommits(fromCommit, toCommit);
+        Set<String> affectedPaths = new HashSet<String>();
+        for (MongoCommit mc : commits) {
+            for (String p : mc.getAffectedPaths()) {
+                if (p.startsWith(path)) {
+                    int d = PathUtils.getDepth(p);
+                    if (d > pathDepth) {
+                        affectedPaths.add(PathUtils.getAncestorPath(p, d - 
pathDepth - 1));
+                    }
+                }
+            }
+        }
+
+        JsopBuilder builder = new JsopBuilder();
+        for (String p : affectedPaths) {
+            builder.tag('^');
+            builder.key(p);
+            builder.object().endObject();
+            builder.newline();
+        }
+
+        return diff + builder.toString();
+    }
+
+    /**
+     * Retrieves the commits within the range of <code>c1</code> and
+     * <code>c2</code>. The given bounding commits are included in the list as
+     * well.
+     *
+     * @param c1 a MongoCommit
+     * @param c2 a MongoCommit
+     * @return the commits from <code>c1</code> to <code>c2</code>.
+     * @throws Exception if an error occurs.
+     */
+    private List<MongoCommit> getCommits(MongoCommit c1, MongoCommit c2)
+            throws Exception {
+        // this implementation does not use the multi commit fetch action
+        // FetchCommitsAction because that action does not leverage the
+        // commit cache in NodeStore. Retrieving each commit individually
+        // results in good cache hit ratios when the revision range is recent
+        // and not too big.
+        List<MongoCommit> commits = new ArrayList<MongoCommit>();
+        MongoCommit fromCommit = c1.getRevisionId() < c2.getRevisionId() ? c1 
: c2;
+        MongoCommit toCommit = c1.getRevisionId() < c2.getRevisionId() ? c2 : 
c1;
+        Long revision = toCommit.getBaseRevisionId();
+        commits.add(toCommit);
+        while (revision != null && revision > fromCommit.getRevisionId()) {
+            MongoCommit c = new FetchCommitAction(nodeStore, 
revision).execute();
+            commits.add(c);
+            revision = c.getBaseRevisionId();
+        }
+        commits.add(fromCommit);
+        return commits;
+    }
+}

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

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

Modified: 
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKGetRevisionHistoryTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKGetRevisionHistoryTest.java?rev=1424481&r1=1424480&r2=1424481&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKGetRevisionHistoryTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKGetRevisionHistoryTest.java
 Thu Dec 20 14:20:39 2012
@@ -72,6 +72,7 @@ public class MongoMKGetRevisionHistoryTe
         JSONArray array = parseJSONArray(mk.getRevisionHistory(since1, -1, 
"/"));
         assertEquals(count1, array.size());
 
+        Thread.sleep(100);
 
         long since2 = System.currentTimeMillis();
         int count2 = 4;


Reply via email to