You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2012/07/06 17:52:53 UTC

svn commit: r1358282 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: plugins/memory/ spi/state/

Author: jukka
Date: Fri Jul  6 15:52:53 2012
New Revision: 1358282

URL: http://svn.apache.org/viewvc?rev=1358282&view=rev
Log:
OAK-171: Add NodeState.compareAgainstBaseState()

First version, not yet optimized.

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java Fri Jul  6 15:52:53 2012
@@ -20,8 +20,10 @@ import org.apache.jackrabbit.oak.api.Pro
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -94,4 +96,42 @@ public class MemoryNodeState extends Abs
         };
     }
 
+    /**
+     * We don't keep track of a separate base node state for
+     * {@link MemoryNodeState} instances, so this method will just do
+     * a generic diff against the given state.
+     */
+    @Override
+    public void compareAgainstBaseState(NodeState base, NodeStateDiff diff) {
+        Map<String, PropertyState> newProperties =
+                new HashMap<String, PropertyState>(properties);
+        for (PropertyState before : base.getProperties()) {
+            PropertyState after = newProperties.remove(before.getName());
+            if (after == null) {
+                diff.propertyDeleted(before);
+            } else if (!after.equals(before)) {
+                diff.propertyChanged(before, after);
+            }
+        }
+        for (PropertyState after : newProperties.values()) {
+            diff.propertyAdded(after);
+        }
+
+        Map<String, NodeState> newNodes =
+                new HashMap<String, NodeState>(nodes);
+        for (ChildNodeEntry entry : base.getChildNodeEntries()) {
+            String name = entry.getName();
+            NodeState before = entry.getNodeState();
+            NodeState after = newNodes.remove(name);
+            if (after == null) {
+                diff.childNodeDeleted(name, before);
+            } else if (!after.equals(before)) {
+                diff.childNodeChanged(name, before, after);
+            }
+        }
+        for (Map.Entry<String, NodeState> entry : newNodes.entrySet()) {
+            diff.childNodeAdded(entry.getKey(), entry.getValue());
+        }
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java Fri Jul  6 15:52:53 2012
@@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.plugin
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeStore;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 
 /**
  * Abstract node store base class with in-memory node state builder
@@ -35,18 +34,4 @@ public abstract class MemoryNodeStore ex
         return new MemoryNodeStateBuilder(base);
     }
 
-    @Override
-    public void compare(NodeState before, NodeState after, NodeStateDiff diff) {
-        if (after instanceof ModifiedNodeState) {
-            ModifiedNodeState modified = (ModifiedNodeState) after;
-            if (before.equals(modified.getBase())) {
-                modified.diffAgainstBase(diff);
-            } else {
-                super.compare(before, after, diff);
-            }
-        } else {
-            super.compare(before, after, diff);
-        }
-    }
-
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java Fri Jul  6 15:52:53 2012
@@ -46,39 +46,6 @@ public class ModifiedNodeState extends A
         this.nodes = nodes;
     }
 
-    NodeState getBase() {
-        return base;
-    }
-
-    void diffAgainstBase(NodeStateDiff diff) {
-        for (Map.Entry<String, PropertyState> entry : properties.entrySet()) {
-            PropertyState before = base.getProperty(entry.getKey());
-            PropertyState after = entry.getValue();
-            if (after == null) {
-                assert before != null;
-                diff.propertyDeleted(before);
-            } else if (before == null) {
-                diff.propertyAdded(after);
-            } else {
-                diff.propertyChanged(before, after);
-            }
-        }
-
-        for (Map.Entry<String, NodeState> entry : nodes.entrySet()) {
-            String name = entry.getKey();
-            NodeState before = base.getChildNode(name);
-            NodeState after = entry.getValue();
-            if (after == null) {
-                assert before != null;
-                diff.childNodeDeleted(name, before);
-            } else if (before == null) {
-                diff.childNodeAdded(name, after);
-            } else {
-                diff.childNodeChanged(name, before, after);
-            }
-        }
-    }
-
     //---------------------------------------------------------< NodeState >--
 
     @Override
@@ -177,6 +144,89 @@ public class ModifiedNodeState extends A
         };
     }
 
+    /**
+     * Since we keep track of an explicit base node state for a
+     * {@link ModifiedNodeState} instance, we can do this in two steps:
+     * first compare the base states to each other (often a fast operation),
+     * ignoring all changed properties and child nodes for which we have
+     * further modifications, and then compare all the modified properties
+     * and child nodes to those in the given base state.
+     */
+    @Override
+    public void compareAgainstBaseState(
+            NodeState base, final NodeStateDiff diff) {
+        this.base.compareAgainstBaseState(base, new NodeStateDiff() {
+            @Override
+            public void propertyAdded(PropertyState after) {
+                if (!properties.containsKey(after.getName())) {
+                    diff.propertyAdded(after);
+                }
+            }
+            @Override
+            public void propertyChanged(
+                    PropertyState before, PropertyState after) {
+                if (!properties.containsKey(before.getName())) {
+                    diff.propertyChanged(before, after);
+                }
+            }
+            @Override
+            public void propertyDeleted(PropertyState before) {
+                if (!properties.containsKey(before.getName())) {
+                    diff.propertyDeleted(before);
+                }
+            }
+            @Override
+            public void childNodeAdded(String name, NodeState after) {
+                if (!nodes.containsKey(name)) {
+                    diff.childNodeAdded(name, after);
+                }
+            }
+            @Override
+            public void childNodeChanged(String name, NodeState before, NodeState after) {
+                if (!nodes.containsKey(name)) {
+                    diff.childNodeChanged(name, before, after);
+                }
+            }
+            @Override
+            public void childNodeDeleted(String name, NodeState before) {
+                if (!nodes.containsKey(name)) {
+                    diff.childNodeDeleted(name, before);
+                }
+            }
+        });
+
+        for (Map.Entry<String, PropertyState> entry : properties.entrySet()) {
+            PropertyState before = base.getProperty(entry.getKey());
+            PropertyState after = entry.getValue();
+            if (before == null && after == null) {
+                // do nothing
+            } else if (after == null) {
+                diff.propertyDeleted(before);
+            } else if (before == null) {
+                diff.propertyAdded(after);
+            } else if (!before.equals(after)) {
+                diff.propertyChanged(before, after);
+            }
+        }
+
+        for (Map.Entry<String, NodeState> entry : nodes.entrySet()) {
+            String name = entry.getKey();
+            NodeState before = base.getChildNode(name);
+            NodeState after = entry.getValue();
+            if (before == null && after == null) {
+                // do nothing
+            } else if (after == null) {
+                diff.childNodeDeleted(name, before);
+            } else if (before == null) {
+                diff.childNodeAdded(name, after);
+            } else if (!before.equals(after)) {
+                diff.childNodeChanged(name, before, after);
+            }
+        }
+    }
+
+    //-----------------------------------------------------------< private >--
+
     private class UnmodifiedPropertyPredicate implements Predicate<PropertyState> {
         @Override
         public boolean evaluate(PropertyState property) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java Fri Jul  6 15:52:53 2012
@@ -18,6 +18,9 @@ package org.apache.jackrabbit.oak.spi.st
 
 import org.apache.jackrabbit.oak.api.PropertyState;
 
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -65,12 +68,52 @@ public abstract class AbstractNodeState 
         return count(getChildNodeEntries());
     }
 
-    private static long count(Iterable<?> iterable) {
-        long n = 0;
-        for (Object x : iterable) {
-            n++;
+    /**
+     * Generic default comparison algorithm that simply walks through the
+     * property and child node lists of the given base state and compares
+     * the entries one by one with corresponding ones (if any) in this state.
+     */
+    @Override
+    public void compareAgainstBaseState(NodeState base, NodeStateDiff diff) {
+        Set<String> baseProperties = new HashSet<String>();
+        for (PropertyState beforeProperty : base.getProperties()) {
+            String name = beforeProperty.getName();
+            PropertyState afterProperty = getProperty(name);
+            if (afterProperty == null) {
+                diff.propertyDeleted(beforeProperty);
+            } else {
+                baseProperties.add(name);
+                if (!beforeProperty.equals(afterProperty)) {
+                    diff.propertyChanged(beforeProperty, afterProperty);
+                }
+            }
+        }
+        for (PropertyState afterProperty : getProperties()) {
+            if (!baseProperties.contains(afterProperty.getName())) {
+                diff.propertyAdded(afterProperty);
+            }
+        }
+
+        Set<String> baseChildNodes = new HashSet<String>();
+        for (ChildNodeEntry beforeCNE : base.getChildNodeEntries()) {
+            String name = beforeCNE.getName();
+            NodeState beforeChild = beforeCNE.getNodeState();
+            NodeState afterChild = getChildNode(name);
+            if (afterChild == null) {
+                diff.childNodeDeleted(name, beforeChild);
+            } else {
+                baseChildNodes.add(name);
+                if (!beforeChild.equals(afterChild)) {
+                    diff.childNodeChanged(name, beforeChild, afterChild);
+                }
+            }
+        }
+        for (ChildNodeEntry afterChild : getChildNodeEntries()) {
+            String name = afterChild.getName();
+            if (!baseChildNodes.contains(name)) {
+                diff.childNodeAdded(name, afterChild.getNodeState());
+            }
         }
-        return n;
     }
 
     /**
@@ -153,4 +196,16 @@ public abstract class AbstractNodeState 
         return 0;
     }
 
+    //-----------------------------------------------------------< private >--
+
+    private static long count(Iterable<?> iterable) {
+        long n = 0;
+        Iterator<?> iterator = iterable.iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            n++;
+        }
+        return n;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeStore.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeStore.java Fri Jul  6 15:52:53 2012
@@ -18,81 +18,12 @@
  */
 package org.apache.jackrabbit.oak.spi.state;
 
-import org.apache.jackrabbit.oak.api.PropertyState;
-
-import java.util.HashSet;
-import java.util.Set;
 
 public abstract class AbstractNodeStore implements NodeStore {
 
     @Override
     public void compare(NodeState before, NodeState after, NodeStateDiff diff) {
-        compareProperties(before, after, diff);
-        compareChildNodes(before, after, diff);
-    }
-
-    /**
-     * Compares the properties of the given two node states.
-     *
-     * @param before node state before changes
-     * @param after node state after changes
-     * @param diff handler of node state differences
-     */
-    protected void compareProperties(
-            NodeState before, NodeState after, NodeStateDiff diff) {
-        Set<String> beforeProperties = new HashSet<String>();
-
-        for (PropertyState beforeProperty : before.getProperties()) {
-            String name = beforeProperty.getName();
-            PropertyState afterProperty = after.getProperty(name);
-            if (afterProperty == null) {
-                diff.propertyDeleted(beforeProperty);
-            } else {
-                beforeProperties.add(name);
-                if (!beforeProperty.equals(afterProperty)) {
-                    diff.propertyChanged(beforeProperty, afterProperty);
-                }
-            }
-        }
-
-        for (PropertyState afterProperty : after.getProperties()) {
-            if (!beforeProperties.contains(afterProperty.getName())) {
-                diff.propertyAdded(afterProperty);
-            }
-        }
-    }
-
-    /**
-     * Compares the child nodes of the given two node states.
-     *
-     * @param before node state before changes
-     * @param after node state after changes
-     * @param diff handler of node state differences
-     */
-    protected void compareChildNodes(
-            NodeState before, NodeState after, NodeStateDiff diff) {
-        Set<String> beforeChildNodes = new HashSet<String>();
-
-        for (ChildNodeEntry beforeCNE : before.getChildNodeEntries()) {
-            String name = beforeCNE.getName();
-            NodeState beforeChild = beforeCNE.getNodeState();
-            NodeState afterChild = after.getChildNode(name);
-            if (afterChild == null) {
-                diff.childNodeDeleted(name, beforeChild);
-            } else {
-                beforeChildNodes.add(name);
-                if (!beforeChild.equals(afterChild)) {
-                    diff.childNodeChanged(name, beforeChild, afterChild);
-                }
-            }
-        }
-
-        for (ChildNodeEntry afterChild : after.getChildNodeEntries()) {
-            String name = afterChild.getName();
-            if (!beforeChildNodes.contains(name)) {
-                diff.childNodeAdded(name, afterChild.getNodeState());
-            }
-        }
+        after.compareAgainstBaseState(before, diff);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java?rev=1358282&r1=1358281&r2=1358282&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java Fri Jul  6 15:52:53 2012
@@ -159,4 +159,15 @@ public interface NodeState {
     @Nonnull
     Iterable<? extends ChildNodeEntry> getChildNodeEntries();
 
+    /**
+     * Compares this node state against the given base state. Any differences
+     * are reported by calling the relevant added/changed/deleted methods of
+     * the given handler.
+     *
+     * @param base base state
+     * @param diff handler of node state differences
+     * @since 0ak 0.4
+     */
+    void compareAgainstBaseState(NodeState base, NodeStateDiff diff);
+
 }