Author: catholicon
Date: Sat Jan 27 04:46:32 2018
New Revision: 1822372

URL: http://svn.apache.org/viewvc?rev=1822372&view=rev
Log:
OAK-7200: Sync propery indexes don't get planned if /:async exists but indexing 
lane hasn't completed its first cycle

We now also make sure that indexing lane entry exists under /:async before 
certifying if at least one indexing cycle for that lane has been done.

Modified:
    
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManager.java
    
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManagerTest.java

Modified: 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManager.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManager.java?rev=1822372&r1=1822371&r2=1822372&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManager.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManager.java
 Sat Jan 27 04:46:32 2018
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
+import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.ASYNC_PROPERTY_NAME;
+import static 
org.apache.jackrabbit.oak.plugins.index.IndexUtils.getAsyncLaneName;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -35,6 +37,7 @@ import javax.annotation.Nullable;
 import com.google.common.collect.Iterables;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.commons.PerfLogger;
+import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndex;
 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndexFactory;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.ReaderRefreshPolicy;
@@ -68,14 +71,25 @@ public class IndexNodeManager {
         IndexDefinition definition = new IndexDefinition(root, defnNodeState, 
indexPath);
         List<LuceneIndexReader> readers = 
readerFactory.createReaders(definition, defnNodeState, indexPath);
         NRTIndex nrtIndex = nrtFactory != null ? 
nrtFactory.createIndex(definition) : null;
-        if (!readers.isEmpty() || (nrtIndex != null && 
!hasAsyncIndexerRun(root))){
+        if (!readers.isEmpty() || (nrtIndex != null && 
!hasAsyncIndexerRun(root, indexPath, defnNodeState))){
             return new IndexNodeManager(PathUtils.getName(indexPath), 
definition, readers, nrtIndex);
         }
         return null;
     }
 
-    static boolean hasAsyncIndexerRun(NodeState root) {
-        return root.hasChildNode(ASYNC);
+    static boolean hasAsyncIndexerRun(NodeState root, String indexPath, 
NodeState defnNodeState) {
+        boolean hasAsyncNode = root.hasChildNode(ASYNC);
+
+        String asyncLaneName = getAsyncLaneName(defnNodeState, indexPath, 
defnNodeState.getProperty(ASYNC_PROPERTY_NAME));
+
+        if (asyncLaneName != null) {
+            return hasAsyncNode && 
root.getChildNode(ASYNC).hasProperty(asyncLaneName);
+        } else {
+            // useful only for tests - basically non-async index defs which 
don't rely on /:async
+            // hence either readers are there (and this method doesn't come 
into play during open)
+            // OR there is no cycle (where we return false correctly)
+            return  false;
+        }
     }
 
     private static final Logger log = 
LoggerFactory.getLogger(IndexNodeManager.class);

Modified: 
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManagerTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManagerTest.java?rev=1822372&r1=1822371&r2=1822372&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManagerTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNodeManagerTest.java
 Sat Jan 27 04:46:32 2018
@@ -23,6 +23,8 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
 
+import com.google.common.collect.ImmutableList;
+import org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakDirectory;
 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndex;
 import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.NRTIndexFactory;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.ReaderRefreshPolicy;
@@ -30,10 +32,13 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReader;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReaderFactory;
 import 
org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.IndexWriterUtils;
 import org.apache.jackrabbit.oak.spi.mount.Mounts;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
@@ -44,12 +49,15 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
 import static 
com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames.PATH;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.newDoc;
 import static org.apache.jackrabbit.oak.InitialContent.INITIAL_CONTENT;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -106,7 +114,7 @@ public class IndexNodeManagerTest {
     public void nullIndex_NonFreshIndex() throws Exception{
         NodeBuilder builder = createNRTIndex().builder();
         NodeBuilder rootBuilder = root.builder();
-        rootBuilder.child(IndexNodeManager.ASYNC);
+        rootBuilder.child(IndexNodeManager.ASYNC).setProperty("async", 
"async");
         assertNull(IndexNodeManager.open("/foo", rootBuilder.getNodeState(), 
builder.getNodeState(), readerFactory, nrtFactory));
     }
 
@@ -129,6 +137,125 @@ public class IndexNodeManagerTest {
         node.close();
     }
 
+    @Test
+    public void indexOpenedBeforeFistCycle() throws Exception {
+        NodeState nrtIndex = createNRTIndex();
+        NodeState asyncIndex = nrtIndex.builder().setProperty("async", 
ImmutableList.of("async"), STRINGS).getNodeState();
+        NodeState nonAsyncIndex;
+        {
+            NodeBuilder builder = nrtIndex.builder();
+            builder.removeProperty("async");
+            nonAsyncIndex = builder.getNodeState();
+        }
+
+        assertNotNull("nrtIndex; Non existing /:async",
+                IndexNodeManager.open("/foo", root, nrtIndex, readerFactory, 
nrtFactory));
+        assertNull("asyncIndex; Non existing /:async",
+                IndexNodeManager.open("/foo", root, asyncIndex, readerFactory, 
nrtFactory));
+        assertNull("nonAsyncIndex; Non existing /:async",
+                IndexNodeManager.open("/foo", root, nonAsyncIndex, 
readerFactory, nrtFactory));
+
+        // Fake an empty /:async - first indexing cycle isn't done yet
+        builder.child(":async");
+        root = builder.getNodeState();
+
+        assertNotNull("nrtIndex; empty /:async",
+                IndexNodeManager.open("/foo", root, nrtIndex, readerFactory, 
nrtFactory));
+        assertNull("asyncIndex; empty /:async",
+                IndexNodeManager.open("/foo", root, asyncIndex, readerFactory, 
nrtFactory));
+        assertNull("nonAsyncIndex; empty /:async",
+                IndexNodeManager.open("/foo", root, nonAsyncIndex, 
readerFactory, nrtFactory));
+
+
+        // Fake async indexing cycle done with no data
+        builder.child(":async").setProperty("async", "some-random-id");
+        root = builder.getNodeState();
+
+        assertNull("nrtIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, nrtIndex, readerFactory, 
nrtFactory));
+        assertNull("asyncIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, asyncIndex, readerFactory, 
nrtFactory));
+        assertNull("nonAsyncIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, nonAsyncIndex, 
readerFactory, nrtFactory));
+    }
+
+    @Test
+    public void indexWithIndexedDataOpenedBeforeFistCycle() throws Exception {
+        NodeState nrtIndex = createNRTIndex();
+        {
+            NodeBuilder indexBuilder = nrtIndex.builder();
+            IndexDefinition indexDefinition = new IndexDefinition(root, 
indexBuilder.getNodeState(), "/foo");
+            IndexWriterConfig config = 
IndexWriterUtils.getIndexWriterConfig(indexDefinition, false);
+            OakDirectory directory = new OakDirectory(indexBuilder, 
indexDefinition, false);
+            IndexWriter writer = new IndexWriter(directory, config);
+            writer.addDocument(newDoc("/content/en").getFields());
+            writer.close();
+            directory.close();
+            nrtIndex = indexBuilder.getNodeState();
+        }
+        NodeState asyncIndex = nrtIndex.builder().setProperty("async", 
ImmutableList.of("async"), STRINGS).getNodeState();
+        NodeState nonAsyncIndex;
+        {
+            NodeBuilder builder = nrtIndex.builder();
+            builder.removeProperty("async");
+            nonAsyncIndex = builder.getNodeState();
+        }
+
+        // absent or empty /:async doesn't make sense with already indexed 
data available.
+        // So, we're considering only this case.
+        // Fake async indexing cycle done with no data
+        builder.child(":async").setProperty("async", "some-random-id");
+        root = builder.getNodeState();
+
+        assertNotNull("nrtIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, nrtIndex, readerFactory, 
nrtFactory));
+        assertNotNull("asyncIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, asyncIndex, readerFactory, 
nrtFactory));
+        assertNotNull("nonAsyncIndex; fake async cycle run",
+                IndexNodeManager.open("/foo", root, nonAsyncIndex, 
readerFactory, nrtFactory));
+    }
+
+    @Test
+    public void hasIndexingRun() {
+        NodeState nrtIndex = createNRTIndex();
+        NodeState asyncIndex = nrtIndex.builder().setProperty("async", 
ImmutableList.of("async"), STRINGS).getNodeState();
+        NodeState nonAsyncIndex;
+        {
+            NodeBuilder builder = nrtIndex.builder();
+            builder.removeProperty("async");
+            nonAsyncIndex = builder.getNodeState();
+        }
+
+        assertFalse("nrtIndex; Non existing /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", nrtIndex));
+        assertFalse("asyncIndex; Non existing /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", asyncIndex));
+        assertFalse("nonAsyncIndex; Non existing /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", 
nonAsyncIndex));
+
+        // Fake an empty /:async - first indexing cycle isn't done yet
+        builder.child(":async");
+        root = builder.getNodeState();
+
+        assertFalse("nrtIndex; Empty /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", nrtIndex));
+        assertFalse("asyncIndex; Non existing /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", asyncIndex));
+        assertFalse("nonAsyncIndex; Non existing /:async",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", 
nonAsyncIndex));
+
+        // Fake async indexing cycle done
+        builder.child(":async").setProperty("async", "some-random-id");
+        root = builder.getNodeState();
+
+        assertTrue("nrtIndex; fake async cycle run",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", nrtIndex));
+        assertTrue("asyncIndex; fake async cycle run",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", asyncIndex));
+        assertFalse("nonAsyncIndex; fake async cycle run",
+                IndexNodeManager.hasAsyncIndexerRun(root, "/foo", 
nonAsyncIndex));
+    }
+
     private static NodeState createNRTIndex(){
         IndexDefinitionBuilder idx = new IndexDefinitionBuilder();
         idx.indexRule("nt:base").property("foo").propertyIndex();


Reply via email to