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 mr...@apache.org on 2013/10/31 11:09:43 UTC
svn commit: r1537423 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/kernel/
main/java/org/apache/jackrabbit/oak/plugins/mongomk/
test/java/org/apache/jackrabbit/oak/
test/java/org/apache/jackrabbit/oak/plugins/mongomk/
Author: mreutegg
Date: Thu Oct 31 10:09:43 2013
New Revision: 1537423
URL: http://svn.apache.org/r1537423
Log:
OAK-1080: MongoMK: improved concurrency
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/BlobSerializer.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/JsonSerializer.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeBuilder.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreBranch.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/SimpleTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/BlobSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/BlobSerializer.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/BlobSerializer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/BlobSerializer.java Thu Oct 31 10:09:43 2013
@@ -22,7 +22,7 @@ import org.apache.jackrabbit.oak.api.Blo
* Customizable mechanism for mapping {@link Blob} instances to corresponding
* serialization identifiers.
*/
-class BlobSerializer {
+public class BlobSerializer {
public String serialize(Blob blob) {
return "Blob{" + blob + '}';
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/JsonSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/JsonSerializer.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/JsonSerializer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/JsonSerializer.java Thu Oct 31 10:09:43 2013
@@ -35,7 +35,7 @@ import org.apache.jackrabbit.oak.spi.sta
/**
* Utility class for serializing node and property states to JSON.
*/
-class JsonSerializer {
+public class JsonSerializer {
private final JsopBuilder json;
@@ -67,7 +67,7 @@ class JsonSerializer {
new JsonFilter(filter), blobs);
}
- JsonSerializer(JsopBuilder json, BlobSerializer blobs) {
+ public JsonSerializer(JsopBuilder json, BlobSerializer blobs) {
this(json, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
new JsonFilter("{\"properties\":[\"*\", \"-:childNodeCount\"]}"),
blobs);
@@ -116,7 +116,7 @@ class JsonSerializer {
json.endObject();
}
- void serialize(PropertyState property) {
+ public void serialize(PropertyState property) {
Type<?> type = property.getType();
if (!type.isArray()) {
serialize(property, type, 0);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitDiff.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitDiff.java Thu Oct 31 10:09:43 2013
@@ -18,11 +18,17 @@ package org.apache.jackrabbit.oak.plugin
import javax.annotation.Nonnull;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.kernel.BlobSerializer;
+import org.apache.jackrabbit.oak.kernel.JsonSerializer;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE;
/**
* Implementation of a {@link NodeStateDiff}, which translates the diffs into
@@ -32,45 +38,73 @@ class CommitDiff implements NodeStateDif
private final Commit commit;
- CommitDiff(@Nonnull Commit commit) {
- this.commit = checkNotNull(commit);
+ private final String path;
+
+ private final JsopBuilder builder;
+
+ private final BlobSerializer blobs;
+
+ CommitDiff(@Nonnull Commit commit, @Nonnull BlobSerializer blobs) {
+ this(checkNotNull(commit), "/", new JsopBuilder(), checkNotNull(blobs));
+ }
+
+ private CommitDiff(Commit commit, String path,
+ JsopBuilder builder, BlobSerializer blobs) {
+ this.commit = commit;
+ this.path = path;
+ this.builder = builder;
+ this.blobs = blobs;
}
@Override
public boolean propertyAdded(PropertyState after) {
- // TODO: implement
- return false;
+ setProperty(after);
+ return true;
}
@Override
public boolean propertyChanged(PropertyState before, PropertyState after) {
- // TODO: implement
- return false;
+ setProperty(after);
+ return true;
}
@Override
public boolean propertyDeleted(PropertyState before) {
- // TODO: implement
- return false;
+ commit.updateProperty(path, before.getName(), null);
+ return true;
}
@Override
public boolean childNodeAdded(String name, NodeState after) {
- // TODO: implement
- return false;
+ String p = PathUtils.concat(path, name);
+ commit.addNode(new Node(p, commit.getRevision()));
+ return after.compareAgainstBaseState(EMPTY_NODE,
+ new CommitDiff(commit, p, builder, blobs));
}
@Override
public boolean childNodeChanged(String name,
NodeState before,
NodeState after) {
- // TODO: implement
- return false;
+ String p = PathUtils.concat(path, name);
+ return after.compareAgainstBaseState(before,
+ new CommitDiff(commit, p, builder, blobs));
}
@Override
public boolean childNodeDeleted(String name, NodeState before) {
- // TODO: implement
- return false;
+ String p = PathUtils.concat(path, name);
+ commit.removeNode(p);
+ return MISSING_NODE.compareAgainstBaseState(before,
+ new CommitDiff(commit, p, builder, blobs));
+ }
+
+ //----------------------------< internal >----------------------------------
+
+ private void setProperty(PropertyState property) {
+ builder.resetWriter();
+ JsonSerializer serializer = new JsonSerializer(builder, blobs);
+ serializer.serialize(property);
+ commit.updateProperty(path, property.getName(), serializer.toString());
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeBuilder.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeBuilder.java Thu Oct 31 10:09:43 2013
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.plugins.mongomk;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
/**
* A node builder implementation for MongoMK.
@@ -35,4 +36,19 @@ class MongoNodeBuilder extends MemoryNod
protected MongoNodeBuilder createChildBuilder(String name) {
return new MongoNodeBuilder(this, name);
}
+
+ @Override
+ public boolean moveTo(NodeBuilder newParent, String newName) {
+ if (newParent instanceof MongoNodeBuilder) {
+ // check if this builder is an ancestor of newParent or newParent
+ MongoNodeBuilder parent = (MongoNodeBuilder) newParent;
+ while (parent != null) {
+ if (parent == this) {
+ return false;
+ }
+ parent = (MongoNodeBuilder) parent.getParent();
+ }
+ }
+ return super.moveTo(newParent, newName);
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeState.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeState.java Thu Oct 31 10:09:43 2013
@@ -17,48 +17,81 @@
package org.apache.jackrabbit.oak.plugins.mongomk;
import java.util.Collections;
+import java.util.List;
import javax.annotation.Nonnull;
+import javax.jcr.PropertyType;
+import org.apache.jackrabbit.mk.json.JsopReader;
+import org.apache.jackrabbit.mk.json.JsopTokenizer;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.kernel.StringCache;
+import org.apache.jackrabbit.oak.kernel.TypeCodes;
+import org.apache.jackrabbit.oak.plugins.memory.BinaryPropertyState;
+import org.apache.jackrabbit.oak.plugins.memory.BooleanPropertyState;
+import org.apache.jackrabbit.oak.plugins.memory.DoublePropertyState;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.plugins.memory.LongPropertyState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
+import org.apache.jackrabbit.oak.plugins.value.Conversions;
+import org.apache.jackrabbit.oak.spi.state.AbstractChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
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 com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
/**
* A {@link NodeState} implementation for the {@link MongoNodeStore}.
+ * TODO: merge MongoNodeState with Node
+ * TODO: implement more methods for efficient access (getProperty(), etc.)
*/
-class MongoNodeState extends AbstractNodeState {
+final class MongoNodeState extends AbstractNodeState {
private final MongoNodeStore store;
- private final String path;
+ private final Node node;
- private final Revision revision;
+ /**
+ * TODO: OAK-1056
+ */
+ private boolean isBranch;
MongoNodeState(@Nonnull MongoNodeStore store,
- @Nonnull String path,
- @Nonnull Revision revision) {
+ @Nonnull Node node) {
this.store = checkNotNull(store);
- this.path = checkNotNull(path);
- this.revision = checkNotNull(revision);
+ this.node = checkNotNull(node);
}
String getPath() {
- return path;
+ return node.getPath();
}
Revision getRevision() {
- return revision;
+ return node.getReadRevision();
}
- //--------------------------< NodeState >-----------------------------------
+ MongoNodeState setBranch() {
+ isBranch = true;
+ return this;
+ }
+ boolean isBranch() {
+ return isBranch;
+ }
+
+ //--------------------------< NodeState >-----------------------------------
@Override
public boolean equals(Object that) {
@@ -66,7 +99,7 @@ class MongoNodeState extends AbstractNod
return true;
} else if (that instanceof MongoNodeState) {
MongoNodeState other = (MongoNodeState) that;
- if (revision.equals(other.revision) && path.equals(other.path)) {
+ if (node.getLastRevision().equals(other.node.getLastRevision()) && getPath().equals(other.getPath())) {
return true;
} else {
// TODO: optimize equals check for this case
@@ -81,37 +114,176 @@ class MongoNodeState extends AbstractNod
@Override
public boolean exists() {
- return true;
+ return node != null;
}
@Nonnull
@Override
public Iterable<? extends PropertyState> getProperties() {
- // TODO: implement
- return Collections.emptyList();
+ if (node == null) {
+ return Collections.emptyList();
+ }
+ return Iterables.transform(node.getPropertyNames(), new Function<String, PropertyState>() {
+ @Override
+ public PropertyState apply(String name) {
+ String value = node.getProperty(name);
+ JsopReader reader = new JsopTokenizer(value);
+ if (reader.matches('[')) {
+ return readArrayProperty(name, reader);
+ } else {
+ return readProperty(name, reader);
+ }
+ }
+ });
}
@Nonnull
@Override
public NodeState getChildNode(@Nonnull String name) {
- // TODO: implement
- return EmptyNodeState.MISSING_NODE;
+ String p = PathUtils.concat(getPath(), name);
+ Node child = store.getNode(p, node.getLastRevision());
+ if (child == null) {
+ return EmptyNodeState.MISSING_NODE;
+ } else {
+ return new MongoNodeState(store, child);
+ }
}
@Nonnull
@Override
public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
- // TODO: implement
- return Collections.emptyList();
+ // TODO: handle many child nodes better
+ Node.Children children = store.getChildren(getPath(),
+ node.getLastRevision(), Integer.MAX_VALUE);
+ return Iterables.transform(children.children, new Function<String, ChildNodeEntry>() {
+ @Override
+ public ChildNodeEntry apply(String path) {
+ final String name = PathUtils.getName(path);
+ return new AbstractChildNodeEntry() {
+ @Nonnull
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Nonnull
+ @Override
+ public NodeState getNodeState() {
+ return getChildNode(name);
+ }
+ };
+ }
+ });
}
@Nonnull
@Override
public NodeBuilder builder() {
- // TODO: implement
- return new MemoryNodeBuilder(this);
+ if (isBranch) {
+ return new MemoryNodeBuilder(this);
+ } else if ("/".equals(getPath())) {
+ return new MongoRootBuilder(this, store);
+ } else {
+ return new MemoryNodeBuilder(this);
+ }
}
//------------------------------< internal >--------------------------------
+ /**
+ * FIXME: copied from KernelNodeState.
+ *
+ * Read a {@code PropertyState} from a {@link JsopReader}
+ * @param name The name of the property state
+ * @param reader The reader
+ * @return new property state
+ */
+ private PropertyState readProperty(String name, JsopReader reader) {
+ if (reader.matches(JsopReader.NUMBER)) {
+ String number = reader.getToken();
+ try {
+ return new LongPropertyState(name, Long.parseLong(number));
+ } catch (NumberFormatException e) {
+ return new DoublePropertyState(name, Double.parseDouble(number));
+ }
+ } else if (reader.matches(JsopReader.TRUE)) {
+ return BooleanPropertyState.booleanProperty(name, true);
+ } else if (reader.matches(JsopReader.FALSE)) {
+ return BooleanPropertyState.booleanProperty(name, false);
+ } else if (reader.matches(JsopReader.STRING)) {
+ String jsonString = reader.getToken();
+ if (jsonString.startsWith(TypeCodes.EMPTY_ARRAY)) {
+ int type = PropertyType.valueFromName(jsonString.substring(TypeCodes.EMPTY_ARRAY.length()));
+ return PropertyStates.createProperty(name, emptyList(), Type.fromTag(type, true));
+ }
+ int split = TypeCodes.split(jsonString);
+ if (split != -1) {
+ int type = TypeCodes.decodeType(split, jsonString);
+ String value = TypeCodes.decodeName(split, jsonString);
+ if (type == PropertyType.BINARY) {
+ return BinaryPropertyState.binaryProperty(name, store.getBlob(value));
+ } else {
+ return createProperty(name, StringCache.get(value), type);
+ }
+ } else {
+ return StringPropertyState.stringProperty(name, StringCache.get(jsonString));
+ }
+ } else {
+ throw new IllegalArgumentException("Unexpected token: " + reader.getToken());
+ }
+ }
+
+ /**
+ * FIXME: copied from KernelNodeState.
+ *
+ * Read a multi valued {@code PropertyState} from a {@link JsopReader}
+ * @param name The name of the property state
+ * @param reader The reader
+ * @return new property state
+ */
+ private PropertyState readArrayProperty(String name, JsopReader reader) {
+ int type = PropertyType.STRING;
+ List<Object> values = Lists.newArrayList();
+ while (!reader.matches(']')) {
+ if (reader.matches(JsopReader.NUMBER)) {
+ String number = reader.getToken();
+ try {
+ type = PropertyType.LONG;
+ values.add(Long.parseLong(number));
+ } catch (NumberFormatException e) {
+ type = PropertyType.DOUBLE;
+ values.add(Double.parseDouble(number));
+ }
+ } else if (reader.matches(JsopReader.TRUE)) {
+ type = PropertyType.BOOLEAN;
+ values.add(true);
+ } else if (reader.matches(JsopReader.FALSE)) {
+ type = PropertyType.BOOLEAN;
+ values.add(false);
+ } else if (reader.matches(JsopReader.STRING)) {
+ String jsonString = reader.getToken();
+ int split = TypeCodes.split(jsonString);
+ if (split != -1) {
+ type = TypeCodes.decodeType(split, jsonString);
+ String value = TypeCodes.decodeName(split, jsonString);
+ if (type == PropertyType.BINARY) {
+ values.add(store.getBlob(value));
+ } else if (type == PropertyType.DOUBLE) {
+ values.add(Conversions.convert(value).toDouble());
+ } else if (type == PropertyType.DECIMAL) {
+ values.add(Conversions.convert(value).toDecimal());
+ } else {
+ values.add(StringCache.get(value));
+ }
+ } else {
+ type = PropertyType.STRING;
+ values.add(StringCache.get(jsonString));
+ }
+ } else {
+ throw new IllegalArgumentException("Unexpected token: " + reader.getToken());
+ }
+ reader.matches(',');
+ }
+ return createProperty(name, values, Type.fromTag(type, true));
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java Thu Oct 31 10:09:43 2013
@@ -294,7 +294,7 @@ public final class MongoNodeStore
backgroundThread.start();
}
- void dispose() {
+ public void dispose() {
// force background write (with asyncDelay > 0, the root wouldn't be written)
// TODO make this more obvious / explicit
// TODO tests should also work if this is not done
@@ -729,7 +729,12 @@ public final class MongoNodeStore
*/
@Nonnull
MongoNodeState getRoot(@Nonnull Revision revision) {
- return new MongoNodeState(this, "/", revision);
+ Node root = getNode("/", revision);
+ if (root == null) {
+ throw new IllegalStateException(
+ "root node does not exist at revision " + revision);
+ }
+ return new MongoNodeState(this, root);
}
@Nonnull
@@ -842,6 +847,18 @@ public final class MongoNodeStore
return rev;
}
+ /**
+ * Returns the {@link Blob} with the given blobId.
+ *
+ * @param blobId the blobId of the blob.
+ * @return the blob.
+ */
+ @Nonnull
+ Blob getBlob(String blobId) {
+ // TODO: implement blob handling
+ return null;
+ }
+
//------------------------< Observable >------------------------------------
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreBranch.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreBranch.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreBranch.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreBranch.java Thu Oct 31 10:09:43 2013
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.plugins.mongomk;
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.kernel.BlobSerializer;
import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher;
import org.apache.jackrabbit.oak.spi.state.AbstractNodeStoreBranch;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -26,6 +28,14 @@ import org.apache.jackrabbit.oak.spi.sta
public class MongoNodeStoreBranch
extends AbstractNodeStoreBranch<MongoNodeStore, MongoNodeState> {
+ private final BlobSerializer blobs = new BlobSerializer() {
+ @Override
+ public String serialize(Blob blob) {
+ // TODO: implement correct blob handling
+ return super.serialize(blob);
+ }
+ };
+
public MongoNodeStoreBranch(MongoNodeStore store,
MongoNodeState base) {
super(store, new ChangeDispatcher(store), base);
@@ -38,13 +48,13 @@ public class MongoNodeStoreBranch
@Override
protected MongoNodeState createBranch(MongoNodeState state) {
- return store.getRoot(state.getRevision().asBranchRevision());
+ return store.getRoot(state.getRevision().asBranchRevision()).setBranch();
}
@Override
protected MongoNodeState rebase(MongoNodeState branchHead,
MongoNodeState base) {
- return store.getRoot(store.rebase(branchHead.getRevision(), base.getRevision()));
+ return store.getRoot(store.rebase(branchHead.getRevision(), base.getRevision())).setBranch();
}
@Override
@@ -55,12 +65,16 @@ public class MongoNodeStoreBranch
@Override
protected MongoNodeState persist(final NodeState toPersist,
final MongoNodeState base) {
- return persist(new Changes() {
+ MongoNodeState state = persist(new Changes() {
@Override
public void with(Commit c) {
- toPersist.compareAgainstBaseState(base, new CommitDiff(c));
+ toPersist.compareAgainstBaseState(base, new CommitDiff(c, blobs));
}
}, base);
+ if (base.isBranch()) {
+ state.setBranch();
+ }
+ return state;
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/Node.java Thu Oct 31 10:09:43 2013
@@ -105,6 +105,14 @@ public class Node implements CacheValue
return op;
}
+ String getPath() {
+ return path;
+ }
+
+ Revision getReadRevision() {
+ return rev;
+ }
+
public String getId() {
return path + "@" + lastRevision;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/NodeDocument.java Thu Oct 31 10:09:43 2013
@@ -408,6 +408,7 @@ public class NodeDocument extends Docume
}
String path = Utils.getPathFromId(getId());
Node n = new Node(path, readRevision, hasChildren());
+ Revision lastRevision = min;
for (String key : keySet()) {
if (!Utils.isPropertyName(key)) {
continue;
@@ -423,11 +424,19 @@ public class NodeDocument extends Docume
String propertyName = Utils.unescapePropertyName(key);
String v = value != null ? value.value : null;
n.setProperty(propertyName, v);
+ // keep track of when this node was last modified
+ if (value != null && isRevisionNewer(context, value.revision, lastRevision)) {
+ lastRevision = value.revision;
+ }
}
+ // lastRevision now points to the revision when this node was
+ // last modified directly. but it may also have been 'modified'
+ // by an operation on a descendant node, which is tracked in
+ // _lastRev.
+
// when was this node last modified?
Branch branch = context.getBranches().getBranch(readRevision);
- Revision lastRevision = null;
Map<Integer, Revision> lastRevs = Maps.newHashMap(getLastRev());
// overlay with unsaved last modified from this instance
if (lastModified != null) {
@@ -447,9 +456,15 @@ public class NodeDocument extends Docume
for (Revision r : lastRevs.values()) {
// ignore if newer than readRevision
if (isRevisionNewer(context, r, readRevision)) {
+ // the node has a _lastRev which is newer than readRevision
+ // this means we don't know when if this node was
+ // modified by an operation on a descendant node between
+ // current lastRevision and readRevision. therefore we have
+ // to stay on the safe side and use readRevision
+ lastRevision = readRevision;
continue;
}
- if (lastRevision == null || isRevisionNewer(context, r, lastRevision)) {
+ if (isRevisionNewer(context, r, lastRevision)) {
lastRevision = r;
}
}
@@ -461,10 +476,6 @@ public class NodeDocument extends Docume
lastRevision = r;
}
}
- if (lastRevision == null) {
- // use readRevision if none found
- lastRevision = readRevision;
- }
n.setLastRevision(lastRevision);
return n;
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java Thu Oct 31 10:09:43 2013
@@ -24,6 +24,7 @@ import java.io.IOException;
import org.apache.jackrabbit.mk.core.MicroKernelImpl;
import org.apache.jackrabbit.oak.plugins.mongomk.MongoMK;
import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
+import org.apache.jackrabbit.oak.plugins.mongomk.MongoNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -72,6 +73,25 @@ public abstract class NodeStoreFixture {
}
};
+ public static final NodeStoreFixture MONGO_NS = new NodeStoreFixture() {
+ @Override
+ public String toString() {
+ return "MongoNS Fixture";
+ }
+
+ @Override
+ public NodeStore createNodeStore() {
+ return new MongoMK.Builder().getNodeStore();
+ }
+
+ @Override
+ public void dispose(NodeStore nodeStore) {
+ if (nodeStore instanceof MongoNodeStore) {
+ ((MongoNodeStore) nodeStore).dispose();
+ }
+ }
+ };
+
public static final NodeStoreFixture MK_IMPL = new NodeStoreFixture() {
@Override
public String toString() {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/SimpleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/SimpleTest.java?rev=1537423&r1=1537422&r2=1537423&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/SimpleTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/SimpleTest.java Thu Oct 31 10:09:43 2013
@@ -96,7 +96,7 @@ public class SimpleTest {
String rev4 = mk.commit("/test", "^\"a/x\":1", null, null);
String r0 = mk.getNodes("/", rev0, 0, 0, Integer.MAX_VALUE, ":id");
- assertEquals("{\":id\":\"/@r1-0-1\",\":childNodeCount\":0}", r0);
+ assertEquals("{\":id\":\"/@r0-0-1\",\":childNodeCount\":0}", r0);
String r1 = mk.getNodes("/", rev1, 0, 0, Integer.MAX_VALUE, ":id");
assertEquals("{\":id\":\"/@r2-0-1\",\"test\":{},\":childNodeCount\":1}", r1);
String r2 = mk.getNodes("/", rev2, 0, 0, Integer.MAX_VALUE, ":id");