Author: mreutegg
Date: Thu Jan 30 14:54:58 2014
New Revision: 1562847
URL: http://svn.apache.org/r1562847
Log:
OAK-825: Unnecessary performance overhead in MongoMK's calculation of keys for
the nodeCache, nodeChildrenCache
- Use a CacheValue instead of String as a cache key
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
(with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/EmpiricalWeigher.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/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocOffHeapCache.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/OffHeapCache.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/EmpiricalWeigher.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/EmpiricalWeigher.java?rev=1562847&r1=1562846&r2=1562847&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/EmpiricalWeigher.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/cache/EmpiricalWeigher.java
Thu Jan 30 14:54:58 2014
@@ -16,22 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.cache;
-
import com.google.common.cache.Weigher;
/**
* Determines the weight of object based on the memory taken by them. The
memory estimates
* are based on empirical data and not exact
*/
-public class EmpiricalWeigher implements Weigher<String, CacheValue> {
+public class EmpiricalWeigher implements Weigher<CacheValue, CacheValue> {
@Override
- public int weigh(String key, CacheValue value) {
+ public int weigh(CacheValue key, CacheValue value) {
int size = 168; // overhead for each cache entry
- size += 48 + key.length() * 2; // string key
+ size += key.getMemory(); // key
size += value.getMemory(); // value
return size;
}
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=1562847&r1=1562846&r2=1562847&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
Thu Jan 30 14:54:58 2014
@@ -17,10 +17,6 @@
package org.apache.jackrabbit.oak.plugins.document;
import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -38,10 +34,8 @@ import org.apache.jackrabbit.mk.blobs.Me
import org.apache.jackrabbit.mk.json.JsopReader;
import org.apache.jackrabbit.mk.json.JsopStream;
import org.apache.jackrabbit.mk.json.JsopTokenizer;
-import org.apache.jackrabbit.mk.json.JsopWriter;
import org.apache.jackrabbit.oak.api.CommitFailedException;
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.cache.EmpiricalWeigher;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -49,12 +43,9 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoBlobStore;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
-import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.plugins.document.rdb.RDBBlobStore;
import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStore;
-import static com.google.common.base.Preconditions.checkNotNull;
-
/**
* A MicroKernel implementation that stores the data in a {@link
DocumentStore}.
*/
@@ -70,7 +61,7 @@ public class DocumentMK implements Micro
* Enable the LIRS cache.
*/
static final boolean LIRS_CACHE = Boolean.parseBoolean(
- System.getProperty("oak.documentMK.lirsCache", "false"));
+ System.getProperty("oak.documentMK.lirsCache", "true"));
/**
* Enable fast diff operations.
@@ -453,7 +444,7 @@ public class DocumentMK implements Micro
private int asyncDelay = 1000;
private boolean timing;
private boolean logging;
- private Weigher<String, CacheValue> weigher = new EmpiricalWeigher();
+ private Weigher<CacheValue, CacheValue> weigher = new
EmpiricalWeigher();
private long nodeCacheSize;
private long childrenCacheSize;
private long diffCacheSize;
@@ -606,11 +597,11 @@ public class DocumentMK implements Micro
return asyncDelay;
}
- public Weigher<String, CacheValue> getWeigher() {
+ public Weigher<CacheValue, CacheValue> getWeigher() {
return weigher;
}
- public Builder withWeigher(Weigher<String, CacheValue> weigher) {
+ public Builder withWeigher(Weigher<CacheValue, CacheValue> weigher) {
this.weigher = weigher;
return this;
}
@@ -684,7 +675,7 @@ public class DocumentMK implements Micro
return new DocumentMK(this);
}
- public <V extends CacheValue> Cache<String, V> buildCache(long
maxWeight) {
+ public <K extends CacheValue, V extends CacheValue> Cache<K, V>
buildCache(long maxWeight) {
if (LIRS_CACHE) {
return CacheLIRS.newBuilder().weigher(weigher).
maximumWeight(maxWeight).recordStats().build();
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=1562847&r1=1562846&r2=1562847&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
Thu Jan 30 14:54:58 2014
@@ -64,6 +64,7 @@ import org.apache.jackrabbit.oak.cache.C
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.kernel.BlobSerializer;
import
org.apache.jackrabbit.oak.plugins.document.util.LoggingDocumentStoreWrapper;
+import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
import
org.apache.jackrabbit.oak.plugins.document.util.TimingDocumentStoreWrapper;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.spi.commit.ChangeDispatcher;
@@ -207,29 +208,33 @@ public final class DocumentNodeStore
/**
* The node cache.
*
- * Key: path@rev, value: node
+ * Key: PathRev, value: Node
*/
- private final Cache<String, Node> nodeCache;
+ private final Cache<CacheValue, Node> nodeCache;
private final CacheStats nodeCacheStats;
/**
* Child node cache.
*
- * Key: start-name/path@rev, value: children
+ * Key: PathRev, value: Children
*/
- private final Cache<String, Node.Children> nodeChildrenCache;
+ private final Cache<CacheValue, Node.Children> nodeChildrenCache;
private final CacheStats nodeChildrenCacheStats;
/**
* Child doc cache.
+ *
+ * Key: StringValue, value: Children
*/
- private final Cache<String, NodeDocument.Children> docChildrenCache;
+ private final Cache<CacheValue, NodeDocument.Children> docChildrenCache;
private final CacheStats docChildrenCacheStats;
/**
* Diff cache.
+ *
+ * Key: PathRev, value: Diff
*/
- private final Cache<String, Diff> diffCache;
+ private final Cache<CacheValue, Diff> diffCache;
private final CacheStats diffCacheStats;
/**
@@ -547,7 +552,7 @@ public final class DocumentNodeStore
Node getNode(@Nonnull final String path, @Nonnull final Revision rev) {
checkRevisionAge(checkNotNull(rev), checkNotNull(path));
try {
- String key = path + "@" + rev;
+ PathRev key = new PathRev(path, rev);
Node node = nodeCache.get(key, new Callable<Node>() {
@Override
public Node call() throws Exception {
@@ -573,7 +578,7 @@ public final class DocumentNodeStore
}
final String path = checkNotNull(parent).getPath();
final Revision readRevision = parent.getLastRevision();
- String key = childNodeCacheKey(path, readRevision, name);
+ PathRev key = childNodeCacheKey(path, readRevision, name);
Node.Children children;
for (;;) {
try {
@@ -674,8 +679,9 @@ public final class DocumentNodeStore
// or more than 16k child docs are requested
return store.query(Collection.NODES, from, to, limit);
}
+ CacheValue key = new StringValue(path);
// check cache
- NodeDocument.Children c = docChildrenCache.getIfPresent(path);
+ NodeDocument.Children c = docChildrenCache.getIfPresent(key);
if (c == null) {
c = new NodeDocument.Children();
List<NodeDocument> docs = store.query(Collection.NODES, from, to,
limit);
@@ -684,7 +690,7 @@ public final class DocumentNodeStore
c.childNames.add(PathUtils.getName(p));
}
c.isComplete = docs.size() < limit;
- docChildrenCache.put(path, c);
+ docChildrenCache.put(key, c);
return docs;
} else if (c.childNames.size() < limit && !c.isComplete) {
// fetch more and update cache
@@ -700,7 +706,7 @@ public final class DocumentNodeStore
clone.childNames.add(PathUtils.getName(p));
}
clone.isComplete = docs.size() < remainingLimit;
- docChildrenCache.put(path, clone);
+ docChildrenCache.put(key, clone);
c = clone;
}
Iterable<NodeDocument> it = Iterables.transform(c.childNames, new
Function<String, NodeDocument>() {
@@ -795,7 +801,7 @@ public final class DocumentNodeStore
}
}
}
- String key = childNodeCacheKey(path, rev, null);
+ CacheValue key = childNodeCacheKey(path, rev, null);
Node.Children c = nodeChildrenCache.getIfPresent(key);
if (isNew || (!isDelete && c != null)) {
Node.Children c2 = new Node.Children();
@@ -811,7 +817,8 @@ public final class DocumentNodeStore
nodeChildrenCache.put(key, c2);
}
if (!added.isEmpty()) {
- NodeDocument.Children docChildren =
docChildrenCache.getIfPresent(path);
+ CacheValue docChildrenKey = new StringValue(path);
+ NodeDocument.Children docChildren =
docChildrenCache.getIfPresent(docChildrenKey);
if (docChildren != null) {
int currentSize = docChildren.childNames.size();
TreeSet<String> names = new
TreeSet<String>(docChildren.childNames);
@@ -838,7 +845,7 @@ public final class DocumentNodeStore
docChildren = new NodeDocument.Children();
docChildren.isComplete = complete;
docChildren.childNames.addAll(names);
- docChildrenCache.put(path, docChildren);
+ docChildrenCache.put(docChildrenKey, docChildren);
}
}
}
@@ -1052,8 +1059,9 @@ public final class DocumentNodeStore
*/
String diff(final @Nonnull Node node,
final @Nonnull Node base) {
- String key = checkNotNull(base).getLastRevision() + "-"
- + checkNotNull(node).getLastRevision() + "-" + node.getPath();
+ PathRev key = new PathRev(
+ checkNotNull(node).getLastRevision() + "-" + node.getPath(),
+ checkNotNull(base).getLastRevision());
try {
return diffCache.get(key, new Callable<Diff>() {
@Override
@@ -1076,7 +1084,8 @@ public final class DocumentNodeStore
if (fromRevisionId.equals(toRevisionId)) {
return "";
}
- String key = fromRevisionId + "-" + toRevisionId + "-" + path;
+ PathRev key = new PathRev(toRevisionId + "-" + path,
+ Revision.fromString(fromRevisionId));
try {
return diffCache.get(key, new Callable<Diff>() {
@Override
@@ -1499,10 +1508,10 @@ public final class DocumentNodeStore
}
}
- private static String childNodeCacheKey(@Nonnull String path,
+ private static PathRev childNodeCacheKey(@Nonnull String path,
@Nonnull Revision readRevision,
@Nullable String name) {
- return (name == null ? "" : name) + path + "@" + readRevision;
+ return new PathRev((name == null ? "" : name) + path, readRevision);
}
private static DocumentRootBuilder asDocumentRootBuilder(NodeBuilder
builder)
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java?rev=1562847&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
Thu Jan 30 14:54:58 2014
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.cache.CacheValue;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A cache key implementation, which is a combination of a path string and a
+ * revision.
+ */
+final public class PathRev implements CacheValue {
+
+ private final String path;
+
+ private final Revision revision;
+
+ public PathRev(@Nonnull String path, @Nonnull Revision revision) {
+ this.path = checkNotNull(path);
+ this.revision = checkNotNull(revision);
+ }
+
+ @Override
+ public int getMemory() {
+ return 24 // shallow size
+ + 40 * path.length() * 2 // path
+ + 32; // revision
+ }
+
+ //----------------------------< Object
>------------------------------------
+
+
+ @Override
+ public int hashCode() {
+ return path.hashCode() ^ revision.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj instanceof PathRev) {
+ PathRev other = (PathRev) obj;
+ return revision.equals(other.revision) && path.equals(other.path);
+ }
+ return false;
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocOffHeapCache.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocOffHeapCache.java?rev=1562847&r1=1562846&r2=1562847&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocOffHeapCache.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/NodeDocOffHeapCache.java
Thu Jan 30 14:54:58 2014
@@ -60,21 +60,21 @@ import static com.google.common.cache.Ab
import static com.google.common.cache.AbstractCache.StatsCounter;
public class NodeDocOffHeapCache
- extends ForwardingCache.SimpleForwardingCache<String, NodeDocument>
+ extends ForwardingCache.SimpleForwardingCache<CacheValue, NodeDocument>
implements Closeable, OffHeapCache {
private final StatsCounter statsCounter = new SimpleStatsCounter();
private final Logger log = LoggerFactory.getLogger(getClass());
- private final Cache<String, NodeDocReference> offHeapCache;
+ private final Cache<CacheValue, NodeDocReference> offHeapCache;
private final CacheStats offHeapCacheStats;
private final MemoryManagerService<NodeDocument> memoryManager;
private final KryoSerializer serializer;
- public NodeDocOffHeapCache(Cache<String, NodeDocument> delegate,
- ForwardingListener<String, NodeDocument>
forwardingListener,
+ public NodeDocOffHeapCache(Cache<CacheValue, NodeDocument> delegate,
+ ForwardingListener<CacheValue, NodeDocument>
forwardingListener,
DocumentMK.Builder builder,
DocumentStore documentStore) {
super(delegate);
@@ -116,7 +116,7 @@ public class NodeDocOffHeapCache
@Override
- public NodeDocument get(final String key, final Callable<? extends
NodeDocument> valueLoader)
+ public NodeDocument get(final CacheValue key, final Callable<? extends
NodeDocument> valueLoader)
throws ExecutionException {
return super.get(key, new Callable<NodeDocument>() {
@Override
@@ -135,9 +135,9 @@ public class NodeDocOffHeapCache
}
@Override
- public ImmutableMap<String, NodeDocument> getAllPresent(Iterable<?> keys) {
- @SuppressWarnings("unchecked") List<String> list =
Lists.newArrayList((Iterable<String>) keys);
- ImmutableMap<String, NodeDocument> result = super.getAllPresent(list);
+ public ImmutableMap<CacheValue, NodeDocument> getAllPresent(Iterable<?>
keys) {
+ @SuppressWarnings("unchecked") List<CacheValue> list =
Lists.newArrayList((Iterable<CacheValue>) keys);
+ ImmutableMap<CacheValue, NodeDocument> result =
super.getAllPresent(list);
//All the requested keys found then no
//need to check L2
@@ -146,8 +146,8 @@ public class NodeDocOffHeapCache
}
//Look up value from L2
- Map<String, NodeDocument> r2 = Maps.newHashMap(result);
- for (String key : list) {
+ Map<CacheValue, NodeDocument> r2 = Maps.newHashMap(result);
+ for (CacheValue key : list) {
if (!result.containsKey(key)) {
NodeDocument val = retrieve(key, false);
if (val != null) {
@@ -183,7 +183,7 @@ public class NodeDocOffHeapCache
}
@Override
- public Map<String, ? extends CachedNodeDocument> offHeapEntriesMap() {
+ public Map<CacheValue, ? extends CachedNodeDocument> offHeapEntriesMap() {
return Collections.unmodifiableMap(offHeapCache.asMap());
}
@@ -235,10 +235,10 @@ public class NodeDocOffHeapCache
return result;
}
- private class PrimaryRemovalListener implements RemovalListener<String,
NodeDocument> {
+ private class PrimaryRemovalListener implements
RemovalListener<CacheValue, NodeDocument> {
@Override
- public void onRemoval(RemovalNotification<String, NodeDocument> n) {
+ public void onRemoval(RemovalNotification<CacheValue, NodeDocument> n)
{
//If removed explicitly then we clear from L2
if (n.getCause() == RemovalCause.EXPLICIT
|| n.getCause() == RemovalCause.REPLACED) {
@@ -250,15 +250,16 @@ public class NodeDocOffHeapCache
if (n.getCause() == RemovalCause.SIZE) {
NodeDocument doc = n.getValue();
if (doc != NodeDocument.NULL) {
- offHeapCache.put(n.getKey(), new
NodeDocReference(n.getKey(), doc));
+ offHeapCache.put(n.getKey(),
+ new NodeDocReference(n.getKey(), doc));
}
}
}
}
- private class SecondaryRemovalListener implements RemovalListener<String,
NodeDocReference> {
+ private class SecondaryRemovalListener implements
RemovalListener<CacheValue, NodeDocReference> {
@Override
- public void onRemoval(RemovalNotification<String, NodeDocReference>
notification) {
+ public void onRemoval(RemovalNotification<CacheValue,
NodeDocReference> notification) {
NodeDocReference doc = notification.getValue();
if (doc != null && doc.getPointer() != null) {
memoryManager.free(doc.getPointer());
@@ -271,9 +272,9 @@ public class NodeDocOffHeapCache
private final long created;
private final AtomicLong lastCheckTime;
private final Pointer<NodeDocument> documentPointer;
- private final String key;
+ private final CacheValue key;
- public NodeDocReference(String key, NodeDocument doc) {
+ public NodeDocReference(CacheValue key, NodeDocument doc) {
this.modCount = doc.getModCount();
this.created = doc.getCreated();
this.lastCheckTime = new AtomicLong(doc.getLastCheckTime());
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/OffHeapCache.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/OffHeapCache.java?rev=1562847&r1=1562846&r2=1562847&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/OffHeapCache.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/cache/OffHeapCache.java
Thu Jan 30 14:54:58 2014
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.plugins.document.cache;
import java.util.Map;
@@ -25,6 +24,7 @@ import javax.annotation.Nullable;
import com.google.common.cache.Cache;
import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.cache.CacheValue;
import org.apache.jackrabbit.oak.plugins.document.CachedNodeDocument;
import org.apache.jackrabbit.oak.plugins.document.NodeDocument;
@@ -34,9 +34,9 @@ import org.apache.jackrabbit.oak.plugins
* This interface is required to avoid direct dependency on DirectMemory
* and Kryo classes
*/
-public interface OffHeapCache extends Cache<String, NodeDocument> {
+public interface OffHeapCache extends Cache<CacheValue, NodeDocument> {
- Map<String, ? extends CachedNodeDocument> offHeapEntriesMap();
+ Map<CacheValue, ? extends CachedNodeDocument> offHeapEntriesMap();
CacheStats getCacheStats();
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java?rev=1562847&r1=1562846&r2=1562847&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/CacheInvalidator.java
Thu Jan 30 14:54:58 2014
@@ -35,6 +35,8 @@ import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
+
+import org.apache.jackrabbit.oak.cache.CacheValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.document.CachedNodeDocument;
import org.apache.jackrabbit.oak.plugins.document.Collection;
@@ -92,9 +94,9 @@ abstract class CacheInvalidator {
public InvalidationResult invalidateCache() {
InvalidationResult result = new InvalidationResult();
int size = 0;
- for (Map.Entry<String, ? extends CachedNodeDocument> e :
documentStore.getCacheEntries()) {
+ for (Map.Entry<CacheValue, ? extends CachedNodeDocument> e :
documentStore.getCacheEntries()) {
size++;
- documentStore.invalidateCache(Collection.NODES, e.getKey());
+ documentStore.invalidateCache(Collection.NODES,
e.getKey().toString());
}
result.cacheSize = size;
return result;
@@ -116,9 +118,9 @@ abstract class CacheInvalidator {
int size = 0;
List<String> cachedKeys = new ArrayList<String>();
- for (Map.Entry<String, ? extends CachedNodeDocument> e :
documentStore.getCacheEntries()) {
+ for (Map.Entry<CacheValue, ? extends CachedNodeDocument> e :
documentStore.getCacheEntries()) {
size++;
- cachedKeys.add(e.getKey());
+ cachedKeys.add(e.getKey().toString());
}
result.cacheSize = size;
@@ -264,10 +266,10 @@ abstract class CacheInvalidator {
return result;
}
- private TreeNode constructTreeFromPaths(Iterable<? extends
Map.Entry<String, ? extends CachedNodeDocument>> entries,
+ private TreeNode constructTreeFromPaths(Iterable<? extends
Map.Entry<CacheValue, ? extends CachedNodeDocument>> entries,
InvalidationResult result) {
TreeNode root = new TreeNode("");
- for (Map.Entry<String, ? extends CachedNodeDocument> e : entries) {
+ for (Map.Entry<CacheValue, ? extends CachedNodeDocument> e :
entries) {
TreeNode current = root;
//TODO Split documents are immutable hence no need to
@@ -275,7 +277,7 @@ abstract class CacheInvalidator {
//TODO Need to determine way to determine if the
//key is referring to a split document
- String path = Utils.getPathFromId(e.getKey());
+ String path = Utils.getPathFromId(e.getKey().toString());
result.cacheSize++;
for (String name : PathUtils.elements(path)) {
current = current.child(name);
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=1562847&r1=1562846&r2=1562847&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 Jan 30 14:54:58 2014
@@ -37,6 +37,7 @@ import javax.annotation.Nullable;
import com.google.common.base.Splitter;
import org.apache.jackrabbit.mk.api.MicroKernelException;
import org.apache.jackrabbit.oak.cache.CacheStats;
+import org.apache.jackrabbit.oak.cache.CacheValue;
import org.apache.jackrabbit.oak.plugins.document.CachedNodeDocument;
import org.apache.jackrabbit.oak.plugins.document.Collection;
import org.apache.jackrabbit.oak.plugins.document.Document;
@@ -52,6 +53,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.cache.ForwardingListener;
import org.apache.jackrabbit.oak.plugins.document.cache.NodeDocOffHeapCache;
import org.apache.jackrabbit.oak.plugins.document.cache.OffHeapCache;
+import org.apache.jackrabbit.oak.plugins.document.util.StringValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -91,7 +93,7 @@ public class MongoDocumentStore implemen
*/
private long timeSum;
- private final Cache<String, NodeDocument> nodesCache;
+ private final Cache<CacheValue, NodeDocument> nodesCache;
private final CacheStats cacheStats;
/**
@@ -133,18 +135,18 @@ public class MongoDocumentStore implemen
builder.getDocumentCacheSize());
}
- private Cache<String , NodeDocument> createOffHeapCache(DocumentMK.Builder
builder){
- ForwardingListener<String , NodeDocument> listener =
ForwardingListener.newInstance();
+ private Cache<CacheValue, NodeDocument>
createOffHeapCache(DocumentMK.Builder builder){
+ ForwardingListener<CacheValue, NodeDocument> listener =
ForwardingListener.newInstance();
- Cache<String,NodeDocument> primaryCache = CacheBuilder.newBuilder()
+ Cache<CacheValue, NodeDocument> primaryCache =
CacheBuilder.newBuilder()
.weigher(builder.getWeigher())
.maximumWeight(builder.getDocumentCacheSize())
.removalListener(listener)
.recordStats()
.build();
- Cache<String,NodeDocument> cache =
- new NodeDocOffHeapCache( primaryCache, listener, builder, this
);
+ Cache<CacheValue, NodeDocument> cache =
+ new NodeDocOffHeapCache(primaryCache, listener, builder, this);
return cache;
}
@@ -182,7 +184,7 @@ public class MongoDocumentStore implemen
if (collection == Collection.NODES) {
Lock lock = getAndLock(key);
try {
- nodesCache.invalidate(key);
+ nodesCache.invalidate(new StringValue(key));
} finally {
lock.unlock();
}
@@ -202,10 +204,11 @@ public class MongoDocumentStore implemen
if (collection != Collection.NODES) {
return findUncached(collection, key);
}
+ CacheValue cacheKey = new StringValue(key);
NodeDocument doc;
if (maxCacheAge > 0) {
// first try without lock
- doc = nodesCache.getIfPresent(key);
+ doc = nodesCache.getIfPresent(cacheKey);
if (doc != null) {
if (maxCacheAge == Integer.MAX_VALUE ||
System.currentTimeMillis() - doc.getCreated() <
maxCacheAge) {
@@ -223,7 +226,7 @@ public class MongoDocumentStore implemen
invalidateCache(collection, key);
}
while (true) {
- doc = nodesCache.get(key, new Callable<NodeDocument>() {
+ doc = nodesCache.get(cacheKey, new
Callable<NodeDocument>() {
@Override
public NodeDocument call() throws Exception {
NodeDocument doc = (NodeDocument)
findUncached(collection, key);
@@ -312,10 +315,11 @@ public class MongoDocumentStore implemen
doc.seal();
String id = doc.getId();
Lock lock = getAndLock(id);
+ CacheValue cacheKey = new StringValue(id);
try {
// do not overwrite document in cache if the
// existing one in the cache is newer
- NodeDocument cached = nodesCache.getIfPresent(id);
+ NodeDocument cached =
nodesCache.getIfPresent(cacheKey);
if (cached != null && cached != NodeDocument.NULL) {
// check mod count
Number cachedModCount = cached.getModCount();
@@ -325,10 +329,10 @@ public class MongoDocumentStore implemen
"Missing " + Document.MOD_COUNT);
}
if (modCount.longValue() >
cachedModCount.longValue()) {
- nodesCache.put(id, (NodeDocument) doc);
+ nodesCache.put(cacheKey, (NodeDocument) doc);
}
} else {
- nodesCache.put(id, (NodeDocument) doc);
+ nodesCache.put(cacheKey, (NodeDocument) doc);
}
} finally {
lock.unlock();
@@ -374,7 +378,7 @@ public class MongoDocumentStore implemen
T cachedDoc = null;
if (collection == Collection.NODES) {
@SuppressWarnings("unchecked")
- T doc = (T) nodesCache.getIfPresent(updateOp.getId());
+ T doc = (T) nodesCache.getIfPresent(new
StringValue(updateOp.getId()));
cachedDoc = doc;
if (cachedDoc != null) {
modCount = cachedDoc.getModCount();
@@ -522,7 +526,7 @@ public class MongoDocumentStore implemen
if (collection == Collection.NODES) {
cachedDocs = Maps.newHashMap();
for (String key : keys) {
- cachedDocs.put(key, nodesCache.getIfPresent(key));
+ cachedDocs.put(key, nodesCache.getIfPresent(new
StringValue(key)));
}
}
try {
@@ -536,7 +540,7 @@ public class MongoDocumentStore implemen
try {
if (entry.getValue() == null) {
// make sure concurrently loaded document is
invalidated
- nodesCache.invalidate(entry.getKey());
+ nodesCache.invalidate(new
StringValue(entry.getKey()));
} else {
applyToCache(Collection.NODES, entry.getValue(),
updateOp.clone(entry.getKey()));
@@ -620,7 +624,7 @@ public class MongoDocumentStore implemen
return cacheStats;
}
- Iterable<? extends Map.Entry<String, ? extends CachedNodeDocument>>
getCacheEntries() {
+ Iterable<? extends Map.Entry<CacheValue, ? extends CachedNodeDocument>>
getCacheEntries() {
if(nodesCache instanceof OffHeapCache){
return Iterables.concat(nodesCache.asMap().entrySet(),
((OffHeapCache)nodesCache).offHeapEntriesMap().entrySet());
@@ -633,7 +637,7 @@ public class MongoDocumentStore implemen
return ((OffHeapCache) nodesCache).getCachedDocument(id);
}
- return nodesCache.getIfPresent(id);
+ return nodesCache.getIfPresent(new StringValue(id));
}
private static void log(String message, Object... args) {
@@ -652,7 +656,7 @@ public class MongoDocumentStore implemen
return null;
}
@SuppressWarnings("unchecked")
- T doc = (T) nodesCache.getIfPresent(key);
+ T doc = (T) nodesCache.getIfPresent(new StringValue(key));
return doc;
}
@@ -677,7 +681,7 @@ public class MongoDocumentStore implemen
oldDoc.deepCopy(newDoc);
oldDoc.seal();
}
- String key = updateOp.getId();
+ CacheValue key = new StringValue(updateOp.getId());
UpdateUtils.applyChanges(newDoc, updateOp, comparator);
newDoc.seal();
@@ -726,8 +730,9 @@ public class MongoDocumentStore implemen
// meantime. That is, use get() with a Callable,
// which is only used when the document isn't there
try {
+ CacheValue key = new StringValue(doc.getId());
for (;;) {
- NodeDocument cached = nodesCache.get(doc.getId(),
+ NodeDocument cached = nodesCache.get(key,
new Callable<NodeDocument>() {
@Override
public NodeDocument call() {
@@ -737,7 +742,7 @@ public class MongoDocumentStore implemen
if (cached != NodeDocument.NULL) {
return cached;
} else {
- nodesCache.invalidate(doc.getId());
+ nodesCache.invalidate(key);
}
}
} catch (ExecutionException e) {
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java?rev=1562847&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
Thu Jan 30 14:54:58 2014
@@ -0,0 +1,63 @@
+/*
+ * 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.util;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.cache.CacheValue;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A cache value wrapping a simple string.
+ */
+final public class StringValue implements CacheValue {
+
+ private final String value;
+
+ public StringValue(@Nonnull String value) {
+ this.value = checkNotNull(value);
+ }
+
+ @Override
+ public int getMemory() {
+ return 16 * value.length() * 2;
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj instanceof StringValue) {
+ StringValue other = (StringValue) obj;
+ return value.equals(other.value);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/StringValue.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL