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 2017/07/25 06:59:51 UTC

svn commit: r1802889 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/ oak-run/src/main/java/org/apache/jackrabbit/oak/index/ oa...

Author: chetanm
Date: Tue Jul 25 06:59:50 2017
New Revision: 1802889

URL: http://svn.apache.org/viewvc?rev=1802889&view=rev
Log:
OAK-6471 - Support adding or updating index definitions via oak-run

Index definitions can now be added via --index-definitions-file option
which must refer to json file having index definitions

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporter.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporterTest.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexOptions.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexerSupport.java
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/OutOfBandIndexer.java
    jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/index/ReindexIT.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporter.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporter.java Tue Jul 25 06:59:50 2017
@@ -40,7 +40,6 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.commit.VisibleEditor;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,6 +47,7 @@ import org.slf4j.LoggerFactory;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
+import static org.apache.jackrabbit.oak.plugins.index.importer.NodeStoreUtils.childBuilder;
 import static org.apache.jackrabbit.oak.plugins.index.importer.NodeStoreUtils.mergeWithConcurrentCheck;
 
 public class IndexImporter {
@@ -62,7 +62,7 @@ public class IndexImporter {
     private final Map<String, IndexImporterProvider> importers = new HashMap<>();
     private final IndexerInfo indexerInfo;
     private final Map<String, File> indexes;
-    private final ListMultimap<String, IndexInfo> asyncLaneToIndexMapping;
+    private ListMultimap<String, IndexInfo> asyncLaneToIndexMapping;
     private final NodeState indexedState;
     private final IndexEditorProvider indexEditorProvider;
     private final AsyncIndexerLock indexerLock;
@@ -77,7 +77,6 @@ public class IndexImporter {
         indexerInfo = IndexerInfo.fromDirectory(indexDir);
         this.indexerLock = indexerLock;
         indexes = indexerInfo.getIndexes();
-        asyncLaneToIndexMapping = mapIndexesToLanes(indexes);
         indexedState = checkNotNull(nodeStore.retrieve(indexerInfo.checkpoint), "Cannot retrieve " +
                 "checkpointed state [%s]", indexerInfo.checkpoint);
     }
@@ -108,8 +107,15 @@ public class IndexImporter {
         importers.put(importerProvider.getType(), importerProvider);
     }
 
-    void switchLanes() throws CommitFailedException {
-        NodeBuilder builder = nodeStore.getRoot().builder();
+    void switchLanes() throws CommitFailedException, IOException {
+        NodeState root = nodeStore.getRoot();
+        NodeBuilder builder = root.builder();
+
+        //Import the updated index definitions from json
+        new IndexDefinitionUpdater(new File(indexDir, IndexDefinitionUpdater.INDEX_DEFINITIONS_JSON)).apply(root, builder);
+
+        asyncLaneToIndexMapping = mapIndexesToLanes(indexes, builder);
+
         for (IndexInfo indexInfo : asyncLaneToIndexMapping.values()){
             NodeBuilder idxBuilder = NodeStoreUtils.childBuilder(builder, indexInfo.indexPath);
             AsyncLaneSwitcher.switchLane(idxBuilder, AsyncLaneSwitcher.getTempLaneName(indexInfo.asyncLaneName));
@@ -212,19 +218,19 @@ public class IndexImporter {
         return checkNotNull(provider, "No IndexImporterProvider found for type [%s]", type);
     }
 
-    private ListMultimap<String, IndexInfo> mapIndexesToLanes(Map<String, File> indexes) {
-        NodeState rootState = nodeStore.getRoot();
+    private ListMultimap<String, IndexInfo> mapIndexesToLanes(Map<String, File> indexes, NodeBuilder rootBuilder) {
         ListMultimap<String, IndexInfo> map = ArrayListMultimap.create();
         for (Map.Entry<String, File> e : indexes.entrySet()) {
             String indexPath = e.getKey();
 
-            NodeState indexState = NodeStateUtils.getNode(rootState, indexPath);
-            checkArgument(indexState.exists(), "No index node found at path [%s]", indexPath);
+            NodeBuilder indexBuilder = childBuilder(rootBuilder, indexPath);
+
+            checkArgument(indexBuilder.exists(), "No index node found at path [%s]", indexPath);
 
-            String type = indexState.getString(IndexConstants.TYPE_PROPERTY_NAME);
+            String type = indexBuilder.getString(IndexConstants.TYPE_PROPERTY_NAME);
             checkNotNull(type, "No 'type' property found for index at path [%s]", indexPath);
 
-            String asyncName = getAsyncLaneName(indexPath, indexState);
+            String asyncName = getAsyncLaneName(indexPath, indexBuilder.getNodeState());
             if (asyncName == null) {
                 asyncName = ASYNC_LANE_SYNC;
             }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporterTest.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporterTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/IndexImporterTest.java Tue Jul 25 06:59:50 2017
@@ -21,6 +21,8 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.io.File;
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Properties;
 import java.util.Set;
 
@@ -28,6 +30,8 @@ import javax.annotation.Nonnull;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.apache.felix.inventory.Format;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -35,6 +39,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
+import org.apache.jackrabbit.oak.plugins.index.inventory.IndexDefinitionPrinter;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexLookup;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
@@ -57,6 +62,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
+import static com.google.common.base.Charsets.UTF_8;
 import static com.google.common.collect.ImmutableSet.of;
 import static java.util.Arrays.asList;
 import static org.apache.jackrabbit.JcrConstants.NT_BASE;
@@ -158,6 +164,40 @@ public class IndexImporterTest {
     }
 
     @Test
+    public void importData_UpdatedIndexDefinition() throws Exception{
+        NodeBuilder builder = store.getRoot().builder();
+        builder.child("idx-a").setProperty("type", "property");
+        builder.child("idx-a").setProperty("foo", "bar");
+
+        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+        createIndexDirs("/idx-a");
+
+        //We remove foo property here
+        builder = store.getRoot().builder();
+        builder.child("idx-a").removeProperty("foo");
+        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+        IndexImporter importer = new IndexImporter(store, temporaryFolder.getRoot(), provider, NOOP_LOCK);
+
+        IndexImporterProvider provider = new IndexImporterProvider() {
+            @Override
+            public void importIndex(NodeState root, NodeBuilder defn, File indexDir) {
+                //Foo property should be set by virtue of import from json
+                assertEquals("bar", defn.getString("foo"));
+            }
+
+            @Override
+            public String getType() {
+                return "property";
+            }
+        };
+        importer.addImporterProvider(provider);
+        importer.switchLanes();
+        importer.importIndexData();
+    }
+
+    @Test
     public void importData_IncrementalUpdate() throws Exception{
         NodeBuilder builder = store.getRoot().builder();
         createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
@@ -328,7 +368,7 @@ public class IndexImporterTest {
                 : PropertyValues.newString(value)));
     }
 
-    private String createIndexDirs(String... indexPaths) throws IOException {
+    private String createIndexDirs(String... indexPaths) throws IOException, CommitFailedException {
         String checkpoint = store.checkpoint(1000000);
         IndexerInfo info = new IndexerInfo(temporaryFolder.getRoot(), checkpoint);
         info.save();
@@ -342,7 +382,17 @@ public class IndexImporterTest {
             indexDir.mkdir();
             PropUtils.writeTo(p, indexMeta, "index info");
         }
-
+        dumpIndexDefinitions(indexPaths);
         return checkpoint;
     }
+
+    private void dumpIndexDefinitions(String... indexPaths) throws IOException, CommitFailedException {
+        IndexDefinitionPrinter printer = new IndexDefinitionPrinter(store, () -> asList(indexPaths));
+        printer.setFilter("{\"properties\":[\"*\", \"-:childOrder\"],\"nodes\":[\"*\", \"-:index-definition\"]}");
+        File file = new File(temporaryFolder.getRoot(), IndexDefinitionUpdater.INDEX_DEFINITIONS_JSON);
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        printer.print(pw, Format.JSON, false);
+        Files.write(sw.toString(), file, UTF_8);
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java Tue Jul 25 06:59:50 2017
@@ -41,6 +41,7 @@ import org.apache.jackrabbit.util.ISO860
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 public class IndexCommand implements Command {
@@ -56,6 +57,7 @@ public class IndexCommand implements Com
     private File definitions;
     private File consistencyCheckReport;
     private Options opts;
+    private IndexOptions indexOpts;
 
     @Override
     public void execute(String... args) throws Exception {
@@ -68,7 +70,7 @@ public class IndexCommand implements Com
         opts.registerOptionsFactory(IndexOptions.FACTORY);
         opts.parseAndConfigure(parser, args);
 
-        IndexOptions indexOpts = opts.getOptionBean(IndexOptions.class);
+        indexOpts = opts.getOptionBean(IndexOptions.class);
 
         //Clean up before setting up NodeStore as the temp
         //directory might be used by NodeStore for cache stuff like persistentCache
@@ -167,7 +169,7 @@ public class IndexCommand implements Com
         checkNotNull(checkpoint, "Checkpoint value is required for reindexing done in read only mode");
 
         Stopwatch w = Stopwatch.createStarted();
-        IndexerSupport indexerSupport = new IndexerSupport(indexHelper, checkpoint);
+        IndexerSupport indexerSupport = createIndexerSupport(indexHelper, checkpoint);
         log.info("Proceeding to index {} upto checkpoint {} {}", indexHelper.getIndexPaths(), checkpoint,
                 indexerSupport.getCheckpointInfo());
 
@@ -271,6 +273,17 @@ public class IndexCommand implements Com
         }
     }
 
+    private IndexerSupport createIndexerSupport(IndexHelper indexHelper, String checkpoint) {
+        IndexerSupport indexerSupport = new IndexerSupport(indexHelper, checkpoint);
+
+        File definitions = indexOpts.getIndexDefinitionsFile();
+        if (definitions != null) {
+            checkArgument(definitions.exists(), "Index definitions file [%s] not found", getPath(definitions));
+            indexerSupport.setIndexDefinitions(definitions);
+        }
+        return indexerSupport;
+    }
+
     private static void setupDirectories(IndexOptions indexOpts) throws IOException {
         if (indexOpts.getOutDir().exists()) {
             if (indexOpts.isImportIndex() &&

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexOptions.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexOptions.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexOptions.java Tue Jul 25 06:59:50 2017
@@ -45,6 +45,7 @@ public class IndexOptions implements Opt
     private final OptionSpec<File> outputDirOpt;
     private final OptionSpec<File> indexImportDir;
     private final OptionSpec<File> preExtractedTextOpt;
+    private final OptionSpec<File> indexDefinitionsOpt;
     private final OptionSpec<Void> stats;
     private final OptionSpec<Void> definitions;
     private final OptionSpec<Void> dumpIndex;
@@ -65,6 +66,9 @@ public class IndexOptions implements Opt
                 .withRequiredArg().ofType(File.class).defaultsTo(new File("indexing-result"));
         preExtractedTextOpt = parser.accepts("pre-extracted-text-dir", "Directory storing pre extracted text")
                 .withRequiredArg().ofType(File.class);
+        indexDefinitionsOpt = parser.accepts("index-definitions-file", "index definition file which " +
+                "include new index definitions or changes to existing index definitions")
+                .withRequiredArg().ofType(File.class);
 
         stats = parser.accepts("index-info", "Collects and dumps various statistics related to the indexes");
         definitions = parser.accepts("index-definitions", "Collects and dumps index definitions");
@@ -139,6 +143,10 @@ public class IndexOptions implements Opt
         return preExtractedTextOpt.value(options);
     }
 
+    public File getIndexDefinitionsFile() {
+        return indexDefinitionsOpt.value(options);
+    }
+
     public File getIndexImportDir() {
         return indexImportDir.value(options);
     }

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexerSupport.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexerSupport.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexerSupport.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexerSupport.java Tue Jul 25 06:59:50 2017
@@ -25,8 +25,14 @@ import java.util.Collections;
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.felix.inventory.Format;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.plugins.index.importer.IndexDefinitionUpdater;
 import org.apache.jackrabbit.oak.plugins.index.importer.IndexerInfo;
+import org.apache.jackrabbit.oak.plugins.index.inventory.IndexDefinitionPrinter;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,6 +53,7 @@ public class IndexerSupport {
     private Map<String, String> checkpointInfo = Collections.emptyMap();
     private final IndexHelper indexHelper;
     private File localIndexDir;
+    private File indexDefinitions;
     private String checkpoint;
 
     public IndexerSupport(IndexHelper indexHelper, String checkpoint) {
@@ -85,7 +92,25 @@ public class IndexerSupport {
         return checkpointedState;
     }
 
+    public void updateIndexDefinitions(NodeState root, NodeBuilder builder) throws IOException, CommitFailedException {
+        if (indexDefinitions != null) {
+            new IndexDefinitionUpdater(indexDefinitions).apply(root, builder);
+        }
+    }
+
+    public void dumpIndexDefinitions(NodeStore nodeStore) throws IOException, CommitFailedException {
+        IndexDefinitionPrinter printer = new IndexDefinitionPrinter(nodeStore, indexHelper.getIndexPathService());
+        printer.setFilter("{\"properties\":[\"*\", \"-:childOrder\"],\"nodes\":[\"*\", \"-:index-definition\"]}");
+        PrinterDumper dumper = new PrinterDumper(getLocalIndexDir(), IndexDefinitionUpdater.INDEX_DEFINITIONS_JSON,
+                false, Format.JSON, printer);
+        dumper.dump();
+    }
+
     public Map<String, String> getCheckpointInfo() {
         return checkpointInfo;
     }
+
+    public void setIndexDefinitions(File indexDefinitions) {
+        this.indexDefinitions = indexDefinitions;
+    }
 }

Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/OutOfBandIndexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/OutOfBandIndexer.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/OutOfBandIndexer.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/index/OutOfBandIndexer.java Tue Jul 25 06:59:50 2017
@@ -67,12 +67,6 @@ public class OutOfBandIndexer implements
      */
     public static final String LOCAL_INDEX_ROOT_DIR = "indexes";
 
-    /**
-     * Checkpoint value which indicate that head state needs to be used
-     * This would be mostly used for testing purpose
-     */
-    private static final String HEAD_AS_CHECKPOINT = "head";
-
     private final Closer closer = Closer.create();
     private final IndexHelper indexHelper;
     private NodeStore copyOnWriteStore;
@@ -95,6 +89,8 @@ public class OutOfBandIndexer implements
 
         switchIndexLanesAndReindexFlag();
         preformIndexUpdate(baseState);
+        switchIndexLanesBack();
+        indexerSupport.dumpIndexDefinitions(copyOnWriteStore);
     }
 
     private File getLocalIndexDir() throws IOException {
@@ -147,6 +143,8 @@ public class OutOfBandIndexer implements
         if (exception != null) {
             throw exception;
         }
+
+        copyOnWriteStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
     }
 
     private IndexEditorProvider createIndexEditorProvider() throws IOException {
@@ -163,8 +161,10 @@ public class OutOfBandIndexer implements
         return luceneIndexHelper.createEditorProvider();
     }
 
-    private void switchIndexLanesAndReindexFlag() throws CommitFailedException {
-        NodeBuilder builder = copyOnWriteStore.getRoot().builder();
+    private void switchIndexLanesAndReindexFlag() throws CommitFailedException, IOException {
+        NodeState root = copyOnWriteStore.getRoot();
+        NodeBuilder builder = root.builder();
+        indexerSupport.updateIndexDefinitions(root, builder);
 
         for (String indexPath : indexHelper.getIndexPaths()) {
             //TODO Do it only for lucene indexes for now
@@ -177,6 +177,19 @@ public class OutOfBandIndexer implements
         log.info("Switched the async lane for indexes at {} to {} and marked them for reindex", indexHelper.getIndexPaths(), REINDEX_LANE);
     }
 
+    private void switchIndexLanesBack() throws CommitFailedException, IOException {
+        NodeState root = copyOnWriteStore.getRoot();
+        NodeBuilder builder = root.builder();
+
+        for (String indexPath : indexHelper.getIndexPaths()) {
+            NodeBuilder idxBuilder = NodeStoreUtils.childBuilder(builder, indexPath);
+            AsyncLaneSwitcher.revertSwitch(idxBuilder, indexPath);
+        }
+
+        copyOnWriteStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        log.info("Switched the async lane for indexes at {} back to there original lanes", indexHelper.getIndexPaths());
+    }
+
     private void configureEstimators(IndexUpdate indexUpdate) {
         StatisticsProvider statsProvider = indexHelper.getStatisticsProvider();
         if (statsProvider instanceof MetricStatisticsProvider) {

Modified: jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/index/ReindexIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/index/ReindexIT.java?rev=1802889&r1=1802888&r2=1802889&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/index/ReindexIT.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/test/java/org/apache/jackrabbit/oak/index/ReindexIT.java Tue Jul 25 06:59:50 2017
@@ -33,6 +33,7 @@ import javax.jcr.query.QueryResult;
 import javax.jcr.query.Row;
 
 import com.google.common.collect.Iterators;
+import com.google.common.io.Files;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
@@ -46,6 +47,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.junit.Test;
 
+import static com.google.common.base.Charsets.UTF_8;
 import static org.apache.jackrabbit.oak.spi.state.NodeStateUtils.getNode;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.not;
@@ -103,6 +105,9 @@ public class ReindexIT extends AbstractI
         createTestData(true);
         fixture.getAsyncIndexUpdate("async").run();
 
+        //Update index to bar property also but do not index yet
+        indexBarPropertyAlso(fixture);
+
         int fooCount = getFooCount(fixture, "foo");
         String checkpoint = fixture.getNodeStore().checkpoint(TimeUnit.HOURS.toMillis(24));
 
@@ -132,7 +137,6 @@ public class ReindexIT extends AbstractI
         RepositoryFixture fixture2 = new RepositoryFixture(storeDir);
         addTestContent(fixture2, "/testNode/b", "foo", 100);
         addTestContent(fixture2, "/testNode/c", "bar", 100);
-        indexBarPropertyAlso(fixture2);
         fixture2.getAsyncIndexUpdate("async").run();
 
         String explain = getQueryPlan(fixture2, "select * from [nt:base] where [bar] is not null");
@@ -228,6 +232,66 @@ public class ReindexIT extends AbstractI
         assertEquals(100, barCount);
     }
 
+    @Test
+    public void newIndexDefinition() throws Exception{
+        createTestData(true);
+        addTestContent(fixture, "/testNode/c", "bar", 100);
+        fixture.getAsyncIndexUpdate("async").run();
+
+        String explain = getQueryPlan(fixture, "select * from [nt:base] where [bar] is not null");
+        assertThat(explain, containsString("traverse"));
+
+        fixture.close();
+
+        IndexCommand command = new IndexCommand();
+
+        String json = "{\n" +
+                "  \"/oak:index/barIndex\": {\n" +
+                "    \"compatVersion\": 2,\n" +
+                "    \"type\": \"lucene\",\n" +
+                "    \"async\": \"async\",\n" +
+                "    \"jcr:primaryType\": \"oak:QueryIndexDefinition\",\n" +
+                "    \"indexRules\": {\n" +
+                "      \"jcr:primaryType\": \"nt:unstructured\",\n" +
+                "      \"nt:base\": {\n" +
+                "        \"jcr:primaryType\": \"nt:unstructured\",\n" +
+                "        \"properties\": {\n" +
+                "          \"jcr:primaryType\": \"nt:unstructured\",\n" +
+                "          \"bar\": {\n" +
+                "            \"name\": \"bar\",\n" +
+                "            \"propertyIndex\": true,\n" +
+                "            \"jcr:primaryType\": \"nt:unstructured\"\n" +
+                "          }\n" +
+                "        }\n" +
+                "      }\n" +
+                "    }\n" +
+                "  }\n" +
+                "}";
+
+        File jsonFile = temporaryFolder.newFile();
+        Files.write(json, jsonFile, UTF_8);
+
+        File outDir = temporaryFolder.newFolder();
+        File storeDir = fixture.getDir();
+        String[] args = {
+                "--index-temp-dir=" + temporaryFolder.newFolder().getAbsolutePath(),
+                "--index-out-dir="  + outDir.getAbsolutePath(),
+                "--index-paths=/oak:index/barIndex",
+                "--index-definitions-file=" + jsonFile.getAbsolutePath(),
+                "--reindex",
+                "--read-write",
+                "--", // -- indicates that options have ended and rest needs to be treated as non option
+                storeDir.getAbsolutePath()
+        };
+
+        command.execute(args);
+
+        RepositoryFixture fixture2 = new RepositoryFixture(storeDir);
+
+        explain = getQueryPlan(fixture2, "select * from [nt:base] where [bar] is not null");
+        assertThat(explain, containsString("/oak:index/barIndex"));
+    }
+
     private void indexBarPropertyAlso(RepositoryFixture fixture2) throws IOException, RepositoryException {
         Session session = fixture2.getAdminSession();
         NodeState idxState = NodeStateUtils.getNode(fixture2.getNodeStore().getRoot(), TEST_INDEX_PATH);