Author: thomasm
Date: Fri Dec 21 12:44:44 2018
New Revision: 1849465

URL: http://svn.apache.org/viewvc?rev=1849465&view=rev
Log:
OAK-7947 Lazy loading of Lucene index files startup

Modified:
    
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexTracker.java
    
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java

Modified: 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexTracker.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexTracker.java?rev=1849465&r1=1849464&r2=1849465&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexTracker.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexTracker.java
 Fri Dec 21 12:44:44 2018
@@ -40,6 +40,7 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.mount.Mounts;
 import org.apache.jackrabbit.oak.spi.state.EqualsDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -207,13 +208,26 @@ public class IndexTracker {
 
     @Nullable
     public LuceneIndexDefinition getIndexDefinition(String indexPath){
-        LuceneIndexNodeManager node = indices.get(indexPath);
-        if (node != null){
-            //Accessing the definition should not require
-            //locking as its immutable state
-            return node.getDefinition();
+        LuceneIndexNodeManager indexNodeManager = indices.get(indexPath);
+        if (indexNodeManager != null) {
+            // Accessing the definition should not require
+            // locking as its immutable state
+            return indexNodeManager.getDefinition();
+        }
+        // fallback - create definition from scratch
+        NodeState node = NodeStateUtils.getNode(root, indexPath);
+        if (!node.exists()) {
+            return null;
+        }
+        // only if there exists a stored index definition
+        if (!node.hasChildNode(INDEX_DEFINITION_NODE)) {
+            return null;
         }
-        return null;
+        if (!isLuceneIndexNode(node)) {
+            return null;
+        }
+        // this will internally use the stored index definition
+        return new LuceneIndexDefinition(root, node, indexPath);
     }
 
     public Set<String> getIndexNodePaths(){

Modified: 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1849465&r1=1849464&r2=1849465&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
 Fri Dec 21 12:44:44 2018
@@ -29,6 +29,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
@@ -46,11 +47,13 @@ import org.apache.jackrabbit.oak.api.Typ
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.commons.PerfLogger;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.fv.SimSearchUtils;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.LuceneIndexWriter;
 import org.apache.jackrabbit.oak.plugins.index.search.FieldNames;
 import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition;
 import 
org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition.IndexingRule;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.property.HybridPropertyIndexLookup;
+import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReader;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.spi.FulltextQueryTermsProvider;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.FacetHelper;
@@ -120,6 +123,8 @@ import org.apache.lucene.search.highligh
 import org.apache.lucene.search.postingshighlight.PostingsHighlighter;
 import org.apache.lucene.search.spell.SuggestWord;
 import org.apache.lucene.search.suggest.Lookup;
+import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
+import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Version;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -688,8 +693,8 @@ public class LucenePropertyIndex extends
     }
 
     @Override
-    protected LuceneIndexNode acquireIndexNode(String indexPath) {
-        return tracker.acquireIndexNode(indexPath);
+    protected LazyLuceneIndexNode acquireIndexNode(String indexPath) {
+        return new LazyLuceneIndexNode(tracker, indexPath);
     }
 
     @Override
@@ -1552,4 +1557,113 @@ public class LucenePropertyIndex extends
             return null;
         }
     }
+
+    /**
+     * A index node implementation that acquires the underlying index only if
+     * actually needed. This is to avoid downloading the index for the planning
+     * phase, if there is no chance that the index is actually used.
+     */
+    static class LazyLuceneIndexNode implements LuceneIndexNode {
+
+        private AtomicBoolean released = new AtomicBoolean();
+        private IndexTracker tracker;
+        private String indexPath;
+        private volatile LuceneIndexNode indexNode;
+
+        LazyLuceneIndexNode(IndexTracker tracker, String indexPath) {
+            this.tracker = tracker;
+            this.indexPath = indexPath;
+        }
+
+        @Override
+        public void release() {
+            if (released.getAndSet(true)) {
+                // already released
+                return;
+            }
+            if (indexNode != null) {
+                indexNode.release();
+            }
+            // to ensure it is not used after releasing
+            indexNode = null;
+            tracker = null;
+            indexPath = null;
+        }
+
+        private void checkNotReleased() {
+            if (released.get()) {
+                throw new IllegalStateException("Already released");
+            }
+        }
+
+        @Override
+        public LuceneIndexDefinition getDefinition() {
+            checkNotReleased();
+            return tracker.getIndexDefinition(indexPath);
+        }
+
+        private LuceneIndexNode getIndexNode() {
+            checkNotReleased();
+            LuceneIndexNode n = indexNode;
+            // double checked locking implemented in the correct way for Java 5
+            // and newer (actually I don't think this is ever called
+            // concurrently right now, but better be save)
+            if (n == null) {
+                synchronized (this) {
+                    n = indexNode;
+                    if (n == null) {
+                        n = indexNode = tracker.acquireIndexNode(indexPath);
+                    }
+                }
+            }
+            return n;
+        }
+
+        @Override
+        public int getIndexNodeId() {
+            return getIndexNode().getIndexNodeId();
+        }
+
+        @Override
+        public LuceneIndexStatistics getIndexStatistics() {
+            return getIndexNode().getIndexStatistics();
+        }
+
+        @Override
+        public IndexSearcher getSearcher() {
+            return getIndexNode().getSearcher();
+        }
+
+        @Override
+        public List<LuceneIndexReader> getPrimaryReaders() {
+            return getIndexNode().getPrimaryReaders();
+        }
+
+        @Override
+        public @Nullable Directory getSuggestDirectory() {
+            return getIndexNode().getSuggestDirectory();
+        }
+
+        @Override
+        public List<LuceneIndexReader> getNRTReaders() {
+            return getIndexNode().getNRTReaders();
+        }
+
+        @Override
+        public @Nullable AnalyzingInfixSuggester getLookup() {
+            return getIndexNode().getLookup();
+        }
+
+        @Override
+        public @Nullable LuceneIndexWriter getLocalWriter() throws IOException 
{
+            return getIndexNode().getLocalWriter();
+        }
+
+        @Override
+        public void refreshReadersOnWriteIfRequired() {
+            getIndexNode().refreshReadersOnWriteIfRequired();
+        }
+
+    }
+
 }


Reply via email to