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/12/18 19:51:36 UTC

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

Author: jukka
Date: Wed Dec 18 18:51:36 2013
New Revision: 1552059

URL: http://svn.apache.org/r1552059
Log:
OAK-1273: Reduce overhead when handling many parallel property indices

Move comparison code from Template into SegmentNodeState to simplify diff stack traces

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

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=1552059&r1=1552058&r2=1552059&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 Dec 18 18:51:36 2013
@@ -24,6 +24,7 @@ import javax.annotation.Nonnull;
 
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
@@ -388,19 +389,170 @@ public class SegmentNodeState extends Re
         if (this == base || fastEquals(this, base)) {
              return true; // no changes
         } else if (base == EMPTY_NODE || !base.exists()) { // special case
-            return getTemplate().compareAgainstEmptyState(
-                    getSegment(), getRecordId(), diff);
-        } else if (base instanceof SegmentNodeState) {
-            SegmentNodeState that = (SegmentNodeState) base;
-            return getTemplate().compareAgainstBaseState(
-                    getSegment(), getRecordId(), that.getTemplate(),
-                    that.getSegment(), that.getRecordId(), diff);
-        } else {
-            // fallback
+            return EmptyNodeState.compareAgainstEmptyState(this, diff);
+        } else if (!(base instanceof SegmentNodeState)) { // fallback
             return AbstractNodeState.compareAgainstBaseState(this, base, diff);
         }
