Author: mreutegg
Date: Mon Aug 29 12:32:50 2016
New Revision: 1758213
URL: http://svn.apache.org/viewvc?rev=1758213&view=rev
Log:
OAK-4715: Reduce DocumentStore reads for local changes
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
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=1758213&r1=1758212&r2=1758213&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
Mon Aug 29 12:32:50 2016
@@ -1123,12 +1123,20 @@ public final class DocumentNodeStore
List<String> removed, List<String> changed,
DiffCache.Entry cacheEntry) {
if (isNew) {
+ // determine the revision for the nodeChildrenCache entry when
+ // the node is new. Fallback to after revision in case document
+ // is not in the cache. (OAK-4715)
+ NodeDocument doc = store.getIfCached(NODES, getIdFromPath(path));
+ RevisionVector afterLastRev = after;
+ if (doc != null) {
+ afterLastRev = new RevisionVector(doc.getLastRev().values());
+ afterLastRev = afterLastRev.update(rev);
+ }
if (added.isEmpty()) {
// this is a leaf node.
// check if it has the children flag set
- NodeDocument doc = store.find(NODES, getIdFromPath(path));
if (doc != null && doc.hasChildren()) {
- PathRev key = childNodeCacheKey(path, after, null);
+ PathRev key = childNodeCacheKey(path, afterLastRev, null);
LOG.debug("nodeChildrenCache.put({},{})", key,
"NO_CHILDREN");
nodeChildrenCache.put(key, DocumentNodeState.NO_CHILDREN);
}
@@ -1139,7 +1147,7 @@ public final class DocumentNodeStore
set.add(Utils.unshareString(PathUtils.getName(p)));
}
c.children.addAll(set);
- PathRev key = childNodeCacheKey(path, after, null);
+ PathRev key = childNodeCacheKey(path, afterLastRev, null);
LOG.debug("nodeChildrenCache.put({},{})", key, c);
nodeChildrenCache.put(key, c);
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1758213&r1=1758212&r2=1758213&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
Mon Aug 29 12:32:50 2016
@@ -76,6 +76,7 @@ import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.json.JsopDiff;
import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
import org.apache.jackrabbit.oak.plugins.commit.ConflictHook;
import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
@@ -2734,6 +2735,64 @@ public class DocumentNodeStoreTest {
}
}
+ // OAK-4715
+ @Test
+ public void localChangesFromCache() throws Exception {
+ final AtomicInteger numQueries = new AtomicInteger();
+ DocumentStore store = new MemoryDocumentStore() {
+ @Nonnull
+ @Override
+ public <T extends Document> List<T> query(Collection<T> collection,
+ String fromKey,
+ String toKey,
+ int limit) {
+ numQueries.incrementAndGet();
+ return super.query(collection, fromKey, toKey, limit);
+ }
+ };
+ DocumentNodeStore ns1 = builderProvider.newBuilder().setClusterId(1)
+ .setDocumentStore(store).getNodeStore();
+ NodeBuilder builder = ns1.getRoot().builder();
+ builder.child("node-1");
+ merge(ns1, builder);
+ ns1.runBackgroundOperations();
+ DocumentNodeStore ns2 = builderProvider.newBuilder().setClusterId(2)
+ .setDocumentStore(store).getNodeStore();
+ builder = ns2.getRoot().builder();
+ builder.child("node-2");
+ merge(ns2, builder);
+ ns2.runBackgroundOperations();
+ ns1.runBackgroundOperations();
+
+ NodeState before = ns1.getRoot();
+
+ builder = before.builder();
+ builder.child("node-1").child("foo").child("bar");
+ NodeState after = merge(ns1, builder);
+
+ numQueries.set(0);
+ JsopDiff.diffToJsop(before, after);
+ assertEquals(0, numQueries.get());
+
+ before = after;
+ builder = ns1.getRoot().builder();
+ builder.child("node-1").child("foo").child("bar").setProperty("p", 1);
+ after = merge(ns1, builder);
+
+ numQueries.set(0);
+ JsopDiff.diffToJsop(before, after);
+ assertEquals(0, numQueries.get());
+
+ before = after;
+ builder = ns1.getRoot().builder();
+ builder.child("node-1").child("foo").child("bar").remove();
+ after = merge(ns1, builder);
+
+ numQueries.set(0);
+ JsopDiff.diffToJsop(before, after);
+ assertEquals(0, numQueries.get());
+ }
+
private static class TestException extends RuntimeException {
}