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