Author: alexparvulescu Date: Wed Oct 31 10:21:37 2012 New Revision: 1404071
URL: http://svn.apache.org/viewvc?rev=1404071&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/CompositeNodeStateDiff.java (with props) jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java (with props) Modified: 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/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/property/PropertyIndexHook.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 Added: 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=1404071&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java Wed Oct 31 10:21:37 2012 @@ -0,0 +1,79 @@ +/* + * 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); + } + } +} Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java ------------------------------------------------------------------------------ svn:mime-type = text/plain 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=1404071&r1=1404070&r2=1404071&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 Wed Oct 31 10:21:37 2012 @@ -16,13 +16,20 @@ */ package org.apache.jackrabbit.oak.plugins.index; -import org.apache.jackrabbit.oak.spi.commit.CommitHook; +import java.io.Closeable; + +import org.apache.jackrabbit.oak.api.CommitFailedException; +import org.apache.jackrabbit.oak.spi.state.NodeStateDiff; /** * Represents the content of a QueryIndex as well as a mechanism for keeping * this content up to date. * */ -public interface IndexHook extends CommitHook { +public interface IndexHook extends Closeable { + + NodeStateDiff preProcess() throws CommitFailedException; + + void postProcess() 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=1404071&r1=1404070&r2=1404071&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 Wed Oct 31 10:21:37 2012 @@ -24,6 +24,8 @@ import static org.apache.jackrabbit.oak. 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; @@ -64,9 +66,8 @@ public class IndexHookManager implements // <path>, <builder> Map<String, NodeBuilder> allDefs = new HashMap<String, NodeBuilder>(); - - IndexDefDiff diff = new IndexDefDiff(builder, allDefs); - after.compareAgainstBaseState(before, diff); + after.compareAgainstBaseState(before, + new IndexDefDiff(builder, allDefs)); // <type, <<path>, <builder>> Map<String, Map<String, NodeBuilder>> updates = new HashMap<String, Map<String, NodeBuilder>>(); @@ -86,26 +87,54 @@ public class IndexHookManager implements } // 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); - List<? extends IndexHook> hooks = provider.getIndexHooks(type, - updateBuiler); - for (IndexHook hook : hooks) { - if (reindex) { - hook.processCommit(MemoryNodeState.EMPTY_NODE, after); - } else { - hook.processCommit(before, after); - } + 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); return builder.getNodeState(); } + private void processIndexHooks(List<IndexHook> hooks, NodeState before, + NodeState after) 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); + } + } + } + } + protected static boolean getAndResetReindex(NodeBuilder builder) { boolean isReindex = false; PropertyState ps = builder.getProperty(REINDEX_PROPERTY_NAME); 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=1404071&r1=1404070&r2=1404071&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 Wed Oct 31 10:21:37 2012 @@ -16,41 +16,26 @@ */ 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 static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; import java.io.IOException; -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.commit.CommitHook; -import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry; +import org.apache.jackrabbit.oak.plugins.index.IndexHook; 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.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; -import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.store.Directory; import org.apache.lucene.util.Version; -import org.apache.tika.Tika; -import org.apache.tika.exception.TikaException; /** * This class updates a Lucene index when node content is changed. */ -class LuceneEditor implements CommitHook, LuceneIndexConstants { - - private static final Tika TIKA = new Tika(); +class LuceneEditor implements IndexHook, LuceneIndexConstants { private static final Version VERSION = Version.LUCENE_40; @@ -58,6 +43,8 @@ class LuceneEditor implements CommitHook 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(); @@ -76,167 +63,62 @@ class LuceneEditor implements CommitHook this.root = root; } + // -----------------------------------------------------< IndexHook >-- + @Override - public NodeState processCommit(NodeState before, NodeState after) - throws CommitFailedException { - Directory directory = new ReadWriteOakDirectory( - root.child(INDEX_DATA_CHILD_NAME)); + public NodeStateDiff preProcess() throws CommitFailedException { try { - IndexWriter writer = new IndexWriter(directory, config); - try { - LuceneDiff diff = new LuceneDiff(writer, "/"); - after.compareAgainstBaseState(before, diff); - diff.postProcess(after); - } finally { - writer.close(); - } - return after; + 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 update the full text search index", e); + "Failed to create writer for the full text search index", e); } } - private static class LuceneDiff implements NodeStateDiff { - - private final IndexWriter writer; - - private final String path; - - private boolean modified; - - private IOException exception; - - public LuceneDiff(IndexWriter writer, String path) { - this.writer = writer; - this.path = path; - } - - public void postProcess(NodeState state) throws IOException { - if (exception != null) { - throw exception; - } - if (modified) { - writer.updateDocument(newPathTerm(path), - makeDocument(path, state)); - } - } - - @Override - public void propertyAdded(PropertyState after) { - modified = true; - } - - @Override - public void propertyChanged(PropertyState before, PropertyState after) { - modified = true; - } - - @Override - public void propertyDeleted(PropertyState before) { - modified = true; - } - - @Override - public void childNodeAdded(String name, NodeState after) { - 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()); - } - } - - @Override - public void childNodeChanged(String name, NodeState before, - NodeState after) { - if (NodeStateUtils.isHidden(name)) { - return; - } - if (exception == null) { - try { - LuceneDiff diff = new LuceneDiff(writer, concat(path, name)); - after.compareAgainstBaseState(before, diff); - diff.postProcess(after); - } catch (IOException e) { - exception = e; - } - } - } - - @Override - public void childNodeDeleted(String name, NodeState before) { - if (NodeStateUtils.isHidden(name)) { - return; - } - if (exception == null) { - try { - deleteSubtree(concat(path, name), before); - } catch (IOException e) { - exception = 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 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()); - } - } + private static boolean isIndexNodeType(PropertyState ps) { + return ps != null && !ps.isArray() + && ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE); + } - 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 boolean isIndexType(PropertyState ps, String type) { + return ps != null && !ps.isArray() + && ps.getValue(Type.STRING).equals(type); + } - private static String parseStringValue(Blob v) { - try { - return TIKA.parseToString(v.getNewStream()); - } catch (IOException e) { - } catch (TikaException e) { - } - return ""; + @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=1404071&r1=1404070&r2=1404071&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 Wed Oct 31 10:21:37 2012 @@ -16,10 +16,14 @@ */ 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.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStateDiff; /** * {@link IndexHook} implementation that is responsible for keeping the @@ -32,15 +36,34 @@ public class LuceneHook implements Index private final NodeBuilder builder; + private IndexHook luceneEditor; + public LuceneHook(NodeBuilder builder) { this.builder = builder; } + // -----------------------------------------------------< IndexHook >-- + @Override - public NodeState processCommit(NodeState before, NodeState after) - throws CommitFailedException { - new LuceneEditor(builder).processCommit(before, after); - return after; + @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; + } + } } Added: 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=1404071&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java Wed Oct 31 10:21:37 2012 @@ -0,0 +1,191 @@ +/* + * 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 javax.jcr.PropertyType; + +import org.apache.jackrabbit.oak.api.Blob; +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.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(); + + private final IndexWriter writer; + + private final NodeBuilder node; + + private final String path; + + private boolean modified; + + private IOException exception; + + public LuceneIndexDiff(IndexWriter writer, NodeBuilder node, String path) { + this.writer = writer; + this.node = node; + this.path = path; + } + + public void postProcess() throws IOException { + if (exception != null) { + throw exception; + } + if (modified) { + writer.updateDocument(newPathTerm(path), + makeDocument(path, node.getNodeState())); + } + } + + // -----------------------------------------------------< NodeStateDiff >-- + + @Override + public void propertyAdded(PropertyState after) { + modified = true; + } + + @Override + public void propertyChanged(PropertyState before, PropertyState after) { + modified = true; + } + + @Override + public void propertyDeleted(PropertyState before) { + modified = true; + } + + @Override + public void childNodeAdded(String name, NodeState after) { + 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()); + } + } + + @Override + public void childNodeChanged(String name, NodeState before, NodeState after) { + 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; + } + } + } + + @Override + public void childNodeDeleted(String name, NodeState before) { + if (NodeStateUtils.isHidden(name)) { + return; + } + if (exception == null) { + try { + deleteSubtree(concat(path, name), before); + } catch (IOException e) { + exception = e; + } + } + } + + 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()); + } + } + + 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 ""; + } + + // -----------------------------------------------------< Closeable >-- + + @Override + public void close() throws IOException { + writer.close(); + } + +} Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java ------------------------------------------------------------------------------ svn:mime-type = text/plain 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=1404071&r1=1404070&r2=1404071&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 Wed Oct 31 10:21:37 2012 @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.oak.plugins.index.property; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -24,7 +25,7 @@ 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.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStateDiff; import com.google.common.collect.Maps; @@ -37,28 +38,35 @@ import com.google.common.collect.Maps; * */ 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 NodeState processCommit(NodeState before, NodeState after) - throws CommitFailedException { - Map<String, List<PropertyIndexUpdate>> indexes = Maps.newHashMap(); - PropertyIndexDiff diff = new PropertyIndexDiff(builder, indexes); - after.compareAgainstBaseState(before, diff); + 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(); } } - - return builder.getNodeState(); } - + @Override + public void close() throws IOException { + indexes = null; + } } \ No newline at end of file Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1404071&r1=1404070&r2=1404071&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java Wed Oct 31 10:21:37 2012 @@ -16,12 +16,14 @@ */ package org.apache.jackrabbit.oak.plugins.index.lucene; +import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import org.apache.jackrabbit.oak.plugins.index.IndexDefinition; import org.apache.jackrabbit.oak.plugins.index.IndexDefinitionImpl; +import org.apache.jackrabbit.oak.plugins.index.IndexHook; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState; import org.apache.jackrabbit.oak.query.ast.Operator; import org.apache.jackrabbit.oak.query.index.FilterImpl; @@ -40,16 +42,21 @@ public class LuceneIndexTest implements NodeState root = MemoryNodeState.EMPTY_NODE; NodeBuilder builder = root.builder(); - NodeBuilder index = builder.child("oak:index").child("lucene"); - IndexDefinition testDef = new IndexDefinitionImpl("lucene", - TYPE_LUCENE, "/oak:index/lucene"); + builder.child("oak:index").child("lucene") + .setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE) + .setProperty("type", TYPE_LUCENE); NodeState before = builder.getNodeState(); builder.setProperty("foo", "bar"); NodeState after = builder.getNodeState(); - new LuceneHook(index).processCommit(before, after); + IndexHook l = new LuceneHook(builder); + after.compareAgainstBaseState(before, l.preProcess()); + l.postProcess(); + l.close(); + IndexDefinition testDef = new IndexDefinitionImpl("lucene", + TYPE_LUCENE, "/oak:index/lucene"); QueryIndex queryIndex = new LuceneIndex(testDef); FilterImpl filter = new FilterImpl(null); filter.restrictPath("/", Filter.PathRestriction.EXACT); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java?rev=1404071&r1=1404070&r2=1404071&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java Wed Oct 31 10:21:37 2012 @@ -20,6 +20,7 @@ import java.util.Arrays; import com.google.common.collect.ImmutableSet; 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; @@ -62,8 +63,12 @@ public class PropertyIndexTest { withoutIndex = System.nanoTime() - withoutIndex; // ... then see how adding an index affects the code - lookup = new PropertyIndexLookup( - new PropertyIndexHook(builder).processCommit(before, after)); + IndexHook p = new PropertyIndexHook(builder); + after.compareAgainstBaseState(before, p.preProcess()); + p.postProcess(); + p.close(); + + lookup = new PropertyIndexLookup(builder.getNodeState()); long withIndex = System.nanoTime(); assertEquals(ImmutableSet.of("a", "b"), lookup.find("foo", "abc")); assertEquals(ImmutableSet.of("b"), lookup.find("foo", "def")); @@ -81,7 +86,9 @@ public class PropertyIndexTest { // Add index definition NodeBuilder builder = root.builder(); - builder.child("oak:index").child("fooIndex").setProperty("propertyNames", Arrays.asList("foo", "extrafoo"), Type.STRINGS); + builder.child("oak:index").child("fooIndex") + .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME) + .setProperty("propertyNames", Arrays.asList("foo", "extrafoo"), Type.STRINGS); NodeState before = builder.getNodeState(); // Add some content and process it through the property index hook @@ -106,8 +113,12 @@ public class PropertyIndexTest { withoutIndex = System.nanoTime() - withoutIndex; // ... then see how adding an index affects the code - lookup = new PropertyIndexLookup( - new PropertyIndexHook(builder).processCommit(before, after)); + IndexHook p = new PropertyIndexHook(builder); + after.compareAgainstBaseState(before, p.preProcess()); + p.postProcess(); + p.close(); + + lookup = new PropertyIndexLookup(builder.getNodeState()); long withIndex = System.nanoTime(); assertEquals(ImmutableSet.of("a", "b"), lookup.find("foo", "abc")); assertEquals(ImmutableSet.of("b"), lookup.find("foo", "def"));