+
+        Template afterTemplate = getTemplate();
+        Segment afterSegment = getSegment();
+        RecordId afterId = getRecordId();
+
+        SegmentNodeState that = (SegmentNodeState) base;
+        Template beforeTemplate = that.getTemplate();
+        Segment beforeSegment = that.getSegment();
+        RecordId beforeId = that.getRecordId();
+
+        // Compare type properties
+        if (!compareProperties(
+                beforeTemplate.getPrimaryType(), afterTemplate.getPrimaryType(),
+                diff)) {
+            return false;
+        }
+        if (!compareProperties(
+                beforeTemplate.getMixinTypes(), afterTemplate.getMixinTypes(),
+                diff)) {
+            return false;
+        }
+
+        // Compare other properties, leveraging the ordering
+        int beforeIndex = 0;
+        int afterIndex = 0;
+        PropertyTemplate[] beforeProperties =
+                beforeTemplate.getPropertyTemplates();
+        PropertyTemplate[] afterProperties =
+                afterTemplate.getPropertyTemplates();
+        while (beforeIndex < beforeProperties.length
+                && afterIndex < afterProperties.length) {
+            int d = Integer.valueOf(afterProperties[afterIndex].hashCode())
+                    .compareTo(Integer.valueOf(beforeProperties[beforeIndex].hashCode()));
+            if (d == 0) {
+                d = afterProperties[afterIndex].getName().compareTo(
+                        beforeProperties[beforeIndex].getName());
+            }
+            PropertyState beforeProperty = null;
+            PropertyState afterProperty = null;
+            if (d < 0) {
+                afterProperty = afterTemplate.getProperty(afterSegment, afterId, afterIndex++);
+            } else if (d > 0) {
+                beforeProperty = beforeTemplate.getProperty(
+                        beforeSegment, beforeId, beforeIndex++);
+            } else {
+                afterProperty = afterTemplate.getProperty(
+                        afterSegment, afterId, afterIndex++);
+                beforeProperty = beforeTemplate.getProperty(
+                        beforeSegment, beforeId, beforeIndex++);
+            }
+            if (!compareProperties(beforeProperty, afterProperty, diff)) {
+                return false;
+            }
+        }
+        while (afterIndex < afterProperties.length) {
+            if (!diff.propertyAdded(afterTemplate.getProperty(
+                    afterSegment, afterId, afterIndex++))) {
+                return false;
+            }
+        }
+        while (beforeIndex < beforeProperties.length) {
+            PropertyState beforeProperty = beforeTemplate.getProperty(
+                    beforeSegment, beforeId, beforeIndex++);
+            if (!diff.propertyDeleted(beforeProperty)) {
+                return false;
+            }
+        }
+
+        String beforeChildName = beforeTemplate.getChildName();
+        String afterChildName = afterTemplate.getChildName();
+        if (afterChildName == Template.ZERO_CHILD_NODES) {
+            if (beforeChildName != Template.ZERO_CHILD_NODES) {
+                for (ChildNodeEntry entry : beforeTemplate.getChildNodeEntries(
+                        beforeSegment, beforeId)) {
+                    if (!diff.childNodeDeleted(
+                            entry.getName(), entry.getNodeState())) {
+                        return false;
+                    }
+                }
+            }
+        } else if (afterChildName != Template.MANY_CHILD_NODES) {
+            NodeState afterNode = afterTemplate.getChildNode(
+                    afterChildName, afterSegment, afterId);
+            NodeState beforeNode = beforeTemplate.getChildNode(
+                    afterChildName, beforeSegment, beforeId);
+            if (!beforeNode.exists()) {
+                if (!diff.childNodeAdded(afterChildName, afterNode)) {
+                    return false;
+                }
+            } else if (!fastEquals(afterNode, beforeNode)) {
+                if (!diff.childNodeChanged(
+                        afterChildName, beforeNode, afterNode)) {
+                    return false;
+                }
+            }
+            if (beforeChildName == Template.MANY_CHILD_NODES
+                    || (beforeChildName != Template.ZERO_CHILD_NODES
+                        && !beforeNode.exists())) {
+                for (ChildNodeEntry entry :
+                    beforeTemplate.getChildNodeEntries(beforeSegment, beforeId)) {
+                    if (!afterChildName.equals(entry.getName())) {
+                        if (!diff.childNodeDeleted(
+                                entry.getName(), entry.getNodeState())) {
+                            return false;
+                        }
+                    }
+                }
+            }
+        } else if (beforeChildName == Template.ZERO_CHILD_NODES) {
+            for (ChildNodeEntry entry
+                    : afterTemplate.getChildNodeEntries(afterSegment, afterId)) {
+                if (!diff.childNodeAdded(
+                        entry.getName(), entry.getNodeState())) {
+                    return false;
+                }
+            }
+        } else if (beforeChildName != Template.MANY_CHILD_NODES) {
+            for (ChildNodeEntry entry : afterTemplate.getChildNodeEntries(afterSegment, afterId)) {
+                String childName = entry.getName();
+                NodeState afterChild = entry.getNodeState();
+                if (beforeChildName.equals(childName)) {
+                    NodeState beforeChild = beforeTemplate.getChildNode(
+                            beforeChildName, beforeSegment, beforeId);
+                    if (beforeChild.exists()) {
+                        if (!fastEquals(afterChild, beforeChild)
+                                && !diff.childNodeChanged(
+                                        childName, beforeChild, afterChild)) {
+                            return false;
+                        }
+                    } else {
+                        if (!diff.childNodeAdded(childName, afterChild)) {
+                            return false;
+                        }
+                    }
+                } else if (!diff.childNodeAdded(childName, afterChild)) {
+                    return false;
+                }
+            }
+        } else {
+            MapRecord afterMap = afterTemplate.getChildNodeMap(afterSegment, afterId);
+            MapRecord beforeMap = beforeTemplate.getChildNodeMap(beforeSegment, beforeId);
+            return afterMap.compare(beforeMap, diff);
+        }
+
+        return true;
     }
 
