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/10/24 19:38:39 UTC
svn commit: r1401794 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak:
plugins/memory/MemoryNodeBuilder.java spi/state/NodeBuilder.java
spi/state/ReadOnlyBuilder.java
Author: jukka
Date: Wed Oct 24 17:38:38 2012
New Revision: 1401794
URL: http://svn.apache.org/viewvc?rev=1401794&view=rev
Log:
OAK-170: Child node state builder
Add a NodeBuidler.reset(NodeState) method to make rebase operations possible with builders
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java?rev=1401794&r1=1401793&r2=1401794&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java Wed Oct 24 17:38:38 2012
@@ -103,7 +103,7 @@ public class MemoryNodeBuilder implement
* The base state of this builder, or {@code null} if this builder
* represents a new node that didn't yet exist in the base content tree.
*/
- private final NodeState baseState;
+ private NodeState baseState;
/**
* The shared mutable state of connected builder instances, or
@@ -150,25 +150,34 @@ public class MemoryNodeBuilder implement
if (revision != root.revision) {
assert(parent != null); // root never gets here
parent.read();
- MutableNodeState pstate = parent.writeState;
- if (pstate != null) {
- MutableNodeState mstate = pstate.nodes.get(name);
- if (mstate == null) {
- if (pstate.nodes.containsKey(name)) {
- throw new IllegalStateException(
- "This node has been removed.");
- }
- } else if (mstate != writeState) {
- writeState = mstate;
+
+ // The builder could have been reset, need to re-get base state
+ if (parent.baseState != null) {
+ baseState = parent.baseState.getChildNode(name);
+ } else {
+ baseState = null;
+ }
+
+ // ... same for the write state
+ if (parent.writeState != null) {
+ writeState = parent.writeState.nodes.get(name);
+ if (writeState == null
+ && parent.writeState.nodes.containsKey(name)) {
+ throw new IllegalStateException(
+ "This node has been removed");
}
+ } else {
+ writeState = null;
}
+
revision = root.revision;
}
if (writeState != null) {
return writeState;
- } else {
- assert baseState != null; // new nodes must have a writeState
+ } else if (baseState != null) {
return baseState;
+ } else {
+ throw new IllegalStateException("This node does not exist");
}
}
@@ -179,32 +188,36 @@ public class MemoryNodeBuilder implement
private MutableNodeState write(long newRevision) {
if (writeState == null || revision != root.revision) {
assert(parent != null); // root never gets here
- MutableNodeState pstate = parent.write(newRevision);
- MutableNodeState mstate = pstate.nodes.get(name);
- if (mstate == null) {
- if (pstate.nodes.containsKey(name)) {
+ parent.write(newRevision);
+
+ // The builder could have been reset, need to re-get base state
+ if (parent.baseState != null) {
+ baseState = parent.baseState.getChildNode(name);
+ } else {
+ baseState = null;
+ }
+
+ assert parent.writeState != null; // we just called parent.write()
+ writeState = parent.writeState.nodes.get(name);
+ if (writeState == null) {
+ if (parent.writeState.nodes.containsKey(name)) {
throw new IllegalStateException(
- "This node has been removed.");
- }
- NodeState base = baseState;
- if (base == null) {
- base = NULL_STATE;
+ "This node has been removed");
+ } else {
+ // need to make this node writable
+ NodeState base = baseState;
+ if (base == null) {
+ base = NULL_STATE;
+ }
+ writeState = new MutableNodeState(base);
+ parent.writeState.nodes.put(name, writeState);
}
- mstate = new MutableNodeState(base);
- pstate.nodes.put(name, mstate);
- }
- if (mstate != writeState) {
- writeState = mstate;
}
}
revision = newRevision;
return writeState;
}
- protected void reset(NodeState newBase) {
- write().reset(newBase);
- }
-
/**
* Factory method for creating new child state builders. Subclasses may
* override this method to control the behavior of child state builders.
@@ -253,6 +266,17 @@ public class MemoryNodeBuilder implement
}
@Override
+ public void reset(NodeState newBase) {
+ if (this == root) {
+ baseState = checkNotNull(newBase);
+ writeState = new MutableNodeState(baseState);
+ revision++;
+ } else {
+ throw new IllegalStateException("Cannot reset a non-root builder");
+ }
+ }
+
+ @Override
public long getChildNodeCount() {
return read().getChildNodeCount();
}
@@ -349,31 +373,36 @@ public class MemoryNodeBuilder implement
@Override
public NodeBuilder child(String name) {
- NodeState state = read();
-
+ // look for a read-only child node
+ read();
if (writeState == null) {
- NodeState base = state.getChildNode(name);
- if (base != null) {
- return createChildBuilder(name, base); // shortcut
+ assert baseState != null; // guaranteed by read()
+ NodeState childBase = baseState.getChildNode(name);
+ if (childBase != null) { // read-only shortcut
+ return createChildBuilder(name, childBase);
}
}
- NodeState cbase = NULL_STATE;
- MutableNodeState mstate = write();
- MutableNodeState cstate = mstate.nodes.get(name);
- if (cstate != null) {
- cbase = cstate.base;
- } else if (mstate.nodes.containsKey(name)) {
- // The child node was removed earlier and we're creating
- // a new child with the same name. Remove the removal marker
- // so that the new child builder won't try reconnecting with
- // the previously removed node.
- mstate.nodes.remove(name);
- } else if (mstate.base.hasChildNode(name)) {
- return createChildBuilder(name, mstate.base.getChildNode(name));
+ // no read-only child node found, switch to write mode
+ write();
+ assert writeState != null; // guaranteed by write()
+
+ NodeState childBase = null;
+ if (baseState != null) {
+ childBase = baseState.getChildNode(name);
}
- MemoryNodeBuilder builder = createChildBuilder(name, cbase);
+ if (writeState.nodes.get(name) == null) {
+ if (writeState.nodes.containsKey(name)) {
+ // The child node was removed earlier and we're creating
+ // a new child with the same name. Use the null state to
+ // prevent the previous child state from re-surfacing.
+ childBase = null;
+ }
+ writeState.nodes.put(name, new MutableNodeState(childBase));
+ }
+
+ MemoryNodeBuilder builder = createChildBuilder(name, childBase);
builder.write();
return builder;
}
@@ -442,7 +471,11 @@ public class MemoryNodeBuilder implement
Maps.newHashMap();
public MutableNodeState(NodeState base) {
- this.base = checkNotNull(base);
+ if (base != null) {
+ this.base = base;
+ } else {
+ this.base = NULL_STATE;
+ }
}
private void reset(NodeState newBase) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java?rev=1401794&r1=1401793&r2=1401794&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java Wed Oct 24 17:38:38 2012
@@ -47,6 +47,23 @@ public interface NodeBuilder {
NodeState getBaseState();
/**
+ * Replaces the base state of this builder and throws away all changes.
+ * The effect of this method is equivalent to replacing this builder
+ * (and the connected subtree) with a new builder returned by
+ * {@code state.builder()}.
+ * <p>
+ * This method only works on builders acquired directly from a call
+ * to {@link NodeState#builder()}. Calling it on a builder returned
+ * by the {@link #child(String)} method will throw an
+ * {@link IllegalStateException}.
+ *
+ * @param state new base state
+ * @throws IllegalStateException if this is not a root builder
+ */
+ void reset(@Nonnull NodeState state)
+ throws IllegalStateException;
+
+ /**
* Returns the current number of child nodes.
*
* @return number of child nodes
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java?rev=1401794&r1=1401793&r2=1401794&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java Wed Oct 24 17:38:38 2012
@@ -48,6 +48,11 @@ public class ReadOnlyBuilder implements
}
@Override
+ public void reset(NodeState state) {
+ throw unsupported();
+ }
+
+ @Override
public long getChildNodeCount() {
return state.getChildNodeCount();
}