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 2012/11/09 12:26:35 UTC
svn commit: r1407425 [1/2] - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/index/
main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
main/java/org/apache/jackrabbit/oak/plugins/index/property/
test/java/org/a...
Author: alexparvulescu
Date: Fri Nov 9 11:26:30 2012
New Revision: 1407425
URL: http://svn.apache.org/viewvc?rev=1407425&view=rev
Log:
OAK-394 IndexManagerHook to manage existing indexes
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiffTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexHookProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/TermFactory.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHookProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexQueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java Fri Nov 9 11:26:30 2012
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.oak.plugins.index;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-
-public class CompositeNodeStateDiff implements NodeStateDiff {
-
- private final List<NodeStateDiff> providers;
-
- public CompositeNodeStateDiff(List<NodeStateDiff> providers) {
- this.providers = providers;
- }
-
- public CompositeNodeStateDiff(NodeStateDiff... providers) {
- this(Arrays.asList(providers));
- }
-
- @Override
- public void propertyAdded(PropertyState after) {
- for (NodeStateDiff d : providers) {
- d.propertyAdded(after);
- }
- }
-
- @Override
- public void propertyChanged(PropertyState before, PropertyState after) {
- for (NodeStateDiff d : providers) {
- d.propertyChanged(before, after);
- }
- }
-
- @Override
- public void propertyDeleted(PropertyState before) {
- for (NodeStateDiff d : providers) {
- d.propertyDeleted(before);
- }
- }
-
- @Override
- public void childNodeAdded(String name, NodeState after) {
- for (NodeStateDiff d : providers) {
- d.childNodeAdded(name, after);
- }
- }
-
- @Override
- public void childNodeChanged(String name, NodeState before, NodeState after) {
- for (NodeStateDiff d : providers) {
- d.childNodeChanged(name, before, after);
- }
- }
-
- @Override
- public void childNodeDeleted(String name, NodeState before) {
- for (NodeStateDiff d : providers) {
- d.childNodeDeleted(name, before);
- }
- }
-}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java?rev=1407425&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java Fri Nov 9 11:26:30 2012
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.index;
+
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+public interface HierarchicalNodeStateDiff<T extends HierarchicalNodeStateDiff<T>>
+ extends NodeStateDiff {
+
+ /**
+ * Generates a child HierarchicalNodeStateDiff, based on the current
+ * NodeStateDiff
+ */
+ T child(String name);
+
+ String getPath();
+
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/HierarchicalNodeStateDiff.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java Fri Nov 9 11:26:30 2012
@@ -19,17 +19,21 @@ package org.apache.jackrabbit.oak.plugin
import java.io.Closeable;
import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
/**
* Represents the content of a QueryIndex as well as a mechanism for keeping
* this content up to date.
*
*/
-public interface IndexHook extends Closeable {
+public interface IndexHook extends HierarchicalNodeStateDiff<IndexHook>,
+ Closeable {
- NodeStateDiff preProcess() throws CommitFailedException;
+ /**
+ * Applies the changes to the index content
+ */
+ void apply() throws CommitFailedException;
- void postProcess() throws CommitFailedException;
+ void reindex(NodeBuilder state) throws CommitFailedException;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java Fri Nov 9 11:26:30 2012
@@ -16,29 +16,15 @@
*/
package org.apache.jackrabbit.oak.plugins.index;
-import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
-import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_UNKNOWN;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
-
import java.io.IOException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.memory.MemoryNodeState;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
/**
* Keeps existing IndexHooks updated.
@@ -64,186 +50,38 @@ public class IndexHookManager implements
throws CommitFailedException {
NodeBuilder builder = after.builder();
- // <path>, <builder>
- Map<String, NodeBuilder> allDefs = new HashMap<String, NodeBuilder>();
- after.compareAgainstBaseState(before,
- new IndexDefDiff(builder, allDefs));
-
- // <type, <<path>, <builder>>
- Map<String, Map<String, NodeBuilder>> updates = new HashMap<String, Map<String, NodeBuilder>>();
- for (String def : allDefs.keySet()) {
- NodeBuilder cb = allDefs.get(def);
- String type = TYPE_UNKNOWN;
- PropertyState typePS = cb.getProperty(TYPE_PROPERTY_NAME);
- if (typePS != null && !typePS.isArray()) {
- type = typePS.getValue(Type.STRING);
- }
- Map<String, NodeBuilder> defs = updates.get(type);
- if (defs == null) {
- defs = new HashMap<String, NodeBuilder>();
- updates.put(type, defs);
- }
- defs.put(def, cb);
- }
-
- // commit
- List<IndexHook> hooks = new ArrayList<IndexHook>();
- List<IndexHook> reindexHooks = new ArrayList<IndexHook>();
-
- for (String type : updates.keySet()) {
- Map<String, NodeBuilder> update = updates.get(type);
- for (String path : update.keySet()) {
- NodeBuilder updateBuiler = update.get(path);
- boolean reindex = getAndResetReindex(updateBuiler);
- if (reindex) {
- reindexHooks.addAll(provider.getIndexHooks(type,
- updateBuiler));
- } else {
- hooks.addAll(provider.getIndexHooks(type, updateBuiler));
- }
- }
- }
- processIndexHooks(reindexHooks, MemoryNodeState.EMPTY_NODE, after);
- processIndexHooks(hooks, before, after);
+ // <type, <path, indexhook>>
+ Map<String, Map<String, List<IndexHook>>> updates = new HashMap<String, Map<String, List<IndexHook>>>();
+ after.compareAgainstBaseState(before, new IndexHookManagerDiff(
+ provider, builder, updates));
+ apply(updates);
return builder.getNodeState();
}
- private void processIndexHooks(List<IndexHook> hooks, NodeState before,
- NodeState after) throws CommitFailedException {
+ private void apply(Map<String, Map<String, List<IndexHook>>> updates)
+ throws CommitFailedException {
try {
-
- List<NodeStateDiff> diffs = new ArrayList<NodeStateDiff>();
- for (IndexHook hook : hooks) {
- diffs.add(hook.preProcess());
- }
- after.compareAgainstBaseState(before, new CompositeNodeStateDiff(
- diffs));
- for (IndexHook hook : hooks) {
- hook.postProcess();
- }
-
- } finally {
- for (IndexHook hook : hooks) {
- try {
- hook.close();
- } catch (IOException e) {
- e.printStackTrace();
- throw new CommitFailedException(
- "Failed to close the index hook", e);
+ for (String type : updates.keySet()) {
+ for (List<IndexHook> hooks : updates.get(type).values()) {
+ for (IndexHook hook : hooks) {
+ hook.apply();
+ }
}
}
- }
- }
-
- protected static boolean getAndResetReindex(NodeBuilder builder) {
- boolean isReindex = false;
- PropertyState ps = builder.getProperty(REINDEX_PROPERTY_NAME);
- if (ps != null) {
- isReindex = ps.getValue(Type.BOOLEAN);
- builder.setProperty(REINDEX_PROPERTY_NAME, false);
- }
- return isReindex;
- }
-
- protected static class IndexDefDiff implements NodeStateDiff {
-
- private final IndexDefDiff parent;
-
- private final NodeBuilder node;
-
- private final String name;
-
- private String path;
-
- private final Map<String, NodeBuilder> updates;
-
- public IndexDefDiff(IndexDefDiff parent, NodeBuilder node, String name,
- String path, Map<String, NodeBuilder> updates) {
- this.parent = parent;
- this.node = node;
- this.name = name;
- this.path = path;
- this.updates = updates;
-
- if (node != null
- && isIndexNodeType(node.getProperty(JCR_PRIMARYTYPE))) {
- node.setProperty(REINDEX_PROPERTY_NAME, true);
- this.updates.put(getPath(), node);
- }
-
- if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
- NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
- for (String indexName : index.getChildNodeNames()) {
- String indexPath = concat(getPath(),
- INDEX_DEFINITIONS_NAME, indexName);
- NodeBuilder indexChild = index.child(indexName);
- if (isIndexNodeType(indexChild.getProperty(JCR_PRIMARYTYPE))) {
- this.updates.put(indexPath, indexChild);
+ } finally {
+ for (String type : updates.keySet()) {
+ for (List<IndexHook> hooks : updates.get(type).values()) {
+ for (IndexHook hook : hooks) {
+ try {
+ hook.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new CommitFailedException(
+ "Failed to close the index hook", e);
+ }
}
}
}
}
-
- public IndexDefDiff(NodeBuilder root, Map<String, NodeBuilder> updates) {
- this(null, root, null, "/", updates);
- }
-
- public IndexDefDiff(IndexDefDiff parent, String name) {
- this(parent, getChildNode(parent.node, name), name, null,
- parent.updates);
- }
-
- private static NodeBuilder getChildNode(NodeBuilder node, String name) {
- if (node != null && node.hasChildNode(name)) {
- return node.child(name);
- } else {
- return null;
- }
- }
-
- private String getPath() {
- if (path == null) { // => parent != null
- path = concat(parent.getPath(), name);
- }
- return path;
- }
-
- @Override
- public void propertyAdded(PropertyState after) {
- }
-
- @Override
- public void propertyChanged(PropertyState before, PropertyState after) {
- }
-
- @Override
- public void propertyDeleted(PropertyState before) {
- }
-
- @Override
- public void childNodeAdded(String name, NodeState after) {
- childNodeChanged(name, MemoryNodeState.EMPTY_NODE, after);
- }
-
- @Override
- public void childNodeChanged(String name, NodeState before,
- NodeState after) {
- if (NodeStateUtils.isHidden(name)) {
- return;
- }
- after.compareAgainstBaseState(before, new IndexDefDiff(this, name));
- }
-
- @Override
- public void childNodeDeleted(String name, NodeState before) {
- }
-
- private boolean isIndexNodeType(PropertyState ps) {
- return ps != null
- && !ps.isArray()
- && ps.getValue(Type.STRING).equals(
- INDEX_DEFINITIONS_NODE_TYPE);
- }
-
}
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java?rev=1407425&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java Fri Nov 9 11:26:30 2012
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.index;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_UNKNOWN;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+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.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Acts as a composite NodeStateDiff, it delegates all the diff's events to the
+ * existing IndexHooks.
+ *
+ * This allows for a simultaneous update of all the indexes via a single
+ * traversal of the changes.
+ *
+ *
+ */
+class IndexHookManagerDiff implements NodeStateDiff {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(IndexHookManagerDiff.class);
+
+ private final IndexHookProvider provider;
+
+ private final IndexHookManagerDiff parent;
+
+ private final NodeBuilder node;
+
+ private final String name;
+
+ private String path;
+
+ /**
+ * <type, <path, indexhook>>
+ */
+ private final Map<String, Map<String, List<IndexHook>>> updates;
+
+ private IndexHookManagerDiff(IndexHookProvider provider,
+ IndexHookManagerDiff parent, NodeBuilder node, String name,
+ String path, Map<String, Map<String, List<IndexHook>>> updates)
+ throws CommitFailedException {
+ this.provider = provider;
+ this.parent = parent;
+ this.node = node;
+ this.name = name;
+ this.path = path;
+ this.updates = updates;
+
+ if (node != null && isIndexNodeType(node.getProperty(JCR_PRIMARYTYPE))) {
+ // to prevent double-reindex we only call reindex if:
+ // - the flag exists and is set to true
+ // OR
+ // - the flag does not exist
+ boolean reindex = node.getProperty(REINDEX_PROPERTY_NAME) == null
+ || node.getProperty(REINDEX_PROPERTY_NAME).getValue(
+ Type.BOOLEAN);
+ if (reindex) {
+ node.setProperty(REINDEX_PROPERTY_NAME, true);
+ String type = TYPE_UNKNOWN;
+ PropertyState typePS = node.getProperty(TYPE_PROPERTY_NAME);
+ if (typePS != null && !typePS.isArray()) {
+ type = typePS.getValue(Type.STRING);
+ }
+ // TODO this is kinda fragile
+ NodeBuilder rebuildBuilder = parent.parent.node;
+ String relativePath = PathUtils.getAncestorPath(getPath(), 2);
+ // find parent index by type and trigger a full reindex
+ List<IndexHook> indexes = getIndexesWithRelativePaths(
+ relativePath, getIndexes(type));
+ for (IndexHook ih : indexes) {
+ ih.reindex(rebuildBuilder);
+ }
+ }
+ }
+
+ if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
+ Set<String> existingTypes = new HashSet<String>();
+ Set<String> reindexTypes = new HashSet<String>();
+
+ NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
+ for (String indexName : index.getChildNodeNames()) {
+ NodeBuilder indexChild = index.child(indexName);
+ if (isIndexNodeType(indexChild.getProperty(JCR_PRIMARYTYPE))) {
+ // this reindex should only happen when the flag is set
+ // before the index impl is online
+ boolean reindex = indexChild
+ .getProperty(REINDEX_PROPERTY_NAME) != null
+ && indexChild.getProperty(REINDEX_PROPERTY_NAME)
+ .getValue(Type.BOOLEAN);
+ String type = TYPE_UNKNOWN;
+ PropertyState typePS = indexChild
+ .getProperty(TYPE_PROPERTY_NAME);
+ if (typePS != null && !typePS.isArray()) {
+ type = typePS.getValue(Type.STRING);
+ }
+ if (reindex) {
+ reindexTypes.add(type);
+ }
+ existingTypes.add(type);
+ }
+ }
+ existingTypes.remove(TYPE_UNKNOWN);
+ reindexTypes.remove(TYPE_UNKNOWN);
+ for (String type : existingTypes) {
+ Map<String, List<IndexHook>> byType = this.updates.get(type);
+ if (byType == null) {
+ byType = new TreeMap<String, List<IndexHook>>();
+ this.updates.put(type, byType);
+ }
+ List<IndexHook> hooks = byType.get(getPath());
+ if (hooks == null) {
+ hooks = Lists.newArrayList();
+ byType.put(getPath(), hooks);
+ }
+ if (reindexTypes.contains(type)) {
+ for (IndexHook ih : provider.getIndexHooks(type, node)) {
+ ih.reindex(node);
+ // TODO proper cleanup of resources in the case of an
+ // exception?
+ hooks.add(ih);
+ }
+ } else {
+ hooks.addAll(provider.getIndexHooks(type, node));
+ }
+ }
+ }
+ }
+
+ private IndexHookManagerDiff(IndexHookProvider provider,
+ IndexHookManagerDiff parent, String name)
+ throws CommitFailedException {
+ this(provider, parent, getChildNode(parent.node, name), name, null,
+ parent.updates);
+ }
+
+ public IndexHookManagerDiff(IndexHookProvider provider, NodeBuilder root,
+ Map<String, Map<String, List<IndexHook>>> updates)
+ throws CommitFailedException {
+ this(provider, null, root, null, "/", updates);
+ }
+
+ private static NodeBuilder getChildNode(NodeBuilder node, String name) {
+ if (node != null && node.hasChildNode(name)) {
+ return node.child(name);
+ } else {
+ return null;
+ }
+ }
+
+ private String getPath() {
+ if (path == null) { // => parent != null
+ path = concat(parent.getPath(), name);
+ }
+ return path;
+ }
+
+ /**
+ *
+ * Returns IndexHooks of all types that have the best match (are situated
+ * the closest on the hierarchy) for the given path.
+ *
+ */
+ private Map<String, List<IndexHook>> getIndexes() {
+ Map<String, List<IndexHook>> hooks = new HashMap<String, List<IndexHook>>();
+ for (String type : this.updates.keySet()) {
+ Map<String, List<IndexHook>> newIndexes = getIndexes(type);
+ for (String key : newIndexes.keySet()) {
+ if (hooks.containsKey(key)) {
+ hooks.get(key).addAll(newIndexes.get(key));
+ } else {
+ hooks.put(key, newIndexes.get(key));
+ }
+ }
+ }
+ return hooks;
+ }
+
+ /**
+ *
+ * Returns IndexHooks of the given type that have the best match (are
+ * situated the closest on the hierarchy) for the current path.
+ *
+ */
+ private Map<String, List<IndexHook>> getIndexes(String type) {
+ Map<String, List<IndexHook>> hooks = new HashMap<String, List<IndexHook>>();
+ Map<String, List<IndexHook>> indexes = this.updates.get(type);
+ if (indexes != null && !indexes.isEmpty()) {
+ Iterator<String> iterator = indexes.keySet().iterator();
+ String bestMatch = iterator.next();
+ while (iterator.hasNext()) {
+ String key = iterator.next();
+ if (PathUtils.isAncestor(key, getPath())) {
+ bestMatch = key;
+ } else {
+ break;
+ }
+ }
+ List<IndexHook> existing = hooks.get(bestMatch);
+ if (existing == null) {
+ existing = new ArrayList<IndexHook>();
+ hooks.put(bestMatch, existing);
+ }
+ existing.addAll(indexes.get(bestMatch));
+ }
+ return hooks;
+ }
+
+ /**
+ * Fixes the relative paths on the best matching indexes so updates apply
+ * properly
+ */
+ private List<IndexHook> getIndexesWithRelativePaths(String path,
+ Map<String, List<IndexHook>> bestMatches) {
+ List<IndexHook> hooks = new ArrayList<IndexHook>();
+ for (String relativePath : bestMatches.keySet()) {
+ for (IndexHook update : bestMatches.get(relativePath)) {
+ IndexHook u = update;
+ String downPath = path.substring(relativePath.length());
+ for (String p : PathUtils.elements(downPath)) {
+ u = u.child(p);
+ }
+ hooks.add(u);
+ }
+ }
+ return hooks;
+ }
+
+ private static boolean isIndexNodeType(PropertyState ps) {
+ return ps != null && !ps.isArray()
+ && ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE);
+ }
+
+ // -----------------------------------------------------< NodeStateDiff >--
+
+ @Override
+ public void propertyAdded(PropertyState after) {
+ for (IndexHook update : getIndexesWithRelativePaths(getPath(),
+ getIndexes())) {
+ update.propertyAdded(after);
+ }
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) {
+ for (IndexHook update : getIndexesWithRelativePaths(getPath(),
+ getIndexes())) {
+ update.propertyChanged(before, after);
+ }
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) {
+ for (IndexHook update : getIndexesWithRelativePaths(getPath(),
+ getIndexes())) {
+ update.propertyDeleted(before);
+ }
+ }
+
+ @Override
+ public void childNodeAdded(String name, NodeState after) {
+ childNodeChanged(name, MemoryNodeState.EMPTY_NODE, after);
+ }
+
+ @Override
+ public void childNodeChanged(String name, NodeState before, NodeState after) {
+ if (NodeStateUtils.isHidden(name)) {
+ return;
+ }
+ getIndexesWithRelativePaths(concat(getPath(), name), getIndexes());
+
+ try {
+ after.compareAgainstBaseState(before, new IndexHookManagerDiff(
+ provider, this, name));
+ } catch (CommitFailedException e) {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void childNodeDeleted(String name, NodeState before) {
+ childNodeChanged(name, before, MemoryNodeState.EMPTY_NODE);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManagerDiff.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookProvider.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookProvider.java Fri Nov 9 11:26:30 2012
@@ -35,11 +35,19 @@ public interface IndexHookProvider {
* <code>type</code> param is of an unknown value, the provider is expected
* to return an empty list.
*
+ * <p>
+ * The <code>builder</code> must point to the repository content node, not
+ * the index content node. Each <code>IndexHook</code> implementation will
+ * have to drill down to its specific index content, and possibly deal with
+ * multiple indexes of the same type.
+ * </p>
+ *
* @param type
* the index type
* @param builder
- * the node state builder that will be used for updates
- * @return a list of index hooks
+ * the node state builder of the content node that will be used
+ * for updates
+ * @return a list of index hooks of the given type
*/
@Nonnull
List<? extends IndexHook> getIndexHooks(String type, NodeBuilder builder);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java Fri Nov 9 11:26:30 2012
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.oak.plugins.index.lucene;
-
-import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
-
-import java.io.IOException;
-
-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.IndexHook;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.analysis.standard.StandardAnalyzer;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.util.Version;
-
-/**
- * This class updates a Lucene index when node content is changed.
- */
-class LuceneEditor implements IndexHook, LuceneIndexConstants {
-
- private static final Version VERSION = Version.LUCENE_40;
-
- private static final Analyzer ANALYZER = new StandardAnalyzer(VERSION);
-
- private static final IndexWriterConfig config = getIndexWriterConfig();
-
- private LuceneIndexDiff diff;
-
- private static IndexWriterConfig getIndexWriterConfig() {
- // FIXME: Hack needed to make Lucene work in an OSGi environment
- Thread thread = Thread.currentThread();
- ClassLoader loader = thread.getContextClassLoader();
- thread.setContextClassLoader(IndexWriterConfig.class.getClassLoader());
- try {
- return new IndexWriterConfig(VERSION, ANALYZER);
- } finally {
- thread.setContextClassLoader(loader);
- }
- }
-
- private final NodeBuilder root;
-
- public LuceneEditor(NodeBuilder root) {
- this.root = root;
- }
-
- // -----------------------------------------------------< IndexHook >--
-
- @Override
- public NodeStateDiff preProcess() throws CommitFailedException {
- try {
- IndexWriter writer = new IndexWriter(new ReadWriteOakDirectory(
- getIndexNode(root).child(INDEX_DATA_CHILD_NAME)), config);
- diff = new LuceneIndexDiff(writer, root, "/");
- return diff;
- } catch (IOException e) {
- e.printStackTrace();
- throw new CommitFailedException(
- "Failed to create writer for the full text search index", e);
- }
- }
-
- private static NodeBuilder getIndexNode(NodeBuilder node) {
- if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
- NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
- for (String indexName : index.getChildNodeNames()) {
- NodeBuilder child = index.child(indexName);
- if (isIndexNodeType(child.getProperty(JCR_PRIMARYTYPE))
- && isIndexType(child.getProperty(TYPE_PROPERTY_NAME),
- TYPE_LUCENE)) {
- return child;
- }
- }
- }
- // did not find a proper child, will use root directly
- return node;
- }
-
- private static boolean isIndexNodeType(PropertyState ps) {
- return ps != null && !ps.isArray()
- && ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE);
- }
-
- private static boolean isIndexType(PropertyState ps, String type) {
- return ps != null && !ps.isArray()
- && ps.getValue(Type.STRING).equals(type);
- }
-
- @Override
- public void postProcess() throws CommitFailedException {
- try {
- diff.postProcess();
- } catch (IOException e) {
- e.printStackTrace();
- throw new CommitFailedException(
- "Failed to update the full text search index", e);
- }
- }
-
- @Override
- public void close() throws IOException {
- diff.close();
- diff = null;
- }
-}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java Fri Nov 9 11:26:30 2012
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.oak.plugins.index.lucene;
-
-import java.io.IOException;
-
-import javax.annotation.Nonnull;
-
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.plugins.index.IndexHook;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-
-/**
- * {@link IndexHook} implementation that is responsible for keeping the
- * {@link LuceneIndex} up to date
- *
- * @see LuceneIndex
- *
- */
-public class LuceneHook implements IndexHook {
-
- private final NodeBuilder builder;
-
- private IndexHook luceneEditor;
-
- public LuceneHook(NodeBuilder builder) {
- this.builder = builder;
- }
-
- // -----------------------------------------------------< IndexHook >--
-
- @Override
- @Nonnull
- public NodeStateDiff preProcess() throws CommitFailedException {
- luceneEditor = new LuceneEditor(builder);
- return luceneEditor.preProcess();
- }
-
- @Override
- public void postProcess() throws CommitFailedException {
- luceneEditor.postProcess();
- }
-
- @Override
- public void close() throws IOException {
- try {
- if (luceneEditor != null) {
- luceneEditor.close();
- }
- } finally {
- luceneEditor = null;
- }
- }
-}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java Fri Nov 9 11:26:30 2012
@@ -20,7 +20,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.jcr.RepositoryException;
@@ -35,11 +34,10 @@ import org.apache.jackrabbit.oak.core.Re
import org.apache.jackrabbit.oak.plugins.index.IndexDefinition;
import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
-import org.apache.jackrabbit.oak.query.index.IndexRowImpl;
import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Cursors;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
-import org.apache.jackrabbit.oak.spi.query.IndexRow;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -137,7 +135,7 @@ public class LuceneIndex implements Quer
}
if (!builder.hasChildNode(INDEX_DATA_CHILD_NAME)) {
// index not initialized yet
- return new PathCursor(Collections.<String> emptySet());
+ return Cursors.newPathCursor(Collections.<String> emptySet());
}
builder = builder.child(INDEX_DATA_CHILD_NAME);
@@ -167,7 +165,7 @@ public class LuceneIndex implements Quer
}
LOG.debug("query via {} took {} ms.", this,
System.currentTimeMillis() - s);
- return new PathCursor(paths);
+ return Cursors.newPathCursor(paths);
} finally {
reader.close();
}
@@ -176,7 +174,7 @@ public class LuceneIndex implements Quer
}
} catch (IOException e) {
e.printStackTrace();
- return new PathCursor(Collections.<String> emptySet());
+ return Cursors.newPathCursor(Collections.<String> emptySet());
}
}
@@ -202,7 +200,7 @@ public class LuceneIndex implements Quer
qs.add(new PrefixQuery(newPathTerm(path)));
break;
case DIRECT_CHILDREN:
- // FIXME
+ // FIXME OAK-420
if (!path.endsWith("/")) {
path += "/";
}
@@ -358,38 +356,6 @@ public class LuceneIndex implements Quer
return new TermQuery(new Term(name, type.getName()));
}
- /**
- * A cursor over the resulting paths.
- */
- private static class PathCursor implements Cursor {
-
- private final Iterator<String> iterator;
-
- private String path;
-
- public PathCursor(Collection<String> paths) {
- this.iterator = paths.iterator();
- }
-
- @Override
- public boolean next() {
- if (iterator.hasNext()) {
- path = iterator.next();
- return true;
- } else {
- path = null;
- return false;
- }
- }
-
- @Override
- public IndexRow currentRow() {
- // TODO support jcr:score and possibly rep:exceprt
- return new IndexRowImpl(path);
- }
-
- }
-
@Override
public String toString() {
return "LuceneIndex [index=" + index + "]";
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java Fri Nov 9 11:26:30 2012
@@ -17,6 +17,10 @@
package org.apache.jackrabbit.oak.plugins.index.lucene;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.util.Version;
+import org.apache.tika.Tika;
public interface LuceneIndexConstants extends IndexConstants {
@@ -24,4 +28,10 @@ public interface LuceneIndexConstants ex
String INDEX_DATA_CHILD_NAME = ":data";
+ Version VERSION = Version.LUCENE_40;
+
+ Analyzer ANALYZER = new StandardAnalyzer(VERSION);
+
+ Tika TIKA = new Tika();
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java Fri Nov 9 11:26:30 2012
@@ -16,74 +16,124 @@
*/
package org.apache.jackrabbit.oak.plugins.index.lucene;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPathField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPropertyField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
-import java.io.Closeable;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
-import javax.jcr.PropertyType;
-
-import org.apache.jackrabbit.oak.api.Blob;
+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.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.index.IndexHook;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.tika.Tika;
-import org.apache.tika.exception.TikaException;
-
-public class LuceneIndexDiff implements NodeStateDiff, Closeable {
- private static final Tika TIKA = new Tika();
+/**
+ * {@link IndexHook} implementation that is responsible for keeping the
+ * {@link LuceneIndex} up to date
+ *
+ * @see LuceneIndex
+ *
+ */
+public class LuceneIndexDiff implements IndexHook, LuceneIndexConstants {
- private final IndexWriter writer;
+ private final LuceneIndexDiff parent;
private final NodeBuilder node;
- private final String path;
+ private final String name;
- private boolean modified;
+ private String path;
- private IOException exception;
+ private final Map<String, LuceneIndexUpdate> updates;
- public LuceneIndexDiff(IndexWriter writer, NodeBuilder node, String path) {
- this.writer = writer;
+ private LuceneIndexDiff(LuceneIndexDiff parent, NodeBuilder node,
+ String name, String path, Map<String, LuceneIndexUpdate> updates) {
+ this.parent = parent;
this.node = node;
+ this.name = name;
this.path = path;
+ this.updates = updates;
+
+ if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
+ NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
+ for (String indexName : index.getChildNodeNames()) {
+ NodeBuilder child = index.child(indexName);
+ if (isIndexNode(child) && !this.updates.containsKey(getPath())) {
+ this.updates.put(getPath(), new LuceneIndexUpdate(
+ getPath(), child));
+ }
+ }
+ }
+ if (node != null && name != null && !NodeStateUtils.isHidden(name)) {
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.insert(getPath(), node);
+ }
+ }
+ }
+
+ private LuceneIndexDiff(LuceneIndexDiff parent, String name) {
+ this(parent, getChildNode(parent.node, name), name, null,
+ parent.updates);
}
- public void postProcess() throws IOException {
- if (exception != null) {
- throw exception;
- }
- if (modified) {
- writer.updateDocument(newPathTerm(path),
- makeDocument(path, node.getNodeState()));
+ public LuceneIndexDiff(NodeBuilder root) {
+ this(null, root, null, "/", new HashMap<String, LuceneIndexUpdate>());
+ }
+
+ private static NodeBuilder getChildNode(NodeBuilder node, String name) {
+ if (node != null && node.hasChildNode(name)) {
+ return node.child(name);
+ } else {
+ return null;
+ }
+ }
+
+ public String getPath() {
+ if (path == null) { // => parent != null
+ path = concat(parent.getPath(), name);
}
+ return path;
+ }
+
+ private static boolean isIndexNode(NodeBuilder node) {
+ PropertyState ps = node.getProperty(JCR_PRIMARYTYPE);
+ boolean isNodeType = ps != null && !ps.isArray()
+ && ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE);
+ if (!isNodeType) {
+ return false;
+ }
+ PropertyState type = node.getProperty(TYPE_PROPERTY_NAME);
+ boolean isIndexType = type != null && !type.isArray()
+ && type.getValue(Type.STRING).equals(TYPE_LUCENE);
+ return isIndexType;
}
// -----------------------------------------------------< NodeStateDiff >--
@Override
public void propertyAdded(PropertyState after) {
- modified = true;
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.insert(getPath(), node);
+ }
}
@Override
public void propertyChanged(PropertyState before, PropertyState after) {
- modified = true;
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.insert(getPath(), node);
+ }
}
@Override
public void propertyDeleted(PropertyState before) {
- modified = true;
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.insert(getPath(), node);
+ }
}
@Override
@@ -91,22 +141,8 @@ public class LuceneIndexDiff implements
if (NodeStateUtils.isHidden(name)) {
return;
}
- if (exception == null) {
- try {
- addSubtree(concat(path, name), after);
- } catch (IOException e) {
- exception = e;
- }
- }
- }
-
- private void addSubtree(String path, NodeState state) throws IOException {
- writer.updateDocument(newPathTerm(path), makeDocument(path, state));
- for (ChildNodeEntry entry : state.getChildNodeEntries()) {
- if (NodeStateUtils.isHidden(entry.getName())) {
- continue;
- }
- addSubtree(concat(path, entry.getName()), entry.getNodeState());
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.insert(concat(getPath(), name), node);
}
}
@@ -115,16 +151,7 @@ public class LuceneIndexDiff implements
if (NodeStateUtils.isHidden(name)) {
return;
}
- if (exception == null && node.hasChildNode(name)) {
- LuceneIndexDiff diff = new LuceneIndexDiff(writer,
- node.child(name), concat(path, name));
- after.compareAgainstBaseState(before, diff);
- try {
- diff.postProcess();
- } catch (IOException e) {
- exception = e;
- }
- }
+ after.compareAgainstBaseState(before, child(name));
}
@Override
@@ -132,60 +159,45 @@ public class LuceneIndexDiff implements
if (NodeStateUtils.isHidden(name)) {
return;
}
- if (exception == null) {
- try {
- deleteSubtree(concat(path, name), before);
- } catch (IOException e) {
- exception = e;
- }
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.remove(concat(getPath(), name));
}
}
- private void deleteSubtree(String path, NodeState state) throws IOException {
- writer.deleteDocuments(newPathTerm(path));
- for (ChildNodeEntry entry : state.getChildNodeEntries()) {
- if (NodeStateUtils.isHidden(entry.getName())) {
- continue;
- }
- deleteSubtree(concat(path, entry.getName()), entry.getNodeState());
+ // -----------------------------------------------------< IndexHook >--
+
+ @Override
+ public void apply() throws CommitFailedException {
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.apply();
}
}
- private static Document makeDocument(String path, NodeState state) {
- Document document = new Document();
- document.add(newPathField(path));
- for (PropertyState property : state.getProperties()) {
- String pname = property.getName();
- switch (property.getType().tag()) {
- case PropertyType.BINARY:
- for (Blob v : property.getValue(Type.BINARIES)) {
- document.add(newPropertyField(pname, parseStringValue(v)));
- }
- break;
- default:
- for (String v : property.getValue(Type.STRINGS)) {
- document.add(newPropertyField(pname, v));
- }
- break;
+ @Override
+ public void reindex(NodeBuilder state) throws CommitFailedException {
+ boolean reindex = false;
+ for (LuceneIndexUpdate update : updates.values()) {
+ if (update.getAndResetReindexFlag()) {
+ reindex = true;
}
}
- return document;
- }
-
- private static String parseStringValue(Blob v) {
- try {
- return TIKA.parseToString(v.getNewStream());
- } catch (IOException e) {
- } catch (TikaException e) {
+ if (reindex) {
+ state.getNodeState().compareAgainstBaseState(
+ MemoryNodeState.EMPTY_NODE,
+ new LuceneIndexDiff(null, state, null, "/", updates));
}
- return "";
}
- // -----------------------------------------------------< Closeable >--
+ @Override
+ public IndexHook child(String name) {
+ return new LuceneIndexDiff(this, name);
+ }
@Override
public void close() throws IOException {
- writer.close();
+ for (LuceneIndexUpdate update : updates.values()) {
+ update.close();
+ }
+ updates.clear();
}
-
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexHookProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexHookProvider.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexHookProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexHookProvider.java Fri Nov 9 11:26:30 2012
@@ -29,9 +29,9 @@ import org.apache.jackrabbit.oak.spi.sta
import com.google.common.collect.ImmutableList;
/**
- * Service that provides Lucene based IndexHooks
+ * Service that provides Lucene based {@link IndexHook}s
*
- * @see LuceneHook
+ * @see LuceneIndexDiff
* @see IndexHookProvider
*
*/
@@ -43,7 +43,7 @@ public class LuceneIndexHookProvider imp
public List<? extends IndexHook> getIndexHooks(String type,
NodeBuilder builder) {
if (TYPE_LUCENE.equals(type)) {
- return ImmutableList.of(new LuceneHook(builder));
+ return ImmutableList.of(new LuceneIndexDiff(builder));
}
return ImmutableList.of();
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java?rev=1407425&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java Fri Nov 9 11:26:30 2012
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.index.lucene;
+
+import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPathField;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPropertyField;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.Blob;
+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.spi.state.ChildNodeEntry;
+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.lucene.document.Document;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.search.PrefixQuery;
+import org.apache.tika.exception.TikaException;
+
+import com.google.common.base.Preconditions;
+
+class LuceneIndexUpdate implements Closeable, LuceneIndexConstants {
+
+ private static IndexWriterConfig getIndexWriterConfig() {
+ // FIXME: Hack needed to make Lucene work in an OSGi environment
+ Thread thread = Thread.currentThread();
+ ClassLoader loader = thread.getContextClassLoader();
+ thread.setContextClassLoader(IndexWriterConfig.class.getClassLoader());
+ try {
+ return new IndexWriterConfig(VERSION, ANALYZER);
+ } finally {
+ thread.setContextClassLoader(loader);
+ }
+ }
+
+ private static final IndexWriterConfig config = getIndexWriterConfig();
+
+ private final String path;
+
+ private final NodeBuilder index;
+
+ private final Map<String, NodeState> insert = new TreeMap<String, NodeState>();
+
+ private final Set<String> remove = new TreeSet<String>();
+
+ public LuceneIndexUpdate(String path, NodeBuilder index) {
+ this.path = path;
+ this.index = index;
+ }
+
+ public void insert(String path, NodeBuilder value) {
+ Preconditions.checkArgument(path.startsWith(this.path));
+ if (!insert.containsKey(path)) {
+ String key = path.substring(this.path.length());
+ if ("".equals(key)) {
+ key = "/";
+ }
+ // null value can come from a deleted node, followed by a deleted
+ // property event which would trigger an update on the previously
+ // deleted node
+ if (value != null) {
+ insert.put(key, value.getNodeState());
+ }
+ }
+ }
+
+ public void remove(String path) {
+ Preconditions.checkArgument(path.startsWith(this.path));
+ remove.add(path.substring(this.path.length()));
+ }
+
+ boolean getAndResetReindexFlag() {
+ boolean reindex = index.getProperty(REINDEX_PROPERTY_NAME) != null
+ && index.getProperty(REINDEX_PROPERTY_NAME).getValue(
+ Type.BOOLEAN);
+ index.setProperty(REINDEX_PROPERTY_NAME, false);
+ return reindex;
+ }
+
+ public void apply() throws CommitFailedException {
+ if(remove.isEmpty() && insert.isEmpty()){
+ return;
+ }
+ IndexWriter writer = null;
+ try {
+ writer = new IndexWriter(new ReadWriteOakDirectory(
+ index.child(INDEX_DATA_CHILD_NAME)), config);
+ for (String p : remove) {
+ deleteSubtreeWriter(writer, p);
+ }
+ for (String p : insert.keySet()) {
+ NodeState ns = insert.get(p);
+ addSubtreeWriter(writer, p, ns);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new CommitFailedException(
+ "Failed to update the full text search index", e);
+ } finally {
+ remove.clear();
+ insert.clear();
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ //
+ }
+ }
+ }
+ }
+
+ private void deleteSubtreeWriter(IndexWriter writer, String path)
+ throws IOException {
+ // TODO verify the removal of the entire sub-hierarchy
+ writer.deleteDocuments(newPathTerm(path));
+ if (!path.endsWith("/")) {
+ path += "/";
+ }
+ writer.deleteDocuments(new PrefixQuery(newPathTerm(path)));
+ }
+
+ private void addSubtreeWriter(IndexWriter writer, String path,
+ NodeState state) throws IOException {
+ writer.updateDocument(newPathTerm(path), makeDocument(path, state));
+ for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ if (NodeStateUtils.isHidden(entry.getName())) {
+ continue;
+ }
+ addSubtreeWriter(writer, concat(path, entry.getName()),
+ entry.getNodeState());
+ }
+ }
+
+ private static Document makeDocument(String path, NodeState state) {
+ Document document = new Document();
+ document.add(newPathField(path));
+ for (PropertyState property : state.getProperties()) {
+ String pname = property.getName();
+ switch (property.getType().tag()) {
+ case PropertyType.BINARY:
+ for (Blob v : property.getValue(Type.BINARIES)) {
+ document.add(newPropertyField(pname, parseStringValue(v)));
+ }
+ break;
+ default:
+ for (String v : property.getValue(Type.STRINGS)) {
+ document.add(newPropertyField(pname, v));
+ }
+ break;
+ }
+ }
+ return document;
+ }
+
+ private static String parseStringValue(Blob v) {
+ try {
+ return TIKA.parseToString(v.getNewStream());
+ } catch (IOException e) {
+ } catch (TikaException e) {
+ }
+ return "";
+ }
+
+ @Override
+ public void close() throws IOException {
+ remove.clear();
+ insert.clear();
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexUpdate.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/TermFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/TermFactory.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/TermFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/TermFactory.java Fri Nov 9 11:26:30 2012
@@ -39,6 +39,9 @@ public final class TermFactory {
* @return the path term.
*/
public static Term newPathTerm(String path) {
+ if (!"/".equals(path) && path.startsWith("/")) {
+ path = path.substring(1);
+ }
return new Term(FieldNames.PATH, path);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java Fri Nov 9 11:26:30 2012
@@ -79,6 +79,8 @@ import com.google.common.collect.Sets;
*/
public class PropertyIndex implements QueryIndex {
+ public static final String TYPE = "property";
+
private static final int MAX_STRING_LENGTH = 100; // TODO: configurable
static List<String> encode(PropertyValue value) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexDiff.java Fri Nov 9 11:26:30 2012
@@ -17,31 +17,37 @@
package org.apache.jackrabbit.oak.plugins.index.property;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
-import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.TYPE;
+import java.io.IOException;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
+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.IndexHook;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
/**
- * {@link NodeStateDiff} implementation that extracts changes for the
- * {@link PropertyIndexHook} to be applied on the {@link PropertyIndex}
+ * {@link IndexHook} implementation that is responsible for keeping the
+ * {@link PropertyIndex} up to date
*
- * @see PropertyIndexHook
+ * @see PropertyIndex
+ * @see PropertyIndexLookup
*
*/
-class PropertyIndexDiff implements NodeStateDiff {
+class PropertyIndexDiff implements IndexHook {
private final PropertyIndexDiff parent;
@@ -63,27 +69,27 @@ class PropertyIndexDiff implements NodeS
this.path = path;
this.updates = updates;
- if (node != null && isIndexNodeType(node.getProperty(JCR_PRIMARYTYPE))) {
- update(node, name);
- }
if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
for (String indexName : index.getChildNodeNames()) {
- update(index.child(indexName), indexName);
+ NodeBuilder child = index.child(indexName);
+ if (isIndexNode(child)) {
+ update(child, indexName);
+ }
}
}
}
- public PropertyIndexDiff(
- NodeBuilder root, Map<String, List<PropertyIndexUpdate>> updates) {
- this(null, root, null, "/", updates);
- }
-
- public PropertyIndexDiff(PropertyIndexDiff parent, String name) {
+ private PropertyIndexDiff(PropertyIndexDiff parent, String name) {
this(parent, getChildNode(parent.node, name),
name, null, parent.updates);
}
+ public PropertyIndexDiff(NodeBuilder root) {
+ this(null, root, null, "/",
+ new HashMap<String, List<PropertyIndexUpdate>>());
+ }
+
private static NodeBuilder getChildNode(NodeBuilder node, String name) {
if (node != null && node.hasChildNode(name)) {
return node.child(name);
@@ -92,7 +98,7 @@ class PropertyIndexDiff implements NodeS
}
}
- private String getPath() {
+ public String getPath() {
if (path == null) { // => parent != null
path = concat(parent.getPath(), name);
}
@@ -118,13 +124,30 @@ class PropertyIndexDiff implements NodeS
list = Lists.newArrayList();
this.updates.put(pname, list);
}
- list.add(new PropertyIndexUpdate(getPath(), builder));
+ boolean exists = false;
+ for (PropertyIndexUpdate piu : list) {
+ if (piu.getPath().equals(getPath())) {
+ exists = true;
+ break;
+ }
+ }
+ if (!exists) {
+ list.add(new PropertyIndexUpdate(getPath(), builder));
+ }
}
}
- private boolean isIndexNodeType(PropertyState ps) {
- return ps != null && !ps.isArray()
+ private static boolean isIndexNode(NodeBuilder node) {
+ PropertyState ps = node.getProperty(JCR_PRIMARYTYPE);
+ boolean isNodeType = ps != null && !ps.isArray()
&& ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE);
+ if (!isNodeType) {
+ return false;
+ }
+ PropertyState type = node.getProperty(TYPE_PROPERTY_NAME);
+ boolean isIndexType = type != null && !type.isArray()
+ && type.getValue(Type.STRING).equals(TYPE);
+ return isIndexType;
}
//-----------------------------------------------------< NodeStateDiff >--
@@ -160,7 +183,7 @@ class PropertyIndexDiff implements NodeS
public void childNodeChanged(
String name, NodeState before, NodeState after) {
if (!NodeStateUtils.isHidden(name)) {
- after.compareAgainstBaseState(before, new PropertyIndexDiff(this, name));
+ after.compareAgainstBaseState(before, child(name));
}
}
@@ -169,4 +192,41 @@ class PropertyIndexDiff implements NodeS
childNodeChanged(name, before, MemoryNodeState.EMPTY_NODE);
}
+ // -----------------------------------------------------< IndexHook >--
+
+ @Override
+ public void apply() throws CommitFailedException {
+ for (List<PropertyIndexUpdate> updateList : updates.values()) {
+ for (PropertyIndexUpdate update : updateList) {
+ update.apply();
+ }
+ }
+ }
+
+ @Override
+ public void reindex(NodeBuilder state) throws CommitFailedException {
+ boolean reindex = false;
+ for (List<PropertyIndexUpdate> updateList : updates.values()) {
+ for (PropertyIndexUpdate update : updateList) {
+ if (update.getAndResetReindexFlag()) {
+ reindex = true;
+ }
+ }
+ }
+ if (reindex) {
+ state.getNodeState().compareAgainstBaseState(
+ MemoryNodeState.EMPTY_NODE,
+ new PropertyIndexDiff(null, state, null, "/", updates));
+ }
+ }
+
+ @Override
+ public IndexHook child(String name) {
+ return new PropertyIndexDiff(this, name);
+ }
+
+ @Override
+ public void close() throws IOException {
+ updates.clear();
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java Fri Nov 9 11:26:30 2012
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jackrabbit.oak.plugins.index.property;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.plugins.index.IndexHook;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-
-import com.google.common.collect.Maps;
-
-/**
- * {@link IndexHook} implementation that is responsible for keeping the
- * {@link PropertyIndex} up to date
- *
- * @see PropertyIndex
- * @see PropertyIndexLookup
- *
- */
-public class PropertyIndexHook implements IndexHook {
-
- private final NodeBuilder builder;
-
- private Map<String, List<PropertyIndexUpdate>> indexes;
-
- public PropertyIndexHook(NodeBuilder builder) {
- this.builder = builder;
- }
-
-
- // -----------------------------------------------------< IndexHook >--
-
- @Override @Nonnull
- public NodeStateDiff preProcess() {
- indexes = Maps.newHashMap();
- return new PropertyIndexDiff(builder, indexes);
- }
-
- @Override
- public void postProcess() throws CommitFailedException {
- for (List<PropertyIndexUpdate> updates : indexes.values()) {
- for (PropertyIndexUpdate update : updates) {
- update.apply();
- }
- }
- }
-
- @Override
- public void close() throws IOException {
- indexes = null;
- }
-}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHookProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHookProvider.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHookProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHookProvider.java Fri Nov 9 11:26:30 2012
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.plugins.index.property;
+import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.TYPE;
+
import java.util.List;
import org.apache.felix.scr.annotations.Component;
@@ -29,7 +31,7 @@ import com.google.common.collect.Immutab
/**
* Service that provides PropertyIndex based IndexHooks
*
- * @see PropertyIndexHook
+ * @see PropertyIndexDiff
* @see IndexHookProvider
*
*/
@@ -37,13 +39,11 @@ import com.google.common.collect.Immutab
@Service(IndexHookProvider.class)
public class PropertyIndexHookProvider implements IndexHookProvider {
- private static final String TYPE = "property";
-
@Override
public List<? extends IndexHook> getIndexHooks(String type,
NodeBuilder builder) {
if (TYPE.equals(type)) {
- return ImmutableList.of(new PropertyIndexHook(builder));
+ return ImmutableList.of(new PropertyIndexDiff(builder));
}
return ImmutableList.of();
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java?rev=1407425&r1=1407424&r2=1407425&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexUpdate.java Fri Nov 9 11:26:30 2012
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.plugins.index.property;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
+
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -54,6 +56,10 @@ class PropertyIndexUpdate {
this.remove = Maps.newHashMap();
}
+ String getPath() {
+ return path;
+ }
+
public void insert(String path, PropertyState value) {
Preconditions.checkArgument(path.startsWith(this.path));
putValues(insert, path.substring(this.path.length()), value);
@@ -79,6 +85,14 @@ class PropertyIndexUpdate {
}
}
+ boolean getAndResetReindexFlag() {
+ boolean reindex = node.getProperty(REINDEX_PROPERTY_NAME) != null
+ && node.getProperty(REINDEX_PROPERTY_NAME).getValue(
+ Type.BOOLEAN);
+ node.setProperty(REINDEX_PROPERTY_NAME, false);
+ return reindex;
+ }
+
public void apply() throws CommitFailedException {
boolean unique = node.getProperty("unique") != null
&& node.getProperty("unique").getValue(Type.BOOLEAN);