diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java index 4d83e1c..6cf259a 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; @@ -347,7 +348,23 @@ public class NodeDocumentCache implements Closeable { }, changeTrackers); } - /** + /** + * Registers a new CacheChangesTracker that records all puts and + * invalidations related to the given documents + * + * @param keys these documents will be tracked + * @return new tracker + */ + public CacheChangesTracker registerTracker(final Set keys) { + return new CacheChangesTracker(new Predicate() { + @Override + public boolean apply(@Nullable String input) { + return input != null && keys.contains(input); + } + }, changeTrackers); + } + + /** * Updates the cache with all the documents that: * * (1) currently have their older versions in the cache or @@ -366,7 +383,7 @@ public class NodeDocumentCache implements Closeable { * @param docs * to put into cache */ - public void putNonConflictingDocs(CacheChangesTracker tracker, List docs) { + public void putNonConflictingDocs(CacheChangesTracker tracker, Iterable docs) { for (NodeDocument d : docs) { if (d == null || d == NodeDocument.NULL) { continue; diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java index 1338177..e3ac306 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java @@ -907,29 +907,30 @@ public class MongoDocumentStore implements DocumentStore { Set lackingDocs = difference(bulkOperations.keySet(), oldDocs.keySet()); oldDocs.putAll(findDocuments(collection, lackingDocs)); - Lock lock = null; + CacheChangesTracker tracker = null; if (collection == Collection.NODES) { - lock = nodeLocks.acquire(bulkOperations.keySet()); + tracker = nodesCache.registerTracker(bulkOperations.keySet()); } try { BulkUpdateResult bulkResult = sendBulkUpdate(collection, bulkOperations.values(), oldDocs); if (collection == Collection.NODES) { + List docsToCache = new ArrayList(); for (UpdateOp op : filterKeys(bulkOperations, in(bulkResult.upserts)).values()) { NodeDocument doc = Collection.NODES.newDocument(this); UpdateUtils.applyChanges(doc, op); - nodesCache.put(doc); + docsToCache.add(doc); } for (String key : difference(bulkOperations.keySet(), bulkResult.failedUpdates)) { T oldDoc = oldDocs.get(key); if (oldDoc != null) { NodeDocument newDoc = (NodeDocument) applyChanges(collection, oldDoc, bulkOperations.get(key)); - nodesCache.put(newDoc); - oldDoc.seal(); + docsToCache.add(newDoc); } } + nodesCache.putNonConflictingDocs(tracker, docsToCache); } oldDocs.keySet().removeAll(bulkResult.failedUpdates); @@ -945,8 +946,8 @@ public class MongoDocumentStore implements DocumentStore { } return result; } finally { - if (lock != null) { - lock.unlock(); + if (tracker != null) { + tracker.close(); } } } diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java index 38e60d4..03debc4 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java @@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.plugins.document.cache; import com.google.common.base.Predicate; import com.google.common.cache.Cache; +import com.google.common.collect.ImmutableSet; import org.apache.jackrabbit.oak.cache.CacheStats; import org.apache.jackrabbit.oak.cache.CacheValue; import org.apache.jackrabbit.oak.plugins.document.Collection; @@ -97,7 +98,31 @@ public class CacheChangesTrackerTest { assertFalse(tracker.mightBeenAffected("2:/parent/123")); } - private NodeDocumentCache createCache() { + @Test + public void testRegisterKeysTracker() { + NodeDocumentCache cache = createCache(); + CacheChangesTracker tracker = cache.registerTracker(ImmutableSet.of("1:/xyz", "1:/abc", "1:/aaa")); + + assertFalse(tracker.mightBeenAffected("1:/xyz")); + assertFalse(tracker.mightBeenAffected("1:/abc")); + assertFalse(tracker.mightBeenAffected("1:/aaa")); + + cache.put(createDoc("1:/xyz")); + assertTrue(tracker.mightBeenAffected("1:/xyz")); + + cache.invalidate("1:/abc"); + assertTrue(tracker.mightBeenAffected("1:/abc")); + + cache.invalidate("1:/other"); + assertFalse(tracker.mightBeenAffected("1:/other")); + + tracker.close(); + + cache.invalidate("1:/aaa"); + assertFalse(tracker.mightBeenAffected("1:/aaa")); + } + + private NodeDocumentCache createCache() { Cache nodeDocumentsCache = Mockito.mock(Cache.class); Cache prevDocumentsCache = Mockito.mock(Cache.class); CacheStats nodeDocumentsCacheStats = Mockito.mock(CacheStats.class);