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 2013/02/20 14:13:17 UTC

svn commit: r1448150 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment: NodeTemplate.java SegmentNodeState.java

Author: jukka
Date: Wed Feb 20 13:13:17 2013
New Revision: 1448150

URL: http://svn.apache.org/r1448150
Log:
OAK-630: SegmentMK: Implement compareAgainstBaseState

Initial SegmentNodeState.compareAgainstBaseState implementation

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/NodeTemplate.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/NodeTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/NodeTemplate.java?rev=1448150&r1=1448149&r2=1448150&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/NodeTemplate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/NodeTemplate.java Wed Feb 20 13:13:17 2013
@@ -16,11 +16,15 @@
  */
 package org.apache.jackrabbit.oak.plugins.segment;
 
+import static com.google.common.base.Preconditions.checkElementIndex;
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -32,6 +36,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.segment.MapRecord.Entry;
 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 com.google.common.base.Function;
 import com.google.common.base.Objects;
@@ -181,16 +186,10 @@ class NodeTemplate {
         } else if ("jcr:mixinTypes".equals(name) && mixinTypes != null) {
             return mixinTypes;
         } else {
-            int offset = 8;
-            if (hasNoChildNodes()) {
-                offset = 4;
-            }
             for (int i = 0; i < properties.length; i++) {
                 int diff = name.compareTo(properties[i].getName());
                 if (diff == 0) {
-                    return new SegmentPropertyState(
-                            properties[i], reader,
-                            reader.readRecordId(recordId, offset + i * 4));
+                    return getProperty(reader, recordId, i);
                 } else if (diff < 0) {
                     return null;
                 }
@@ -199,6 +198,21 @@ class NodeTemplate {
         }
     }
 
+    private PropertyState getProperty(
+            SegmentReader reader, RecordId recordId, int index) {
+        checkNotNull(reader);
+        checkNotNull(recordId);
+        checkElementIndex(index, properties.length);
+
+        int offset = 8;
+        if (hasNoChildNodes()) {
+            offset = 4;
+        }
+        return new SegmentPropertyState(
+                properties[index], reader,
+                reader.readRecordId(recordId, offset + index * 4));
+    }
+
     public Iterable<PropertyState> getProperties(
             SegmentReader reader, RecordId recordId) {
         List<PropertyState> list =
@@ -308,6 +322,116 @@ class NodeTemplate {
         }
     }
 
+    public void compareAgainstBaseState(
+            SegmentReader reader, RecordId afterId,
+            NodeTemplate beforeTemplate, RecordId beforeId,
+            NodeStateDiff diff) {
+        checkNotNull(reader);
+        checkNotNull(afterId);
+        checkNotNull(beforeTemplate);
+        checkNotNull(beforeId);
+        checkNotNull(diff);
+
+        // Compare type properties
+        compareProperties(beforeTemplate.primaryType, primaryType, diff);
+        compareProperties(beforeTemplate.mixinTypes, mixinTypes, diff);
+
+        // Compare other properties, leveraging the ordering
+        int beforeIndex = 0;
+        int afterIndex = 0;
+        while (beforeIndex < beforeTemplate.properties.length
+                && afterIndex < properties.length) {
+            int d = properties[afterIndex].compareTo(
+                    beforeTemplate.properties[beforeIndex]);
+            PropertyState beforeProperty = null;
+            PropertyState afterProperty = null;
+            if (d < 0) {
+                afterProperty = getProperty(reader, afterId, afterIndex++);
+            } else if (d > 0) {
+                beforeProperty = beforeTemplate.getProperty(
+                        reader, beforeId, beforeIndex++);
+            } else {
+                afterProperty = getProperty(reader, afterId, afterIndex++);
+                beforeProperty = beforeTemplate.getProperty(
+                        reader, beforeId, beforeIndex++);
+            }
+            compareProperties(beforeProperty, afterProperty, diff);
+        }
+        while (afterIndex < properties.length) {
+            diff.propertyAdded(getProperty(reader, afterId, afterIndex++));
+        }
+        while (beforeIndex < beforeTemplate.properties.length) {
+            diff.propertyDeleted(beforeTemplate.getProperty(
+                    reader, beforeId, beforeIndex++));
+        }
+
+        if (hasNoChildNodes()) {
+            if (!beforeTemplate.hasNoChildNodes()) {
+                for (ChildNodeEntry entry :
+                        beforeTemplate.getChildNodeEntries(reader, beforeId)) {
+                    diff.childNodeDeleted(
+                            entry.getName(), entry.getNodeState());
+                }
+            }
+        } else if (hasOneChildNode()) {
+            NodeState afterNode = getChildNode(childName, reader, afterId);
+            NodeState beforeNode = beforeTemplate.getChildNode(
+                    childName, reader, beforeId);
+            if (beforeNode == null) {
+                diff.childNodeAdded(childName, afterNode);
+            } else if (!beforeNode.equals(afterNode)) {
+                diff.childNodeChanged(childName, beforeNode, afterNode);
+            }
+            if ((beforeTemplate.hasOneChildNode() && beforeNode == null)
+                    || beforeTemplate.hasManyChildNodes()) {
+                for (ChildNodeEntry entry :
+                    beforeTemplate.getChildNodeEntries(reader, beforeId)) {
+                    if (!childName.equals(entry.getName())) {
+                        diff.childNodeDeleted(
+                                entry.getName(), entry.getNodeState());
+                    }
+                }
+            }
+        } else {
+            // TODO: Leverage the HAMT data structure for the comparison
+            Set<String> baseChildNodes = new HashSet<String>();
+            for (ChildNodeEntry beforeCNE
+                    : beforeTemplate.getChildNodeEntries(reader, beforeId)) {
+                String name = beforeCNE.getName();
+                NodeState beforeChild = beforeCNE.getNodeState();
+                NodeState afterChild = getChildNode(name, reader, afterId);
+                if (afterChild == null) {
+                    diff.childNodeDeleted(name, beforeChild);
+                } else {
+                    baseChildNodes.add(name);
+                    if (!beforeChild.equals(afterChild)) {
+                        diff.childNodeChanged(name, beforeChild, afterChild);
+                    }
+                }
+            }
+            for (ChildNodeEntry afterChild
+                    : getChildNodeEntries(reader, afterId)) {
+                String name = afterChild.getName();
+                if (!baseChildNodes.contains(name)) {
+                    diff.childNodeAdded(name, afterChild.getNodeState());
+                }
+            }
+        }
+    }
+
+    private void compareProperties(
+            PropertyState before, PropertyState after, NodeStateDiff diff) {
+        if (before == null) {
+            if (after != null) {
+                diff.propertyAdded(after);
+            }
+        } else if (after == null) {
+            diff.propertyDeleted(before);
+        } else if (!before.equals(after)) {
+            diff.propertyChanged(before, after);
+        }
+    }
+
     //------------------------------------------------------------< Object >--
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java?rev=1448150&r1=1448149&r2=1448150&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java Wed Feb 20 13:13:17 2013
@@ -27,6 +27,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 
 class SegmentNodeState extends AbstractNodeState {
 
@@ -102,6 +103,20 @@ class SegmentNodeState extends AbstractN
         return new MemoryNodeBuilder(this);
     }
 
+    @Override
+    public void compareAgainstBaseState(NodeState base, NodeStateDiff diff) {
+        if (base instanceof SegmentNodeState) {
+            SegmentNodeState that = (SegmentNodeState) base;
+            if (!recordId.equals(that.recordId)) {
+                getTemplate().compareAgainstBaseState(
+                        reader, recordId, that.getTemplate(), that.recordId,
+                        diff);
+            }
+        } else {
+            super.compareAgainstBaseState(base, diff); // fallback
+        }
+    }
+
     public boolean equals(Object object) {
         if (this == object) {
             return true;