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 al...@apache.org on 2014/10/23 12:05:04 UTC

svn commit: r1633783 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/index/ test/java/org/apache/jackrabbit/oak/plugins/index/

Author: alexparvulescu
Date: Thu Oct 23 10:05:04 2014
New Revision: 1633783

URL: http://svn.apache.org/r1633783
Log:
OAK-2203 Full reindexing is triggered when the IndexEditor is missing


Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdateTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java?rev=1633783&r1=1633782&r2=1633783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java Thu Oct 23 10:05:04 2014
@@ -39,6 +39,7 @@ import org.apache.jackrabbit.oak.api.jmx
 import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
 import org.apache.jackrabbit.oak.plugins.commit.ConflictHook;
 import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
+import org.apache.jackrabbit.oak.plugins.index.IndexUpdate.MissingIndexProviderStrategy;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -121,6 +122,8 @@ public class AsyncIndexUpdate implements
      */
     private final Set<String> reindexedDefinitions = new HashSet<String>();
 
+    private final MissingIndexProviderStrategy missingStrategy = new DefaultMissingIndexProviderStrategy();
+
     public AsyncIndexUpdate(@Nonnull String name, @Nonnull NodeStore store,
             @Nonnull IndexEditorProvider provider, boolean switchOnSync) {
         this.name = checkNotNull(name);
@@ -341,7 +344,8 @@ public class AsyncIndexUpdate implements
             NodeBuilder builder = store.getRoot().builder();
 
             IndexUpdate indexUpdate =
-                    new IndexUpdate(provider, name, after, builder, callback);
+                    new IndexUpdate(provider, name, after, builder, callback)
+                    .withMissingProviderStrategy(missingStrategy);
             CommitFailedException exception =
                     EditorDiff.process(VisibleEditor.wrap(indexUpdate), before, after);
             if (exception != null) {
@@ -578,4 +582,24 @@ public class AsyncIndexUpdate implements
         return name.charAt(0) == ':';
     }
 
+    static class DefaultMissingIndexProviderStrategy extends
+            MissingIndexProviderStrategy {
+
+        private final Set<String> ignore = Sets.newHashSet("disabled");
+
+        @Override
+        public void onMissingIndex(String type, NodeBuilder definition)
+                throws CommitFailedException {
+            if (ignore.contains(type)) {
+                return;
+            }
+            throw new CommitFailedException("Async", 2,
+                    "Missing index provider detected");
+        }
+    }
+
+    public boolean isFailing() {
+        return failing;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java?rev=1633783&r1=1633782&r2=1633783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java Thu Oct 23 10:05:04 2014
@@ -52,6 +52,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Objects;
 
 public class IndexUpdate implements Editor {
+
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     private final IndexEditorProvider provider;
@@ -86,6 +87,8 @@ public class IndexUpdate implements Edit
      */
     private final IndexUpdateCallback updateCallback;
 
+    private MissingIndexProviderStrategy missingProvider = new MissingIndexProviderStrategy();
+
     public IndexUpdate(
             IndexEditorProvider provider, String async,
             NodeState root, NodeBuilder builder,
@@ -154,12 +157,15 @@ public class IndexUpdate implements Edit
             NodeBuilder definition = definitions.getChildNode(name);
             if (Objects.equal(async, definition.getString(ASYNC_PROPERTY_NAME))) {
                 String type = definition.getString(TYPE_PROPERTY_NAME);
+                if (type == null) {
+                    // probably not an index def
+                    continue;
+                }
                 boolean shouldReindex = shouldReindex(definition,
                         before, name);
                 Editor editor = provider.getIndexEditor(type, definition, root, updateCallback);
                 if (editor == null) {
-                    // trigger reindexing when an indexer becomes available
-                    definition.setProperty(REINDEX_PROPERTY_NAME, true);
+                    missingProvider.onMissingIndex(type, definition);
                 } else if (shouldReindex) {
                     if (definition.getBoolean(REINDEX_ASYNC_PROPERTY_NAME)
                             && definition.getString(ASYNC_PROPERTY_NAME) == null) {
@@ -272,4 +278,18 @@ public class IndexUpdate implements Edit
         return reindex.keySet();
     }
 
+    public static class MissingIndexProviderStrategy {
+        public void onMissingIndex(String type, NodeBuilder definition)
+                throws CommitFailedException {
+            // trigger reindexing when an indexer becomes available
+            definition.setProperty(REINDEX_PROPERTY_NAME, true);
+        }
+    }
+
+    public IndexUpdate withMissingProviderStrategy(
+            MissingIndexProviderStrategy missingProvider) {
+        this.missingProvider = missingProvider;
+        return this;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java?rev=1633783&r1=1633782&r2=1633783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java Thu Oct 23 10:05:04 2014
@@ -20,6 +20,7 @@ import static com.google.common.collect.
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ASYNC_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexUtils.createIndexDefinition;
 import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider.TYPE;
 import static org.junit.Assert.assertEquals;
@@ -27,6 +28,7 @@ import static org.junit.Assert.assertFal
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -36,12 +38,9 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
 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 +56,10 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
 public class AsyncIndexUpdateTest {
 
     // TODO test index config deletes
@@ -553,6 +556,61 @@ public class AsyncIndexUpdateTest {
                 store.listCheckpoints().size() == 0);
     }
 
+    /**
+     * OAK-2203 Test reindex behavior on an async index when the index provider is missing
+     * for a given type
+     */
+    @Test
+    public void testReindexMissingProvider() throws Exception {
+        MemoryNodeStore store = new MemoryNodeStore();
+        IndexEditorProvider provider = new PropertyIndexEditorProvider();
+
+        NodeBuilder builder = store.getRoot().builder();
+        createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
+                "rootIndex", true, false, ImmutableSet.of("foo"), null)
+                .setProperty(ASYNC_PROPERTY_NAME, "asyncMissing");
+
+        builder.child("testRoot").setProperty("foo", "abc");
+
+        // merge it back in
+        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+        AsyncIndexUpdate async = new AsyncIndexUpdate("asyncMissing", store,
+                provider);
+        //first run, creates a checkpoint and a ref to it as the last indexed state
+        async.run();
+        assertFalse(async.isFailing());
+        assertTrue("Expecting one checkpoint",
+                store.listCheckpoints().size() == 1);
+        String firstCp = store.listCheckpoints().iterator().next();
+        assertEquals(
+                firstCp,
+                store.getRoot().getChildNode(AsyncIndexUpdate.ASYNC)
+                        .getString("asyncMissing"));
+
+        // second run, simulate an index going away
+        provider = CompositeIndexEditorProvider
+                .compose(new ArrayList<IndexEditorProvider>());
+        async = new AsyncIndexUpdate("asyncMissing", store, provider);
+        async.run();
+        assertTrue(async.isFailing());
+        // don't set reindex=true but skip the update
+        PropertyState reindex = store.getRoot()
+                .getChildNode(INDEX_DEFINITIONS_NAME).getChildNode("rootIndex")
+                .getProperty(REINDEX_PROPERTY_NAME);
+        assertTrue(reindex == null || !reindex.getValue(Type.BOOLEAN));
+
+        assertTrue("Expecting one checkpoint",
+                store.listCheckpoints().size() == 1);
+        String secondCp = store.listCheckpoints().iterator().next();
+        assertTrue("Store should not create a new checkpoint",
+                secondCp.equals(firstCp));
+        assertEquals(
+                firstCp,
+                store.getRoot().getChildNode(AsyncIndexUpdate.ASYNC)
+                        .getString("asyncMissing"));
+    }
+
     private static class FaultyIndexEditorProvder implements
             IndexEditorProvider {
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdateTest.java?rev=1633783&r1=1633782&r2=1633783&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdateTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdateTest.java Thu Oct 23 10:05:04 2014
@@ -35,6 +35,7 @@ import static org.junit.Assert.assertTru
 
 import java.util.Set;
 
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
@@ -45,6 +46,7 @@ import org.apache.jackrabbit.oak.query.Q
 import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
@@ -357,6 +359,46 @@ public class IndexUpdateTest {
         "abc"));
     }
 
+    /**
+     * OAK-2203 Test reindex behavior on a sync index when the index provider is missing
+     * for a given type
+     */
+    @Test
+    public void testReindexSyncMissingProvider() throws Exception {
+        EditorHook hook = new EditorHook(new IndexUpdateProvider(
+                emptyProvider()));
+        NodeState before = builder.getNodeState();
+
+        createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME),
+                "rootIndex", true, false, ImmutableSet.of("foo"), null);
+        builder.child(INDEX_DEFINITIONS_NAME).child("azerty");
+        builder.child("testRoot").setProperty("foo", "abc");
+        NodeState after = builder.getNodeState();
+
+        NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY);
+        NodeState rootIndex = checkPathExists(indexed, INDEX_DEFINITIONS_NAME,
+                "rootIndex");
+        PropertyState ps = rootIndex.getProperty(REINDEX_PROPERTY_NAME);
+        assertNotNull(ps);
+        assertTrue(ps.getValue(Type.BOOLEAN));
+
+        NodeState azerty = checkPathExists(indexed, INDEX_DEFINITIONS_NAME,
+                "azerty");
+        assertNull("Node should be ignored by reindexer",
+                azerty.getProperty(REINDEX_PROPERTY_NAME));
+    }
+
+    private static IndexEditorProvider emptyProvider() {
+        return new IndexEditorProvider() {
+            @Override
+            public Editor getIndexEditor(String type, NodeBuilder definition,
+                    NodeState root, IndexUpdateCallback callback)
+                    throws CommitFailedException {
+                return null;
+            }
+        };
+    }
+
     private Set<String> find(PropertyIndexLookup lookup, String name,
             String value) {
         NodeState system = root.getChildNode(JCR_SYSTEM);