+    private static boolean compareProperties(
+            PropertyState before, PropertyState after, NodeStateDiff diff) {
+        if (before == null) {
+            return after == null || diff.propertyAdded(after);
+        } else if (after == null) {
+            return diff.propertyDeleted(before);
+        } else {
+            return before.equals(after) || diff.propertyChanged(before, after);
+        }
+    }
+
+    //------------------------------------------------------------< Object >--
+
     @Override
     public boolean equals(Object object) {
         if (this == object || fastEquals(this, object)) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java?rev=1552059&r1=1552058&r2=1552059&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java Wed Dec 18 18:51:36 2013
@@ -38,7 +38,6 @@ import org.apache.jackrabbit.oak.api.Typ
 import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 
 public class Template {
 
@@ -160,7 +159,7 @@ public class Template {
         return childName;
     }
 
-    private PropertyState getProperty(
+    PropertyState getProperty(
             Segment segment, RecordId recordId, int index) {
         checkElementIndex(index, properties.length);
         segment = checkNotNull(segment).getSegment(checkNotNull(recordId));
@@ -265,199 +264,6 @@ public class Template {
         }
     }
 
-    public boolean compareAgainstBaseState(
-            Segment afterSegment, RecordId afterId,
-            Template beforeTemplate, Segment beforeSegment, RecordId beforeId,
-            final NodeStateDiff diff) {
-        checkNotNull(afterSegment);
-        checkNotNull(afterId);
-        checkNotNull(beforeTemplate);
-        checkNotNull(beforeSegment);
-        checkNotNull(beforeId);
-        checkNotNull(diff);
-
-        // Compare type properties
-        if (!compareProperties(beforeTemplate.primaryType, primaryType, diff)
-                || !compareProperties(beforeTemplate.mixinTypes, mixinTypes, diff)) {
-            return false;
-        }
-
-        // Compare other properties, leveraging the ordering
-        int beforeIndex = 0;
-        int afterIndex = 0;
-        while (beforeIndex < beforeTemplate.properties.length
-                && afterIndex < properties.length) {
-            int d = Integer.valueOf(properties[afterIndex].hashCode())
-                    .compareTo(Integer.valueOf(beforeTemplate.properties[beforeIndex].hashCode()));
-            if (d == 0) {
-                d = properties[afterIndex].getName().compareTo(
-                        beforeTemplate.properties[beforeIndex].getName());
-            }
-            PropertyState beforeProperty = null;
-            PropertyState afterProperty = null;
-            if (d < 0) {
-                afterProperty = getProperty(afterSegment, afterId, afterIndex++);
-            } else if (d > 0) {
-                beforeProperty = beforeTemplate.getProperty(
-                        beforeSegment, beforeId, beforeIndex++);
-            } else {
-                afterProperty = getProperty(afterSegment, afterId, afterIndex++);
-                beforeProperty = beforeTemplate.getProperty(
-                        beforeSegment, beforeId, beforeIndex++);
-            }
-            if (!compareProperties(beforeProperty, afterProperty, diff)) {
-                return false;
-            }
-        }
-        while (afterIndex < properties.length) {
-            if (!diff.propertyAdded(getProperty(afterSegment, afterId, afterIndex++))) {
-                return false;
-            }
-        }
-        while (beforeIndex < beforeTemplate.properties.length) {
-            PropertyState beforeProperty = beforeTemplate.getProperty(
-                    beforeSegment, beforeId, beforeIndex++);
-            if (!diff.propertyDeleted(beforeProperty)) {
-                return false;
-            }
-        }
-
-        if (childName == ZERO_CHILD_NODES) {
-            if (beforeTemplate.childName != ZERO_CHILD_NODES) {
-                for (ChildNodeEntry entry : beforeTemplate.getChildNodeEntries(
-                        beforeSegment, beforeId)) {
-                    if (!diff.childNodeDeleted(
-                            entry.getName(), entry.getNodeState())) {
-                        return false;
-                    }
-                }
-            }
-        } else if (childName != MANY_CHILD_NODES) {
-            NodeState afterNode = getChildNode(childName, afterSegment, afterId);
-            NodeState beforeNode = beforeTemplate.getChildNode(
-                    childName, beforeSegment, beforeId);
-            if (!beforeNode.exists()) {
-                if (!diff.childNodeAdded(childName, afterNode)) {
-                    return false;
-                }
-            } else if (!fastEquals(afterNode, beforeNode)) {
-                if (!diff.childNodeChanged(childName, beforeNode, afterNode)) {
-                    return false;
-                }
-            }
-            if (beforeTemplate.childName == MANY_CHILD_NODES
-                    || (beforeTemplate.childName != ZERO_CHILD_NODES
-                        && !beforeNode.exists())) {
-                for (ChildNodeEntry entry :
-                    beforeTemplate.getChildNodeEntries(beforeSegment, beforeId)) {
-                    if (!childName.equals(entry.getName())) {
-                        if (!diff.childNodeDeleted(
-                                entry.getName(), entry.getNodeState())) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        } else if (beforeTemplate.childName == ZERO_CHILD_NODES) {
-            for (ChildNodeEntry entry : getChildNodeEntries(afterSegment, afterId)) {
-                if (!diff.childNodeAdded(
-                        entry.getName(), entry.getNodeState())) {
-                    return false;
-                }
-            }
-        } else if (beforeTemplate.childName != MANY_CHILD_NODES) {
-            String name = beforeTemplate.childName;
-            for (ChildNodeEntry entry : getChildNodeEntries(afterSegment, afterId)) {
-                String childName = entry.getName();
-                NodeState afterChild = entry.getNodeState();
-                if (name.equals(childName)) {
-                    NodeState beforeChild =
-                            beforeTemplate.getChildNode(name, beforeSegment, beforeId);
-                    if (beforeChild.exists()) {
-                        if (!fastEquals(afterChild, beforeChild)
-                                && !diff.childNodeChanged(
-                                        childName, beforeChild, afterChild)) {
-                            return false;
-                        }
-                    } else {
-                        if (!diff.childNodeAdded(childName, afterChild)) {
-                            return false;
-                        }
-                    }
-                } else if (!diff.childNodeAdded(childName, afterChild)) {
-                    return false;
-                }
-            }
-        } else {
-            // TODO: Leverage the HAMT data structure for the comparison
-            MapRecord afterMap = getChildNodeMap(afterSegment, afterId);
-            MapRecord beforeMap = beforeTemplate.getChildNodeMap(beforeSegment, beforeId);
-            return afterMap.compare(beforeMap, diff);
-        }
-
-        return true;
-    }
-
-    public boolean compareAgainstEmptyState(
-            Segment segment, RecordId recordId, final NodeStateDiff diff) {
-        checkNotNull(segment);
-        checkNotNull(recordId);
-        checkNotNull(diff);
-
-        // Type properties
-        if (primaryType != null && !diff.propertyAdded(primaryType)) {
-            return false;
-        }
-        if (mixinTypes != null && !diff.propertyAdded(mixinTypes)) {
-            return false;
-        }
-
-        segment = segment.getSegment(recordId);
-        int offset = recordId.getOffset() + RECORD_ID_BYTES;
-
-        if (childName == MANY_CHILD_NODES) {
-            RecordId childNodesId = segment.readRecordId(offset);
-            MapRecord children = segment.readMap(childNodesId);
-            for (MapEntry entry : children.getEntries()) {
-                if (!diff.childNodeAdded(
-                        entry.getName(), entry.getNodeState())) {
-                    return false;
-                }
-            }
-            offset += RECORD_ID_BYTES;
-        } else if (childName != ZERO_CHILD_NODES) {
-            RecordId childNodeId = segment.readRecordId(offset);
-            if (!diff.childNodeAdded(
-                    childName, new SegmentNodeState(segment, childNodeId))) {
-                return false;
-            }
-            offset += RECORD_ID_BYTES;
-        }
-
-        // Other properties
-        for (int i = 0; i < properties.length; i++) {
-            if (!diff.propertyAdded(new SegmentPropertyState(
-                    segment, segment.readRecordId(offset), properties[i]))) {
-                return false;
-            }
-            offset += RECORD_ID_BYTES;
-        }
-
-        return true;
-    }
-
-
-    private boolean compareProperties(
-            PropertyState before, PropertyState after, NodeStateDiff diff) {
-        if (before == null) {
-            return after == null || diff.propertyAdded(after);
-        } else if (after == null) {
-            return diff.propertyDeleted(before);
-        } else {
-            return before.equals(after) || diff.propertyChanged(before, after);
-        }
-    }
-
     //------------------------------------------------------------< Object >--
 
     @Override