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();