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 to...@apache.org on 2016/04/28 12:02:41 UTC
svn commit: r1741403 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/document/cache/
main/java/org/apache/jackrabbit/oak/plugins/document/locks/
main/java/org/apache/jackrabbit/oak/plugins/document/mongo/ test/java/...
Author: tomekr
Date: Thu Apr 28 10:02:41 2016
New Revision: 1741403
URL: http://svn.apache.org/viewvc?rev=1741403&view=rev
Log:
OAK-4112: Replace the query exclusive lock with a cache tracker
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTracker.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/BulkReadWriteLock.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/TreeNodeDocumentLocks.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/TreeNodeDocumentsLocksTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/NodeDocumentLocksTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTracker.java?rev=1741403&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTracker.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTracker.java Thu Apr 28 10:02:41 2016
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.document.cache;
+
+import com.google.common.base.Predicate;
+import com.google.common.hash.BloomFilter;
+import com.google.common.hash.Funnel;
+import com.google.common.hash.PrimitiveSink;
+
+import java.util.List;
+
+public class CacheChangesTracker {
+
+ private final List<CacheChangesTracker> changeTrackers;
+
+ private final Predicate<String> keyFilter;
+
+ private final LazyBloomFilter lazyBloomFilter;
+
+ CacheChangesTracker(Predicate<String> keyFilter, List<CacheChangesTracker> changeTrackers) {
+ this.changeTrackers = changeTrackers;
+ this.keyFilter = keyFilter;
+ this.lazyBloomFilter = new LazyBloomFilter();
+ changeTrackers.add(this);
+ }
+
+ public void putDocument(String key) {
+ if (keyFilter.apply(key)) {
+ lazyBloomFilter.put(key);
+ }
+ }
+
+ public void invalidateDocument(String key) {
+ if (keyFilter.apply(key)) {
+ lazyBloomFilter.put(key);
+ }
+ }
+
+ public boolean mightBeenAffected(String key) {
+ return keyFilter.apply(key) && lazyBloomFilter.mightContain(key);
+ }
+
+ public void close() {
+ changeTrackers.remove(this);
+ }
+
+ public static class LazyBloomFilter {
+
+ private static final double FPP = 0.01d;
+
+ private static final int ENTRIES = 1000;
+
+ private volatile BloomFilter<String> filter;
+
+ public synchronized void put(String entry) {
+ getFilter().put(entry);
+ }
+
+ public boolean mightContain(String entry) {
+ if (filter == null) {
+ return false;
+ } else {
+ synchronized (this) {
+ return filter.mightContain(entry);
+ }
+ }
+ }
+
+ private BloomFilter<String> getFilter() {
+ if (filter == null) {
+ filter = BloomFilter.create(new Funnel<String>() {
+ private static final long serialVersionUID = -7114267990225941161L;
+
+ @Override
+ public void funnel(String from, PrimitiveSink into) {
+ into.putUnencodedChars(from);
+ }
+ }, ENTRIES, FPP);
+ }
+ return filter;
+ }
+
+ }
+}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java?rev=1741403&r1=1741402&r2=1741403&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocumentCache.java Thu Apr 28 10:02:41 2016
@@ -18,16 +18,20 @@ package org.apache.jackrabbit.oak.plugin
import java.io.Closeable;
import java.io.IOException;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.oak.cache.CacheStats;
@@ -36,6 +40,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
import org.apache.jackrabbit.oak.plugins.document.locks.NodeDocumentLocks;
import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
+import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import com.google.common.base.Objects;
import com.google.common.cache.Cache;
@@ -61,6 +66,8 @@ public class NodeDocumentCache implement
private final NodeDocumentLocks locks;
+ private final List<CacheChangesTracker> changeTrackers;
+
public NodeDocumentCache(@Nonnull Cache<CacheValue, NodeDocument> nodeDocumentsCache,
@Nonnull CacheStats nodeDocumentsCacheStats,
@Nonnull Cache<StringValue, NodeDocument> prevDocumentsCache,
@@ -71,6 +78,7 @@ public class NodeDocumentCache implement
this.prevDocumentsCache = prevDocumentsCache;
this.prevDocumentsCacheStats = prevDocumentsCacheStats;
this.locks = locks;
+ this.changeTrackers = new CopyOnWriteArrayList<CacheChangesTracker>();
}
/**
@@ -86,6 +94,10 @@ public class NodeDocumentCache implement
} else {
nodeDocumentsCache.invalidate(new StringValue(key));
}
+
+ for (CacheChangesTracker tracker : changeTrackers) {
+ tracker.invalidateDocument(key);
+ }
} finally {
lock.unlock();
}
@@ -145,14 +157,23 @@ public class NodeDocumentCache implement
* @return document matching given key
*/
@Nonnull
- public NodeDocument get(@Nonnull String key, @Nonnull Callable<NodeDocument> valueLoader)
+ public NodeDocument get(@Nonnull final String key, @Nonnull final Callable<NodeDocument> valueLoader)
throws ExecutionException {
+ Callable<NodeDocument> wrappedLoader = new Callable<NodeDocument>() {
+ @Override
+ public NodeDocument call() throws Exception {
+ for (CacheChangesTracker tracker : changeTrackers) {
+ tracker.putDocument(key);
+ }
+ return valueLoader.call();
+ }
+ };
Lock lock = locks.acquire(key);
try {
if (isLeafPreviousDocId(key)) {
- return prevDocumentsCache.get(new StringValue(key), valueLoader);
+ return prevDocumentsCache.get(new StringValue(key), wrappedLoader);
} else {
- return nodeDocumentsCache.get(new StringValue(key), valueLoader);
+ return nodeDocumentsCache.get(new StringValue(key), wrappedLoader);
}
} finally {
lock.unlock();
@@ -328,6 +349,63 @@ public class NodeDocumentCache implement
}
}
+ /**
+ * Registers a new CacheChangesTracker that records all puts and
+ * invalidations related to children of the given parent.
+ *
+ * @param parentId children of this parent will be tracked
+ * @return new tracker
+ */
+ public CacheChangesTracker registerTracker(final String parentId) {
+ return new CacheChangesTracker(new Predicate<String>() {
+ @Override
+ public boolean apply(@Nullable String input) {
+ return input != null && parentId.equals(Utils.getParentId(input));
+ }
+ }, changeTrackers);
+ }
+
+ /**
+ * Updates the cache with all the documents that:
+ *
+ * (1) currently have their older versions in the cache or
+ * (2) have been neither put nor invalidated during the tracker lifetime.
+ *
+ * We can't cache documents that has been invalidated during the tracker
+ * lifetime, as it's possible that the invalidated version was newer than
+ * the one passed in the docs parameter.
+ *
+ * If the document has been added during the tracker lifetime, but it is not
+ * present in the cache anymore, it means it may have been evicted, so we
+ * can't re-add it for the same reason as above.
+ *
+ * @param tracker
+ * used to decide whether the docs should be put into cache
+ * @param docs
+ * to put into cache
+ */
+ public void putNonConflictingDocs(CacheChangesTracker tracker, List<NodeDocument> docs) {
+ for (NodeDocument d : docs) {
+ if (d == null || d == NodeDocument.NULL) {
+ continue;
+ }
+ String id = d.getId();
+ Lock lock = locks.acquire(id);
+ try {
+ // if an old document is present in the cache, we can simply update it
+ if (getIfPresent(id) != null) {
+ putIfNewer(d);
+ // if the document hasn't been invalidated or added during the tracker lifetime,
+ // we can put it as well
+ } else if (!tracker.mightBeenAffected(id)) {
+ putIfNewer(d);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
//----------------------------< internal >----------------------------------
/**
@@ -341,5 +419,8 @@ public class NodeDocumentCache implement
} else {
nodeDocumentsCache.put(new StringValue(doc.getId()), doc);
}
+ for (CacheChangesTracker tracker : changeTrackers) {
+ tracker.putDocument(doc.getId());
+ }
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1741403&r1=1741402&r2=1741403&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java Thu Apr 28 10:02:41 2016
@@ -47,7 +47,6 @@ import com.google.common.collect.Iterato
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.mongodb.MongoClientURI;
-import com.mongodb.MongoExecutionTimeoutException;
import com.mongodb.QueryOperators;
import com.mongodb.ReadPreference;
@@ -68,9 +67,11 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key;
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation;
import org.apache.jackrabbit.oak.plugins.document.UpdateUtils;
+import org.apache.jackrabbit.oak.plugins.document.cache.CacheChangesTracker;
import org.apache.jackrabbit.oak.plugins.document.cache.CacheInvalidationStats;
import org.apache.jackrabbit.oak.plugins.document.cache.NodeDocumentCache;
-import org.apache.jackrabbit.oak.plugins.document.locks.TreeNodeDocumentLocks;
+import org.apache.jackrabbit.oak.plugins.document.locks.NodeDocumentLocks;
+import org.apache.jackrabbit.oak.plugins.document.locks.StripedNodeDocumentLocks;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.stats.Clock;
import org.apache.jackrabbit.oak.util.PerfLogger;
@@ -135,7 +136,7 @@ public class MongoDocumentStore implemen
private final NodeDocumentCache nodesCache;
- private final TreeNodeDocumentLocks nodeLocks;
+ private final NodeDocumentLocks nodeLocks;
private Clock clock = Clock.SIMPLE;
@@ -170,17 +171,6 @@ public class MongoDocumentStore implemen
Long.getLong("oak.mongo.maxQueryTimeMS", TimeUnit.MINUTES.toMillis(1));
/**
- * Duration in milliseconds after a mongo query with an additional
- * constraint (e.g. _modified) on the NODES collection times out and is
- * executed again without holding a {@link TreeNodeDocumentLocks.TreeLock}
- * and without updating the cache with data retrieved from MongoDB.
- * <p>
- * Default is 3000 (three seconds).
- */
- private long maxLockedQueryTimeMS =
- Long.getLong("oak.mongo.maxLockedQueryTimeMS", TimeUnit.SECONDS.toMillis(3));
-
- /**
* The number of documents to put into one bulk update.
* <p>
* Default is 30.
@@ -240,7 +230,7 @@ public class MongoDocumentStore implemen
// index on _modified for journal entries
createIndex(journal, JournalEntry.MODIFIED, true, false, false);
- this.nodeLocks = new TreeNodeDocumentLocks();
+ this.nodeLocks = new StripedNodeDocumentLocks();
this.nodesCache = builder.buildNodeDocumentCache(this, nodeLocks);
LOG.info("Configuration maxReplicationLagMillis {}, " +
@@ -523,27 +513,11 @@ public class MongoDocumentStore implemen
String indexedProperty,
long startValue,
int limit) {
- boolean withLock = true;
- if (collection == Collection.NODES && indexedProperty != null) {
- long maxQueryTime;
- if (maxQueryTimeMS > 0) {
- maxQueryTime = Math.min(maxQueryTimeMS, maxLockedQueryTimeMS);
- } else {
- maxQueryTime = maxLockedQueryTimeMS;
- }
- try {
- return queryInternal(collection, fromKey, toKey, indexedProperty,
- startValue, limit, maxQueryTime, true);
- } catch (MongoExecutionTimeoutException e) {
- LOG.info("query timed out after {} milliseconds and will be retried without lock {}",
- maxQueryTime, Lists.newArrayList(fromKey, toKey, indexedProperty, startValue, limit));
- withLock = false;
- }
- }
return queryInternal(collection, fromKey, toKey, indexedProperty,
- startValue, limit, maxQueryTimeMS, withLock);
+ startValue, limit, maxQueryTimeMS);
}
+ @SuppressWarnings("unchecked")
@Nonnull
<T extends Document> List<T> queryInternal(Collection<T> collection,
String fromKey,
@@ -551,8 +525,7 @@ public class MongoDocumentStore implemen
String indexedProperty,
long startValue,
int limit,
- long maxQueryTime,
- boolean withLock) {
+ long maxQueryTime) {
log("query", fromKey, toKey, indexedProperty, startValue, limit);
DBCollection dbCollection = getDBCollection(collection);
QueryBuilder queryBuilder = QueryBuilder.start(Document.ID);
@@ -584,11 +557,14 @@ public class MongoDocumentStore implemen
String parentId = Utils.getParentIdFromLowerLimit(fromKey);
long lockTime = -1;
final Stopwatch watch = startWatch();
- Lock lock = withLock ? nodeLocks.acquireExclusive(parentId != null ? parentId : "") : null;
+
boolean isSlaveOk = false;
int resultSize = 0;
+ CacheChangesTracker cacheChangesTracker = null;
+ if (parentId != null && collection == Collection.NODES) {
+ cacheChangesTracker = nodesCache.registerTracker(parentId);
+ }
try {
- lockTime = withLock ? watch.elapsed(TimeUnit.MILLISECONDS) : -1;
DBCursor cursor = dbCollection.find(query).sort(BY_ID_ASC);
if (!disableIndexHint && !hasModifiedIdCompoundIndex) {
cursor.hint(hint);
@@ -613,21 +589,21 @@ public class MongoDocumentStore implemen
for (int i = 0; i < limit && cursor.hasNext(); i++) {
DBObject o = cursor.next();
T doc = convertFromDBObject(collection, o);
- if (collection == Collection.NODES
- && doc != null
- && lock != null) {
- nodesCache.putIfNewer((NodeDocument) doc);
- }
list.add(doc);
}
resultSize = list.size();
} finally {
cursor.close();
}
+
+ if (cacheChangesTracker != null) {
+ nodesCache.putNonConflictingDocs(cacheChangesTracker, (List<NodeDocument>) list);
+ }
+
return list;
} finally {
- if (lock != null) {
- lock.unlock();
+ if (cacheChangesTracker != null) {
+ cacheChangesTracker.close();
}
stats.doneQuery(watch.elapsed(TimeUnit.NANOSECONDS), collection, fromKey, toKey,
indexedProperty != null , resultSize, lockTime, isSlaveOk);
@@ -1528,18 +1504,6 @@ public class MongoDocumentStore implemen
this.clock = clock;
}
- void setMaxLockedQueryTimeMS(long maxLockedQueryTimeMS) {
- this.maxLockedQueryTimeMS = maxLockedQueryTimeMS;
- }
-
- void resetLockAcquisitionCount() {
- nodeLocks.resetLockAcquisitionCount();
- }
-
- long getLockAcquisitionCount() {
- return nodeLocks.getLockAcquisitionCount();
- }
-
NodeDocumentCache getNodeDocumentCache() {
return nodesCache;
}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java?rev=1741403&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/cache/CacheChangesTrackerTest.java Thu Apr 28 10:02:41 2016
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.document.cache;
+
+import com.google.common.base.Predicate;
+import com.google.common.cache.Cache;
+import org.apache.jackrabbit.oak.cache.CacheLIRS;
+import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.cache.CacheValue;
+import org.apache.jackrabbit.oak.plugins.document.Collection;
+import org.apache.jackrabbit.oak.plugins.document.DocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
+import org.apache.jackrabbit.oak.plugins.document.locks.NodeDocumentLocks;
+import org.apache.jackrabbit.oak.plugins.document.locks.StripedNodeDocumentLocks;
+import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class CacheChangesTrackerTest {
+
+ private DocumentStore ds;
+
+ @Before
+ public void createDS() {
+ ds = new MemoryDocumentStore();
+ }
+
+ @Test
+ public void testTracker() {
+ List<CacheChangesTracker> list = new ArrayList<CacheChangesTracker>();
+ CacheChangesTracker tracker = new CacheChangesTracker(new Predicate<String>() {
+ @Override
+ public boolean apply(@Nullable String input) {
+ return !"ignored".equals(input);
+ }
+ }, list);
+
+ assertFalse(tracker.mightBeenAffected("xyz"));
+ assertFalse(tracker.mightBeenAffected("abc"));
+
+ tracker.putDocument("xyz");
+ assertTrue(tracker.mightBeenAffected("xyz"));
+
+ tracker.invalidateDocument("abc");
+ assertTrue(tracker.mightBeenAffected("abc"));
+
+ tracker.putDocument("ignored");
+ tracker.invalidateDocument("ignored");
+ assertFalse(tracker.mightBeenAffected("ignored"));
+
+ tracker.close();
+ assertTrue(list.isEmpty());
+ }
+
+ @Test
+ public void testRegisterChildrenTracker() {
+ NodeDocumentCache cache = createCache();
+ CacheChangesTracker tracker = cache.registerTracker("1:/parent");
+
+ assertFalse(tracker.mightBeenAffected("2:/parent/xyz"));
+ assertFalse(tracker.mightBeenAffected("2:/parent/abc"));
+
+ cache.put(createDoc("2:/parent/xyz"));
+ assertTrue(tracker.mightBeenAffected("2:/parent/xyz"));
+
+ cache.invalidate("2:/parent/abc");
+ assertTrue(tracker.mightBeenAffected("2:/parent/abc"));
+
+ cache.invalidate("2:/other-parent/abc");
+ assertFalse(tracker.mightBeenAffected("2:/other-parent/abc"));
+
+ tracker.close();
+
+ cache.invalidate("2:/parent/123");
+ assertFalse(tracker.mightBeenAffected("2:/parent/123"));
+ }
+
+ @Test
+ public void testGetLoaderAffectsTracker() throws ExecutionException {
+ NodeDocumentCache cache = createCache();
+ CacheChangesTracker tracker = cache.registerTracker("1:/parent");
+
+ assertFalse(tracker.mightBeenAffected("2:/parent/xyz"));
+
+ cache.getIfPresent("2:/parent/xyz");
+ assertFalse(tracker.mightBeenAffected("2:/parent/xyz"));
+
+ cache.get("2:/parent/xyz", new Callable<NodeDocument>() {
+ @Override
+ public NodeDocument call() throws Exception {
+ return createDoc("2:/parent/xyz");
+ }
+ });
+ assertTrue(tracker.mightBeenAffected("2:/parent/xyz"));
+ }
+
+ private NodeDocumentCache createCache() {
+ Cache<CacheValue, NodeDocument> nodeDocumentsCache = new CacheLIRS<CacheValue, NodeDocument>(10);
+ Cache<StringValue, NodeDocument> prevDocumentsCache = new CacheLIRS<StringValue, NodeDocument>(10);
+ CacheStats nodeDocumentsCacheStats = Mockito.mock(CacheStats.class);
+ CacheStats prevDocumentsCacheStats = Mockito.mock(CacheStats.class);
+ NodeDocumentLocks locks = new StripedNodeDocumentLocks();
+ return new NodeDocumentCache(nodeDocumentsCache, nodeDocumentsCacheStats, prevDocumentsCache, prevDocumentsCacheStats, locks);
+ }
+
+ private NodeDocument createDoc(String id) {
+ NodeDocument doc = Collection.NODES.newDocument(ds);
+ doc.put("_id", id);
+ return doc;
+ }
+}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/NodeDocumentLocksTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/NodeDocumentLocksTest.java?rev=1741403&r1=1741402&r2=1741403&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/NodeDocumentLocksTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/locks/NodeDocumentLocksTest.java Thu Apr 28 10:02:41 2016
@@ -19,30 +19,14 @@ package org.apache.jackrabbit.oak.plugin
import static org.junit.Assert.fail;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import java.util.concurrent.locks.Lock;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-@RunWith(Parameterized.class)
public class NodeDocumentLocksTest {
- @Parameters(name = "{1}")
- public static Collection<Object[]> data() {
- return Arrays.asList(new Object[][] { { new StripedNodeDocumentLocks(), "StripedNodeDocumentLocks" },
- { new TreeNodeDocumentLocks(), "TreeNodeDocumentLocks" } });
- }
-
- private final NodeDocumentLocks locks;
-
- public NodeDocumentLocksTest(NodeDocumentLocks locks, String name) {
- this.locks = locks;
- }
+ private final NodeDocumentLocks locks = new StripedNodeDocumentLocks();
@Test
public void testBulkAcquireNonConflicting() throws InterruptedException {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java?rev=1741403&r1=1741402&r2=1741403&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStoreTest.java Thu Apr 28 10:02:41 2016
@@ -16,11 +16,6 @@
*/
package org.apache.jackrabbit.oak.plugins.document.mongo;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.annotation.Nonnull;
-
import com.mongodb.DB;
import org.apache.jackrabbit.oak.plugins.document.AbstractMongoConnectionTest;
@@ -30,14 +25,11 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.JournalEntry;
import org.apache.jackrabbit.oak.plugins.document.MongoUtils;
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
-import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.junit.Test;
import static org.apache.jackrabbit.oak.plugins.document.mongo.MongoUtils.hasIndex;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
/**
* <code>MongoDocumentStoreTest</code>...
@@ -57,32 +49,6 @@ public class MongoDocumentStoreTest exte
}
@Test
- public void timeoutQuery() {
- String fromId = Utils.getKeyLowerLimit("/");
- String toId = Utils.getKeyUpperLimit("/");
- store.setMaxLockedQueryTimeMS(1);
- long index = 0;
- for (int i = 0; i < 100; i++) {
- // keep adding nodes until the query runs into the timeout
- StringBuilder sb = new StringBuilder();
- for (int j = 0; j < 1000; j++) {
- sb.append("+\"node-").append(index++).append("\":{}");
- }
- mk.commit("/", sb.toString(), null, null);
- store.queriesWithoutLock.set(0);
- store.resetLockAcquisitionCount();
- List<NodeDocument> docs = store.query(Collection.NODES, fromId, toId,
- "foo", System.currentTimeMillis(), Integer.MAX_VALUE);
- assertTrue(docs.isEmpty());
- if (store.queriesWithoutLock.get() > 0) {
- assertEquals(1, store.getLockAcquisitionCount());
- return;
- }
- }
- fail("No query timeout triggered even after adding " + index + " nodes");
- }
-
- @Test
public void defaultIndexes() {
assertTrue(hasIndex(store.getDBCollection(Collection.NODES), Document.ID));
assertTrue(hasIndex(store.getDBCollection(Collection.NODES), NodeDocument.SD_TYPE));
@@ -94,28 +60,8 @@ public class MongoDocumentStoreTest exte
}
static final class TestStore extends MongoDocumentStore {
-
- AtomicInteger queriesWithoutLock = new AtomicInteger();
-
TestStore(DB db, DocumentMK.Builder builder) {
super(db, builder);
}
-
- @Nonnull
- @Override
- <T extends Document> List<T> queryInternal(Collection<T> collection,
- String fromKey,
- String toKey,
- String indexedProperty,
- long startValue,
- int limit,
- long maxQueryTime,
- boolean withLock) {
- if (collection == Collection.NODES && !withLock) {
- queriesWithoutLock.incrementAndGet();
- }
- return super.queryInternal(collection, fromKey, toKey,
- indexedProperty, startValue, limit, maxQueryTime, withLock);
- }
}
}