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 ch...@apache.org on 2016/06/21 06:17:44 UTC

svn commit: r1749425 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document: DocumentNodeState.java DocumentNodeStateCache.java DocumentNodeStore.java DocumentNodeStoreService.java

Author: chetanm
Date: Tue Jun 21 06:17:44 2016
New Revision: 1749425

URL: http://svn.apache.org/viewvc?rev=1749425&view=rev
Log:
OAK-4180 - Use another NodeStore as a local cache for a remote Document store

Refactor to introduce a DocumentNodeStateCache interface. This encapsulates logic related to caching of AbstractDocumentNodeState

DocumentNodeStoreService keeps a track of the DocumentNodeStateCache service (optional). Once detected it registers it with DocumentNodeStore

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.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/DocumentNodeStoreService.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java?rev=1749425&r1=1749424&r2=1749425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeState.java Tue Jun 21 06:17:44 2016
@@ -223,7 +223,7 @@ public class DocumentNodeState extends A
             return false;
         } else {
             String p = PathUtils.concat(getPath(), name);
-            return store.getNode(p, lastRevision) != null;
+            return store.getNode(p, rootRevision, lastRevision) != null;
         }
     }
 
@@ -235,7 +235,7 @@ public class DocumentNodeState extends A
             return EmptyNodeState.MISSING_NODE;
         }
         String p = PathUtils.concat(getPath(), name);
