Author: mreutegg
Date: Fri Feb 21 21:40:35 2014
New Revision: 1570718
URL: http://svn.apache.org/r1570718
Log:
OAK-1461: Merge DocumentNodeState with Node
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Node.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
Fri Feb 21 21:40:35 2014
@@ -110,7 +110,7 @@ public class Commit {
}
void addNodeDiff(Node n) {
- diff.tag('+').key(n.path);
+ diff.tag('+').key(n.getPath());
diff.object();
n.append(diff, false);
diff.endObject();
@@ -135,13 +135,14 @@ public class Commit {
}
void addNode(Node n) {
- if (operations.containsKey(n.path)) {
- String msg = "Node already added: " + n.path;
+ String path = n.getPath();
+ if (operations.containsKey(path)) {
+ String msg = "Node already added: " + path;
LOG.error(msg);
throw new MicroKernelException(msg);
}
- operations.put(n.path, n.asOperation(true));
- addedNodes.add(n.path);
+ operations.put(path, n.asOperation(true));
+ addedNodes.add(path);
}
boolean isEmpty() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/CommitDiff.java
Fri Feb 21 21:40:35 2014
@@ -36,6 +36,8 @@ import static org.apache.jackrabbit.oak.
*/
class CommitDiff implements NodeStateDiff {
+ private final DocumentNodeStore store;
+
private final Commit commit;
private final String path;
@@ -44,12 +46,15 @@ class CommitDiff implements NodeStateDif
private final BlobSerializer blobs;
- CommitDiff(@Nonnull Commit commit, @Nonnull BlobSerializer blobs) {
- this(checkNotNull(commit), "/", new JsopBuilder(),
checkNotNull(blobs));
+ CommitDiff(@Nonnull DocumentNodeStore store, @Nonnull Commit commit,
+ @Nonnull BlobSerializer blobs) {
+ this(checkNotNull(store), checkNotNull(commit), "/",
+ new JsopBuilder(), checkNotNull(blobs));
}
- private CommitDiff(Commit commit, String path,
+ private CommitDiff(DocumentNodeStore store, Commit commit, String path,
JsopBuilder builder, BlobSerializer blobs) {
+ this.store = store;
this.commit = commit;
this.path = path;
this.builder = builder;
@@ -77,9 +82,9 @@ class CommitDiff implements NodeStateDif
@Override
public boolean childNodeAdded(String name, NodeState after) {
String p = PathUtils.concat(path, name);
- commit.addNode(new Node(p, commit.getRevision()));
+ commit.addNode(new DocumentNodeState(store, p, commit.getRevision()));
return after.compareAgainstBaseState(EMPTY_NODE,
- new CommitDiff(commit, p, builder, blobs));
+ new CommitDiff(store, commit, p, builder, blobs));
}
@Override
@@ -88,7 +93,7 @@ class CommitDiff implements NodeStateDif
NodeState after) {
String p = PathUtils.concat(path, name);
return after.compareAgainstBaseState(before,
- new CommitDiff(commit, p, builder, blobs));
+ new CommitDiff(store, commit, p, builder, blobs));
}
@Override
@@ -96,7 +101,7 @@ class CommitDiff implements NodeStateDif
String p = PathUtils.concat(path, name);
commit.removeNode(p);
return MISSING_NODE.compareAgainstBaseState(before,
- new CommitDiff(commit, p, builder, blobs));
+ new CommitDiff(store, commit, p, builder, blobs));
}
//----------------------------< internal
>----------------------------------
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
Fri Feb 21 21:40:35 2014
@@ -416,8 +416,8 @@ public class DocumentMK implements Micro
}
}
- private static void parseAddNode(Commit commit, JsopReader t, String path)
{
- Node n = new Node(path, commit.getRevision());
+ private void parseAddNode(Commit commit, JsopReader t, String path) {
+ Node n = new DocumentNodeState(nodeStore, path, commit.getRevision());
if (!t.matches('}')) {
do {
String key = t.readString();
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
Fri Feb 21 21:40:35 2014
@@ -18,15 +18,22 @@ package org.apache.jackrabbit.oak.plugin
import java.util.Collections;
import java.util.Iterator;
+import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.commons.json.JsopReader;
import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.json.JsopWriter;
+import org.apache.jackrabbit.oak.kernel.JsonSerializer;
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder;
import org.apache.jackrabbit.oak.plugins.memory.ModifiedNodeState;
@@ -40,15 +47,15 @@ import org.apache.jackrabbit.oak.spi.sta
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
+import com.google.common.collect.Maps;
import static com.google.common.base.Preconditions.checkNotNull;
import static
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
/**
* A {@link NodeState} implementation for the {@link DocumentNodeStore}.
- * TODO: merge DocumentNodeState with Node
*/
-final class DocumentNodeState extends AbstractNodeState {
+class DocumentNodeState extends AbstractNodeState implements Node {
/**
* The number of child nodes to fetch initially.
@@ -68,24 +75,32 @@ final class DocumentNodeState extends Ab
private final DocumentNodeStore store;
- private final Node node;
+ final String path;
+ final Revision rev;
+ final Map<String, PropertyState> properties = Maps.newHashMap();
+ Revision lastRevision;
+ final boolean hasChildren;
/**
* TODO: OAK-1056
*/
private boolean isBranch;
- DocumentNodeState(@Nonnull DocumentNodeStore store, @Nonnull Node node) {
- this.store = checkNotNull(store);
- this.node = checkNotNull(node);
+ DocumentNodeState(@Nonnull DocumentNodeStore store, @Nonnull String path,
+ @Nonnull Revision rev) {
+ this(store, path, rev, false);
}
- String getPath() {
- return node.getPath();
+ DocumentNodeState(@Nonnull DocumentNodeStore store, @Nonnull String path,
+ @Nonnull Revision rev, boolean hasChildren) {
+ this.store = checkNotNull(store);
+ this.path = checkNotNull(path);
+ this.rev = checkNotNull(rev);
+ this.hasChildren = hasChildren;
}
Revision getRevision() {
- return node.getReadRevision();
+ return rev;
}
DocumentNodeState setBranch() {
@@ -106,7 +121,7 @@ final class DocumentNodeState extends Ab
} else if (that instanceof DocumentNodeState) {
DocumentNodeState other = (DocumentNodeState) that;
if (getPath().equals(other.getPath())) {
- return
node.getLastRevision().equals(other.node.getLastRevision());
+ return lastRevision.equals(other.lastRevision);
}
} else if (that instanceof ModifiedNodeState) {
ModifiedNodeState modified = (ModifiedNodeState) that;
@@ -128,66 +143,57 @@ final class DocumentNodeState extends Ab
@Override
public PropertyState getProperty(String name) {
- String value = node.getProperty(name);
- if (value == null) {
- return null;
- }
- return new DocumentPropertyState(store, name, value);
+ return properties.get(name);
}
@Override
public boolean hasProperty(String name) {
- return node.getPropertyNames().contains(name);
+ return properties.containsKey(name);
}
@Nonnull
@Override
public Iterable<? extends PropertyState> getProperties() {
- return Iterables.transform(node.getPropertyNames(), new
Function<String, PropertyState>() {
- @Override
- public PropertyState apply(String name) {
- return getProperty(name);
- }
- });
+ return properties.values();
}
@Override
public boolean hasChildNode(String name) {
- if (node.hasNoChildren() || !isValidName(name)) {
+ if (!hasChildren || !isValidName(name)) {
return false;
} else {
String p = PathUtils.concat(getPath(), name);
- return store.getNode(p, node.getLastRevision()) != null;
+ return store.getNode(p, lastRevision) != null;
}
}
@Nonnull
@Override
public NodeState getChildNode(@Nonnull String name) {
- if (node.hasNoChildren()) {
+ if (!hasChildren) {
checkValidName(name);
return EmptyNodeState.MISSING_NODE;
}
String p = PathUtils.concat(getPath(), name);
- Node child = store.getNode(p, node.getLastRevision());
+ DocumentNodeState child = store.getNode(p, lastRevision);
if (child == null) {
checkValidName(name);
return EmptyNodeState.MISSING_NODE;
} else {
- return new DocumentNodeState(store, child);
+ return child;
}
}
@Override
public long getChildNodeCount(long max) {
- if (node.hasNoChildren()) {
+ if (!hasChildren) {
return 0;
}
if (max > DocumentNodeStore.NUM_CHILDREN_CACHE_LIMIT) {
// count all
return Iterators.size(new ChildNodeEntryIterator());
}
- Node.Children c = store.getChildren(node, null, (int) max);
+ Node.Children c = store.getChildren(this, null, (int) max);
if (c.hasMore) {
return Long.MAX_VALUE;
} else {
@@ -199,7 +205,7 @@ final class DocumentNodeState extends Ab
@Nonnull
@Override
public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
- if (node.hasNoChildren()) {
+ if (!hasChildren) {
return Collections.emptyList();
}
return new Iterable<ChildNodeEntry>() {
@@ -233,12 +239,12 @@ final class DocumentNodeState extends Ab
DocumentNodeState mBase = (DocumentNodeState) base;
if (store == mBase.store) {
if (getPath().equals(mBase.getPath())) {
- if
(node.getLastRevision().equals(mBase.node.getLastRevision())) {
+ if (lastRevision.equals(mBase.lastRevision)) {
// no differences
return true;
} else if (getChildNodeCount(LOCAL_DIFF_THRESHOLD) >
LOCAL_DIFF_THRESHOLD) {
// use DocumentNodeStore compare when there are many
children
- return dispatch(store.diffChildren(this.node,
mBase.node), mBase, diff);
+ return dispatch(store.diffChildren(this, mBase),
mBase, diff);
}
}
}
@@ -247,6 +253,131 @@ final class DocumentNodeState extends Ab
return super.compareAgainstBaseState(base, diff);
}
+ //----------------------------< Node
>--------------------------------------
+
+ @Override
+ public void setProperty(String propertyName, String value) {
+ if (value == null) {
+ properties.remove(propertyName);
+ } else {
+ properties.put(propertyName,
+ new DocumentPropertyState(store, propertyName, value));
+ }
+ }
+
+ @Override
+ public void setProperty(PropertyState property) {
+ properties.put(property.getName(), property);
+ }
+
+ @Override
+ public String getPropertyAsString(String propertyName) {
+ PropertyState prop = properties.get(propertyName);
+ if (prop == null) {
+ return null;
+ }
+ JsopBuilder builder = new JsopBuilder();
+ new JsonSerializer(builder, store.getBlobSerializer()).serialize(prop);
+ return builder.toString();
+ }
+
+ @Override
+ public Set<String> getPropertyNames() {
+ return properties.keySet();
+ }
+
+ @Override
+ public void copyTo(Node newNode) {
+ for (Map.Entry<String, PropertyState> entry : properties.entrySet()) {
+ newNode.setProperty(entry.getValue());
+ }
+ }
+
+ @Override
+ public boolean hasNoChildren() {
+ return !hasChildren;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+ buff.append("path: ").append(path).append('\n');
+ buff.append("rev: ").append(rev).append('\n');
+ buff.append(properties);
+ buff.append('\n');
+ return buff.toString();
+ }
+
+ /**
+ * Create an add node operation for this node.
+ */
+ @Override
+ public UpdateOp asOperation(boolean isNew) {
+ String id = Utils.getIdFromPath(path);
+ UpdateOp op = new UpdateOp(id, isNew);
+ op.set(Document.ID, id);
+ NodeDocument.setModified(op, rev);
+ NodeDocument.setDeleted(op, rev, false);
+ for (String p : properties.keySet()) {
+ String key = Utils.escapePropertyName(p);
+ op.setMapEntry(key, rev, getPropertyAsString(p));
+ }
+ return op;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public String getId() {
+ return path + "@" + lastRevision;
+ }
+
+ @Override
+ public void append(JsopWriter json, boolean includeId) {
+ if (includeId) {
+ json.key(":id").value(getId());
+ }
+ for (String p : properties.keySet()) {
+ json.key(p).encodedValue(getPropertyAsString(p));
+ }
+ }
+
+ @Override
+ public void setLastRevision(Revision lastRevision) {
+ this.lastRevision = lastRevision;
+ }
+
+ @Override
+ public Revision getLastRevision() {
+ return lastRevision;
+ }
+
+ @Override
+ public int getMemory() {
+ int size = 180 + path.length() * 2;
+ // rough approximation for properties
+ for (Map.Entry<String, PropertyState> entry : properties.entrySet()) {
+ // name
+ size += 48 + entry.getKey().length() * 2;
+ PropertyState propState = entry.getValue();
+ if (propState.getType() != Type.BINARY
+ && propState.getType() != Type.BINARIES) {
+ // assume binaries go into blob store
+ for (int i = 0; i < propState.count(); i++) {
+ // size() returns length of string
+ // overhead:
+ // - 8 bytes per reference in values list
+ // - 48 bytes per string
+ size += 56 + propState.size(i) * 2;
+ }
+ }
+ }
+ return size;
+ }
+
//------------------------------< internal
>--------------------------------
private boolean dispatch(@Nonnull String jsonDiff,
@@ -338,21 +469,21 @@ final class DocumentNodeState extends Ab
@Nonnull
private Iterable<ChildNodeEntry> getChildNodeEntries(@Nullable String name,
int limit) {
- Iterable<Node> children = store.getChildNodes(node, name, limit);
- return Iterables.transform(children, new Function<Node,
ChildNodeEntry>() {
+ Iterable<DocumentNodeState> children = store.getChildNodes(this, name,
limit);
+ return Iterables.transform(children, new Function<DocumentNodeState,
ChildNodeEntry>() {
@Override
- public ChildNodeEntry apply(final Node input) {
+ public ChildNodeEntry apply(final DocumentNodeState input) {
return new AbstractChildNodeEntry() {
@Nonnull
@Override
public String getName() {
- return PathUtils.getName(input.path);
+ return PathUtils.getName(input.getPath());
}
@Nonnull
@Override
public NodeState getNodeState() {
- return new DocumentNodeState(store, input);
+ return input;
}
};
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
Fri Feb 21 21:40:35 2014
@@ -55,6 +55,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.spi.blob.BlobStore;
import org.apache.jackrabbit.oak.commons.json.JsopStream;
import org.apache.jackrabbit.oak.commons.json.JsopWriter;
@@ -84,7 +85,7 @@ import org.slf4j.LoggerFactory;
*/
public final class DocumentNodeStore
implements NodeStore, RevisionContext, Observable {
-
+
private static final Logger LOG =
LoggerFactory.getLogger(DocumentNodeStore.class);
/**
@@ -116,6 +117,11 @@ public final class DocumentNodeStore
protected final DocumentStore store;
/**
+ * Marker node, indicating a node does not exist at a given revision.
+ */
+ protected final DocumentNodeState missing;
+
+ /**
* The commit queue to coordinate the commits.
*/
protected final CommitQueue commitQueue;
@@ -218,9 +224,9 @@ public final class DocumentNodeStore
/**
* The node cache.
*
- * Key: PathRev, value: Node
+ * Key: PathRev, value: DocumentNodeState
*/
- private final Cache<CacheValue, Node> nodeCache;
+ private final Cache<CacheValue, DocumentNodeState> nodeCache;
private final CacheStats nodeCacheStats;
/**
@@ -299,6 +305,12 @@ public final class DocumentNodeStore
this.revisionComparator = new Revision.RevisionComparator(clusterId);
this.branches = new UnmergedBranches(getRevisionComparator());
this.asyncDelay = builder.getAsyncDelay();
+ this.missing = new DocumentNodeState(this, "MISSING", new Revision(0,
0, 0)) {
+ @Override
+ public int getMemory() {
+ return 8;
+ }
+ };
//TODO Make stats collection configurable as it add slight overhead
@@ -323,7 +335,7 @@ public final class DocumentNodeStore
// root node is missing: repository is not initialized
Revision head = newRevision();
Commit commit = new Commit(this, null, head);
- Node n = new Node("/", head);
+ Node n = new DocumentNodeState(this, "/", head);
commit.addNode(n);
commit.applyToDocumentStore();
// use dummy Revision as before
@@ -570,21 +582,21 @@ public final class DocumentNodeStore
* given revision.
*/
@CheckForNull
- Node getNode(@Nonnull final String path, @Nonnull final Revision rev) {
+ DocumentNodeState getNode(@Nonnull final String path, @Nonnull final
Revision rev) {
checkRevisionAge(checkNotNull(rev), checkNotNull(path));
try {
PathRev key = new PathRev(path, rev);
- Node node = nodeCache.get(key, new Callable<Node>() {
+ DocumentNodeState node = nodeCache.get(key, new
Callable<DocumentNodeState>() {
@Override
- public Node call() throws Exception {
- Node n = readNode(path, rev);
+ public DocumentNodeState call() throws Exception {
+ DocumentNodeState n = readNode(path, rev);
if (n == null) {
- n = Node.MISSING;
+ n = missing;
}
return n;
}
});
- return node == Node.MISSING ? null : node;
+ return node == missing ? null : node;
} catch (ExecutionException e) {
throw new MicroKernelException(e);
}
@@ -755,9 +767,9 @@ public final class DocumentNodeStore
* @return the child nodes.
*/
@Nonnull
- Iterable<Node> getChildNodes(final @Nonnull Node parent,
- final @Nullable String name,
- final int limit) {
+ Iterable<DocumentNodeState> getChildNodes(final @Nonnull Node parent,
+ final @Nullable String name,
+ final int limit) {
// Preemptive check. If we know there are no children then
// return straight away
if (checkNotNull(parent).hasNoChildren()) {
@@ -766,16 +778,16 @@ public final class DocumentNodeStore
final Revision readRevision = parent.getLastRevision();
return Iterables.transform(getChildren(parent, name, limit).children,
- new Function<String, Node>() {
+ new Function<String, DocumentNodeState>() {
@Override
- public Node apply(String input) {
+ public DocumentNodeState apply(String input) {
return getNode(input, readRevision);
}
});
}
@CheckForNull
- Node readNode(String path, Revision readRevision) {
+ DocumentNodeState readNode(String path, Revision readRevision) {
String id = Utils.getIdFromPath(path);
Revision lastRevision = getPendingModifications().get(path);
NodeDocument doc = store.find(Collection.NODES, id);
@@ -935,12 +947,12 @@ public final class DocumentNodeStore
*/
@Nonnull
DocumentNodeState getRoot(@Nonnull Revision revision) {
- Node root = getNode("/", revision);
+ DocumentNodeState root = getNode("/", revision);
if (root == null) {
throw new IllegalStateException(
"root node does not exist at revision " + revision);
}
- return new DocumentNodeState(this, root);
+ return root;
}
@Nonnull
@@ -1091,7 +1103,8 @@ public final class DocumentNodeStore
* @param base the base node to compare against.
* @return the json diff.
*/
- String diffChildren(final @Nonnull Node node, final @Nonnull Node base) {
+ String diffChildren(final @Nonnull DocumentNodeState node,
+ final @Nonnull DocumentNodeState base) {
PathRev key = diffCacheKey(node.getPath(),
base.getLastRevision(), node.getLastRevision());
try {
@@ -1118,8 +1131,8 @@ public final class DocumentNodeStore
}
Revision fromRev = Revision.fromString(fromRevisionId);
Revision toRev = Revision.fromString(toRevisionId);
- final Node from = getNode(path, fromRev);
- final Node to = getNode(path, toRev);
+ final DocumentNodeState from = getNode(path, fromRev);
+ final DocumentNodeState to = getNode(path, toRev);
if (from == null || to == null) {
// TODO implement correct behavior if the node does't/didn't exist
String msg = String.format("Diff is only supported if the node
exists in both cases. " +
@@ -1379,30 +1392,32 @@ public final class DocumentNodeStore
//-----------------------------< internal
>---------------------------------
- private static void diffProperties(Node from, Node to, JsopWriter w) {
- for (String name : from.getPropertyNames()) {
+ private static void diffProperties(DocumentNodeState from,
+ DocumentNodeState to,
+ JsopWriter w) {
+ for (PropertyState fromValue : from.getProperties()) {
+ String name = fromValue.getName();
// changed or removed properties
- String fromValue = from.getProperty(name);
- String toValue = to.getProperty(name);
+ PropertyState toValue = to.getProperty(name);
if (!fromValue.equals(toValue)) {
w.tag('^').key(PathUtils.concat(from.getPath(), name));
if (toValue == null) {
w.value(null);
} else {
- w.encodedValue(toValue).newline();
+ w.encodedValue(to.getPropertyAsString(name)).newline();
}
}
}
for (String name : to.getPropertyNames()) {
// added properties
- if (from.getProperty(name) == null) {
+ if (!from.hasProperty(name)) {
w.tag('^').key(PathUtils.concat(from.getPath(), name))
- .encodedValue(to.getProperty(name)).newline();
+ .encodedValue(to.getPropertyAsString(name)).newline();
}
}
}
- private String diffImpl(Node from, Node to)
+ private String diffImpl(DocumentNodeState from, DocumentNodeState to)
throws MicroKernelException {
JsopWriter w = new JsopStream();
diffProperties(from, to, w);
@@ -1554,7 +1569,7 @@ public final class DocumentNodeStore
// of this commit i.e. transient nodes. If its required it would need
to be looked
// into
- Node newNode = new Node(targetPath, commit.getRevision());
+ Node newNode = new DocumentNodeState(this, targetPath,
commit.getRevision());
source.copyTo(newNode);
commit.addNode(newNode);
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
Fri Feb 21 21:40:35 2014
@@ -86,7 +86,7 @@ public class DocumentNodeStoreBranch
@Override
public void with(Commit c) {
toPersist.compareAgainstBaseState(base,
- new CommitDiff(c, store.getBlobSerializer()));
+ new CommitDiff(store, c, store.getBlobSerializer()));
}
}, base, info);
if (base.isBranch()) {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Node.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Node.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Node.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Node.java
Fri Feb 21 21:40:35 2014
@@ -17,138 +17,47 @@
package org.apache.jackrabbit.oak.plugins.document;
import java.util.ArrayList;
-import java.util.Map;
import java.util.Set;
-import java.util.Map.Entry;
-import org.apache.jackrabbit.oak.commons.json.JsopWriter;
+import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.cache.CacheValue;
-import org.apache.jackrabbit.oak.plugins.document.util.Utils;
+import org.apache.jackrabbit.oak.commons.json.JsopWriter;
/**
* Represents a node held in memory (in the cache for example).
*/
-public class Node implements CacheValue {
- /**
- * A node, which does not exist at a given revision.
- */
- static final Node MISSING = new Node(null, null) {
- @Override
- public int getMemory() {
- return 8;
- }
- };
+public interface Node extends CacheValue {
- final String path;
- final Revision rev;
- final Map<String, String> properties = Utils.newMap();
- Revision lastRevision;
- final boolean hasChildren;
-
- Node(String path, Revision rev) {
- this(path, rev, false);
- }
+ Children NO_CHILDREN = new Children();
- Node(String path, Revision rev, boolean hasChildren) {
- this.path = path;
- this.rev = rev;
- this.hasChildren = hasChildren;
- }
-
- void setProperty(String propertyName, String value) {
- if (value == null) {
- properties.remove(propertyName);
- } else {
- properties.put(propertyName, value);
- }
- }
-
- public String getProperty(String propertyName) {
- return properties.get(propertyName);
- }
-
- public Set<String> getPropertyNames() {
- return properties.keySet();
- }
+ String getPropertyAsString(String propertyName);
- public void copyTo(Node newNode) {
- newNode.properties.putAll(properties);
- }
+ void setProperty(String propertyName, String value);
- public boolean hasNoChildren() {
- return !hasChildren;
- }
+ void setProperty(PropertyState property);
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder();
- buff.append("path: ").append(path).append('\n');
- buff.append("rev: ").append(rev).append('\n');
- buff.append(properties);
- buff.append('\n');
- return buff.toString();
- }
-
- /**
- * Create an add node operation for this node.
- */
- UpdateOp asOperation(boolean isNew) {
- String id = Utils.getIdFromPath(path);
- UpdateOp op = new UpdateOp(id, isNew);
- op.set(Document.ID, id);
- NodeDocument.setModified(op, rev);
- NodeDocument.setDeleted(op, rev, false);
- for (String p : properties.keySet()) {
- String key = Utils.escapePropertyName(p);
- op.setMapEntry(key, rev, properties.get(p));
- }
- return op;
- }
+ Set<String> getPropertyNames();
- String getPath() {
- return path;
- }
+ void copyTo(Node newNode);
- Revision getReadRevision() {
- return rev;
- }
+ boolean hasNoChildren();
- public String getId() {
- return path + "@" + lastRevision;
- }
+ String getId();
- public void append(JsopWriter json, boolean includeId) {
- if (includeId) {
- json.key(":id").value(getId());
- }
- for (String p : properties.keySet()) {
- json.key(p).encodedValue(properties.get(p));
- }
- }
+ void append(JsopWriter json, boolean includeId);
- public void setLastRevision(Revision lastRevision) {
- this.lastRevision = lastRevision;
- }
+ void setLastRevision(Revision lastRevision);
- public Revision getLastRevision() {
- return lastRevision;
- }
-
- @Override
- public int getMemory() {
- int size = 180 + path.length() * 2;
- for (Entry<String, String> e : properties.entrySet()) {
- size += 136 + e.getKey().length() * 2 + e.getValue().length() * 2;
- }
- return size;
- }
+ Revision getLastRevision();
- static final Children NO_CHILDREN = new Children();
+ String getPath();
+
+ UpdateOp asOperation(boolean isNew);
/**
* A list of children for a node.
*/
- static class Children implements CacheValue {
+ public static class Children implements CacheValue {
final ArrayList<String> children = new ArrayList<String>();
boolean hasMore;
@@ -166,7 +75,5 @@ public class Node implements CacheValue
public String toString() {
return children.toString();
}
-
}
-
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
Fri Feb 21 21:40:35 2014
@@ -451,9 +451,10 @@ public class NodeDocument extends Docume
}
/**
- * Returns a {@link Node} as seen at the given <code>readRevision</code>.
+ * Returns a {@link DocumentNodeState} as seen at the given
+ * <code>readRevision</code>.
*
- * @param context the revision context.
+ * @param nodeStore the node store.
* @param readRevision the read revision.
* @param lastModified the revision when this node was last modified, but
* the value is potentially not yet reflected in this
@@ -463,35 +464,35 @@ public class NodeDocument extends Docume
* given read revision.
*/
@CheckForNull
- public Node getNodeAtRevision(@Nonnull RevisionContext context,
- @Nonnull Revision readRevision,
- @Nullable Revision lastModified) {
+ public DocumentNodeState getNodeAtRevision(@Nonnull DocumentNodeStore
nodeStore,
+ @Nonnull Revision readRevision,
+ @Nullable Revision
lastModified) {
Set<Revision> validRevisions = new HashSet<Revision>();
- Revision min = getLiveRevision(context, readRevision, validRevisions);
+ Revision min = getLiveRevision(nodeStore, readRevision,
validRevisions);
if (min == null) {
// deleted
return null;
}
String path = Utils.getPathFromId(getId());
- Node n = new Node(path, readRevision, hasChildren());
+ DocumentNodeState n = new DocumentNodeState(nodeStore, path,
readRevision, hasChildren());
Revision lastRevision = min;
for (String key : keySet()) {
if (!Utils.isPropertyName(key)) {
continue;
}
// first check local map, which contains most recent values
- Value value = getLatestValue(context, getLocalMap(key),
+ Value value = getLatestValue(nodeStore, getLocalMap(key),
min, readRevision, validRevisions);
if (value == null && !getPreviousRanges().isEmpty()) {
// check complete revision history
- value = getLatestValue(context, getValueMap(key),
+ value = getLatestValue(nodeStore, getValueMap(key),
min, readRevision, validRevisions);
}
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)) {
+ if (value != null && isRevisionNewer(nodeStore, value.revision,
lastRevision)) {
lastRevision = value.revision;
}
}
@@ -502,11 +503,11 @@ public class NodeDocument extends Docume
// _lastRev.
// when was this node last modified?
- Branch branch = context.getBranches().getBranch(readRevision);
+ Branch branch = nodeStore.getBranches().getBranch(readRevision);
Map<Integer, Revision> lastRevs = Maps.newHashMap(getLastRev());
// overlay with unsaved last modified from this instance
if (lastModified != null) {
- lastRevs.put(context.getClusterId(), lastModified);
+ lastRevs.put(nodeStore.getClusterId(), lastModified);
}
Revision branchBase = null;
if (branch != null) {
@@ -514,7 +515,7 @@ public class NodeDocument extends Docume
}
for (Revision r : lastRevs.values()) {
// ignore if newer than readRevision
- if (isRevisionNewer(context, r, readRevision)) {
+ if (isRevisionNewer(nodeStore, r, readRevision)) {
// the node has a _lastRev which is newer than readRevision
// this means we don't know when this node was
// modified by an operation on a descendant node between
@@ -522,7 +523,7 @@ public class NodeDocument extends Docume
// to stay on the safe side and use readRevision
lastRevision = readRevision;
continue;
- } else if (branchBase != null && isRevisionNewer(context, r,
branchBase)) {
+ } else if (branchBase != null && isRevisionNewer(nodeStore, r,
branchBase)) {
// readRevision is on a branch and the node has a
// _lastRev which is newer than the base of the branch
// we cannot use this _lastRev because it is not visible
@@ -530,7 +531,7 @@ public class NodeDocument extends Docume
// changes is the base of the branch
r = branchBase;
}
- if (isRevisionNewer(context, r, lastRevision)) {
+ if (isRevisionNewer(nodeStore, r, lastRevision)) {
lastRevision = r;
}
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterTest.java
Fri Feb 21 21:40:35 2014
@@ -36,6 +36,8 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -109,8 +111,12 @@ public class ClusterTest {
String r1b = mk1.getHeadRevision();
String n1b = mk1.getNodes("/test", r1b, 0, 0, 10, null);
+ JSONParser parser = new JSONParser();
+ JSONObject obj = (JSONObject) parser.parse(n1b);
// mk1 now sees both changes
- assertEquals("{\"x\":1,\"y\":2,\":childNodeCount\":0}", n1b);
+ assertEquals(1L, obj.get("x"));
+ assertEquals(2L, obj.get("y"));
+ assertEquals(0L, obj.get(":childNodeCount"));
mk1.dispose();
mk2.dispose();
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentSplitTest.java
Fri Feb 21 21:40:35 2014
@@ -262,7 +262,7 @@ public class DocumentSplitTest extends B
Revision lastRev = ns.getPendingModifications().get("/test");
Node n = doc.getNodeAtRevision(mk.getNodeStore(), head, lastRev);
assertNotNull(n);
- String value = n.getProperty(name);
+ String value = n.getPropertyAsString(name);
// set or increment
if (value == null) {
value = String.valueOf(0);
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MeasureMemory.java
Fri Feb 21 21:40:35 2014
@@ -36,6 +36,9 @@ public class MeasureMemory {
static final int TEST_COUNT = 10000;
static final int OVERHEAD = 24;
+ static final DocumentNodeStore STORE = new DocumentMK.Builder()
+ .setAsyncDelay(0).getNodeStore();
+
@Test
public void overhead() throws Exception {
measureMemory(new Callable<Object[]>() {
@@ -150,9 +153,10 @@ public class MeasureMemory {
}
static Node generateNode(int propertyCount) {
- Node n = new Node(new String("/hello/world"), new Revision(1, 2, 3));
+ Node n = new DocumentNodeState(STORE, new String("/hello/world"),
+ new Revision(1, 2, 3));
for (int i = 0; i < propertyCount; i++) {
- n.setProperty("property" + i, "values " + i);
+ n.setProperty("property" + i, "\"values " + i + "\"");
}
n.setLastRevision(new Revision(1, 2, 3));
return n;
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoDocumentStoreTest.java
Fri Feb 21 21:40:35 2014
@@ -190,10 +190,12 @@ public class MongoDocumentStoreTest {
@Test
public void queryWithLimit() throws Exception {
DocumentStore docStore = openDocumentStore();
+ DocumentNodeStore store = new DocumentMK.Builder()
+ .setDocumentStore(docStore).setAsyncDelay(0).getNodeStore();
Revision rev = Revision.newRevision(0);
List<UpdateOp> inserts = new ArrayList<UpdateOp>();
for (int i = 0; i < DocumentMK.MANY_CHILDREN_THRESHOLD * 2; i++) {
- Node n = new Node("/node-" + i, rev);
+ Node n = new DocumentNodeState(store, "/node-" + i, rev);
inserts.add(n.asOperation(true));
}
docStore.create(Collection.NODES, inserts);
@@ -201,6 +203,7 @@ public class MongoDocumentStoreTest {
Utils.getKeyLowerLimit("/"), Utils.getKeyUpperLimit("/"),
DocumentMK.MANY_CHILDREN_THRESHOLD);
assertEquals(DocumentMK.MANY_CHILDREN_THRESHOLD, docs.size());
+ store.dispose();
}
@Test
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java?rev=1570718&r1=1570717&r2=1570718&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/SimpleTest.java
Fri Feb 21 21:40:35 2014
@@ -26,6 +26,8 @@ import static org.junit.Assert.fail;
import java.util.Random;
import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.plugins.document.Node.Children;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
@@ -71,17 +73,20 @@ public class SimpleTest {
@Test
public void addNodeGetNode() {
DocumentMK mk = new DocumentMK.Builder().open();
+ DocumentStore s = mk.getDocumentStore();
+ DocumentNodeStore ns = mk.getNodeStore();
Revision rev = Revision.fromString(mk.getHeadRevision());
- Node n = new Node("/test", rev);
- n.setProperty("name", "Hello");
+ DocumentNodeState n = new DocumentNodeState(ns, "/test", rev);
+ n.setProperty("name", "\"Hello\"");
UpdateOp op = n.asOperation(true);
// mark as commit root
NodeDocument.setRevision(op, rev, "c");
- DocumentStore s = mk.getDocumentStore();
- DocumentNodeStore ns = mk.getNodeStore();
assertTrue(s.create(Collection.NODES, Lists.newArrayList(op)));
- Node n2 = ns.getNode("/test", rev);
- assertEquals("Hello", n2.getProperty("name"));
+ DocumentNodeState n2 = ns.getNode("/test", rev);
+ assertNotNull(n2);
+ PropertyState p = n2.getProperty("name");
+ assertNotNull(p);
+ assertEquals("Hello", p.getValue(Type.STRING));
mk.dispose();
}