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


Reply via email to