-        DocumentNodeState child = store.getNode(p, lastRevision);
+        AbstractDocumentNodeState child = store.getNode(p, rootRevision, lastRevision);
         if (child == null) {
             checkValidName(name);
             return EmptyNodeState.MISSING_NODE;

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java?rev=1749425&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java Tue Jun 21 06:17:44 2016
@@ -0,0 +1,86 @@
+/*
+ * 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 javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkState;
+
+public interface DocumentNodeStateCache {
+    DocumentNodeStateCache NOOP = new DocumentNodeStateCache() {
+        @Nonnull
+        @Override
+        public NodeStateCacheEntry getDocumentNodeState(String path, @Nullable RevisionVector rootRevision,
+                                                        RevisionVector parentLastRev) {
+            return UNKNOWN;
+        }
+    };
+
+    NodeStateCacheEntry MISSING = new NodeStateCacheEntry(NodeStateCacheEntry.EntryType.MISSING);
+
+    NodeStateCacheEntry UNKNOWN = new NodeStateCacheEntry(NodeStateCacheEntry.EntryType.UNKNOWN);
+
+    /**
+     * Get the node for the given path and revision.
+     *
+     * @param path the path of the node.
+     * @param rootRevision
+     * @param readRevision the read revision.
+     * @return the node or {@link MISSING} if no state is there for given path and revision or {@link UNKNOWN} if
+     * cache does not have any knowledge of nodeState for given parameters
+     */
+    @Nonnull
+    NodeStateCacheEntry getDocumentNodeState(String path, RevisionVector rootRevision,
+                                             RevisionVector parentLastRev);
+
+    class NodeStateCacheEntry {
+        private enum EntryType {FOUND, MISSING, UNKNOWN}
+        private final AbstractDocumentNodeState state;
+        private final EntryType entryType;
+
+        public NodeStateCacheEntry(AbstractDocumentNodeState state) {
+            this.state = state;
+            this.entryType = EntryType.FOUND;
+        }
+
+        private NodeStateCacheEntry(EntryType entryType) {
+            this.state = null;
+            this.entryType = entryType;
+        }
+
+        public AbstractDocumentNodeState getState(){
+            checkState(entryType == EntryType.FOUND, "Cannot read state from an entry of type [%s]", entryType);
+            return state;
+        }
+
+        public boolean isUnknown(){
+            return entryType == EntryType.UNKNOWN;
+        }
+
+        public boolean isMissing(){
+            return entryType == EntryType.MISSING;
+        }
+
+        public boolean isFound(){
+            return entryType == EntryType.FOUND;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStateCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1749425&r1=1749424&r2=1749425&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 Tue Jun 21 06:17:44 2016
@@ -87,6 +87,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector;
 import org.apache.jackrabbit.oak.plugins.blob.ReferencedBlob;
 import org.apache.jackrabbit.oak.plugins.document.Branch.BranchCommit;
+import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStateCache.NodeStateCacheEntry;
 import org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCache;
 import org.apache.jackrabbit.oak.plugins.document.persistentCache.broadcast.DynamicBroadcastConfig;
 import org.apache.jackrabbit.oak.plugins.document.util.ReadOnlyDocumentStoreWrapperFactory;
@@ -412,6 +413,8 @@ public final class DocumentNodeStore
 
     private final boolean readOnlyMode;
 
+    private DocumentNodeStateCache nodeStateCache = DocumentNodeStateCache.NOOP;
+
     private final DocumentNodeStoreStatsCollector nodeStoreStatsCollector;
 
     private final StatisticsProvider statisticsProvider;
@@ -868,6 +871,26 @@ public final class DocumentNodeStore
         }
     }
 
+    @CheckForNull
+    AbstractDocumentNodeState getNode(@Nonnull final String path,
+                              @Nonnull final RevisionVector rootRevision,
+                              @Nonnull final RevisionVector rev) {
+        AbstractDocumentNodeState result = nodeCache.getIfPresent(new PathRev(path, rev));
+        if (result == null){
+            NodeStateCacheEntry entry  = nodeStateCache.getDocumentNodeState(path, rootRevision, rev);
+            if (entry.isMissing()){
+                return null;
+            } else if (entry.isFound()){
+                return entry.getState();
+            }
+        } else {
+            return result == missing
+                    || result.equals(missing) ? null : result;
+        }
+
+        return getNode(path, rev);
+    }
+
     /**
      * Get the node for the given path and revision. The returned object might
      * not be modified directly.
@@ -2804,4 +2827,8 @@ public final class DocumentNodeStore
     public DocumentNodeStoreStatsCollector getStatsCollector() {
         return nodeStoreStatsCollector;
     }
+
+    public void setNodeStateCache(DocumentNodeStateCache nodeStateCache) {
+        this.nodeStateCache = nodeStateCache;
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java?rev=1749425&r1=1749424&r2=1749425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java Tue Jun 21 06:17:44 2016
@@ -265,7 +265,7 @@ public class DocumentNodeStoreService {
 
     private final Logger log = LoggerFactory.getLogger(this.getClass());
 
-    private ServiceRegistration reg;
+    private ServiceRegistration nodeStoreReg;
     private final List<Registration> registrations = new ArrayList<Registration>();
     private WhiteboardExecutor executor;
 
@@ -285,6 +285,10 @@ public class DocumentNodeStoreService {
     )
     private volatile DataSource blobDataSource;
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
+            policy = ReferencePolicy.DYNAMIC)
+    private volatile DocumentNodeStateCache nodeStateCache;
+
     private DocumentMK mk;
     private ObserverTracker observerTracker;
     private ComponentContext context;
@@ -345,6 +349,8 @@ public class DocumentNodeStoreService {
 
     private boolean customBlobStore;
 
+    private DocumentNodeStore documentNodeStore;
+
     @Activate
     protected void activate(ComponentContext context, Map<String, ?> config) throws Exception {
         this.context = context;
@@ -501,9 +507,9 @@ public class DocumentNodeStoreService {
         registerJournalGC(mk.getNodeStore());
 
         NodeStore store;
-        DocumentNodeStore mns = mk.getNodeStore();
-        store = mns;
-        observerTracker = new ObserverTracker(mns);
+        documentNodeStore = mk.getNodeStore();
+        store = documentNodeStore;
+        observerTracker = new ObserverTracker(documentNodeStore);
 
         observerTracker.start(context.getBundleContext());
 
@@ -532,7 +538,7 @@ public class DocumentNodeStoreService {
         // OAK-2844: in order to allow DocumentDiscoveryLiteService to directly
         // require a service DocumentNodeStore (instead of having to do an 'instanceof')
         // the registration is now done for both NodeStore and DocumentNodeStore here.
-        reg = context.getBundleContext().registerService(
+        nodeStoreReg = context.getBundleContext().registerService(
             new String[]{
                  NodeStore.class.getName(), 
                  DocumentNodeStore.class.getName(), 
@@ -589,6 +595,21 @@ public class DocumentNodeStoreService {
         unregisterNodeStore();
     }
 
+    @SuppressWarnings("UnusedDeclaration")
+    protected void bindNodeStateCache(DocumentNodeStateCache nodeStateCache) throws IOException {
+       if (documentNodeStore != null){
+           log.info("Registered DocumentNodeStateCache [{}] with DocumentNodeStore", nodeStateCache);
+           documentNodeStore.setNodeStateCache(nodeStateCache);
+       }
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void unbindNodeStateCache(DocumentNodeStateCache nodeStateCache) {
+        if (documentNodeStore != null){
+            documentNodeStore.setNodeStateCache(DocumentNodeStateCache.NOOP);
+        }
+    }
+
     private void unregisterNodeStore() {
         deactivationTimestamp = System.currentTimeMillis();
 
@@ -597,9 +618,9 @@ public class DocumentNodeStoreService {
         }
         registrations.clear();
 
-        if (reg != null) {
-            reg.unregister();
-            reg = null;
+        if (nodeStoreReg != null) {
+            nodeStoreReg.unregister();
+            nodeStoreReg = null;
         }
 
         if (mk != null) {