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/08/28 16:56:16 UTC
svn commit: r1378156 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak:
plugins/index/ plugins/lucene/ spi/query/
Author: alexparvulescu
Date: Tue Aug 28 14:56:15 2012
New Revision: 1378156
URL: http://svn.apache.org/viewvc?rev=1378156&view=rev
Log:
OAK-269 Query: IndexManager to manage existing indexes
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexFactory.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexFactory.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexDefinitionImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexFactory.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexFactory.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexFactory.java Tue Aug 28 14:56:15 2012
@@ -16,16 +16,28 @@
*/
package org.apache.jackrabbit.oak.plugins.index;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.oak.spi.query.Index;
import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
import org.apache.jackrabbit.oak.spi.query.IndexFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class PropertyIndexFactory implements IndexFactory {
public static final String TYPE_PROPERTY = "property";
public static final String TYPE_PREFIX = "prefix";
+ private static final Logger LOG = LoggerFactory
+ .getLogger(PropertyIndexFactory.class);
+
+ private final ConcurrentHashMap<IndexDefinition, Index> indexes = new ConcurrentHashMap<IndexDefinition, Index>();
+
private Indexer indexer;
@Override
@@ -38,8 +50,7 @@ public class PropertyIndexFactory implem
return new String[] { TYPE_PREFIX, TYPE_PROPERTY };
}
- @Override
- public Index createIndex(IndexDefinition indexDefinition) {
+ private Index createIndex(IndexDefinition indexDefinition) {
if (TYPE_PREFIX.equals(indexDefinition.getType())) {
String prefix = indexDefinition.getProperties().get("prefix");
if (prefix != null) {
@@ -57,4 +68,34 @@ public class PropertyIndexFactory implem
return null;
}
+ @Override
+ public Index getIndex(IndexDefinition indexDefinition) {
+ Index index = indexes.get(indexDefinition);
+ if (index == null) {
+ index = createIndex(indexDefinition);
+ indexes.put(indexDefinition, index);
+ }
+ return index;
+ }
+
+ @Override
+ public void close() throws IOException {
+ Iterator<IndexDefinition> iterator = indexes.keySet().iterator();
+ while (iterator.hasNext()) {
+ IndexDefinition id = iterator.next();
+ try {
+ indexes.get(id).close();
+ } catch (IOException e) {
+ LOG.error("Error closing index {}.", id.getName(), e);
+ }
+ iterator.remove();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyIndexFactory [getTypes()="
+ + Arrays.toString(getTypes()) + "]";
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexFactory.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexFactory.java Tue Aug 28 14:56:15 2012
@@ -16,15 +16,27 @@
*/
package org.apache.jackrabbit.oak.plugins.lucene;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.oak.spi.query.Index;
import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
import org.apache.jackrabbit.oak.spi.query.IndexFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class LuceneIndexFactory implements IndexFactory {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(LuceneIndexFactory.class);
+
public static final String TYPE = "lucene";
+ private final ConcurrentHashMap<IndexDefinition, Index> indexes = new ConcurrentHashMap<IndexDefinition, Index>();
+
@Override
public void init(MicroKernel mk) {
// not needed
@@ -36,8 +48,32 @@ public class LuceneIndexFactory implemen
}
@Override
- public Index createIndex(IndexDefinition indexDefinition) {
- return new LuceneEditor(indexDefinition);
+ public void close() throws IOException {
+ Iterator<IndexDefinition> iterator = indexes.keySet().iterator();
+ while (iterator.hasNext()) {
+ IndexDefinition id = iterator.next();
+ try {
+ indexes.get(id).close();
+ } catch (IOException e) {
+ LOG.error("Error closing index {}.", id.getName(), e);
+ }
+ iterator.remove();
+ }
+ }
+
+ @Override
+ public Index getIndex(IndexDefinition indexDefinition) {
+ Index index = indexes.get(indexDefinition);
+ if (index == null) {
+ index = new LuceneEditor(indexDefinition);
+ indexes.put(indexDefinition, index);
+ }
+ return index;
}
+ @Override
+ public String toString() {
+ return "LuceneIndexFactory [getTypes()=" + Arrays.toString(getTypes())
+ + "]";
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexDefinitionImpl.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexDefinitionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexDefinitionImpl.java Tue Aug 28 14:56:15 2012
@@ -66,11 +66,21 @@ public class IndexDefinitionImpl impleme
}
@Override
+ public String toString() {
+ return "IndexDefinitionImpl [name=" + name + ", type=" + type
+ + ", path=" + path + ", unique=" + unique + ", properties="
+ + properties + "]";
+ }
+
+ @Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result
+ + ((properties == null) ? 0 : properties.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + (unique ? 1231 : 1237);
return result;
}
@@ -83,17 +93,23 @@ public class IndexDefinitionImpl impleme
if (getClass() != obj.getClass())
return false;
IndexDefinitionImpl other = (IndexDefinitionImpl) obj;
- if (path == null) {
- if (other.path != null)
+ if (name == null) {
+ if (other.name != null)
return false;
- } else if (!path.equals(other.path))
+ } else if (!name.equals(other.name))
+ return false;
+ if (properties == null) {
+ if (other.properties != null)
+ return false;
+ } else if (!properties.equals(other.properties))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
+ if (unique != other.unique)
+ return false;
return true;
}
-
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexFactory.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexFactory.java Tue Aug 28 14:56:15 2012
@@ -16,12 +16,14 @@
*/
package org.apache.jackrabbit.oak.spi.query;
+import java.io.Closeable;
+
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.apache.jackrabbit.mk.api.MicroKernel;
-public interface IndexFactory {
+public interface IndexFactory extends Closeable {
/**
* initializes the provided factory
@@ -39,6 +41,6 @@ public interface IndexFactory {
* @return
*/
@CheckForNull
- Index createIndex(IndexDefinition indexDefinition);
+ Index getIndex(IndexDefinition indexDefinition);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManager.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManager.java Tue Aug 28 14:56:15 2012
@@ -17,10 +17,14 @@
package org.apache.jackrabbit.oak.spi.query;
import java.io.Closeable;
-import java.util.Set;
+import java.util.List;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import org.apache.jackrabbit.oak.spi.commit.CommitEditor;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
/**
* <p>
* Index Manager keeps track of all the available indexes.
@@ -32,28 +36,31 @@ import javax.annotation.Nonnull;
* </p>
*
* <p>
- * TODO It *should* define an API for managing indexes (CRUD ops)
- * </p>
- *
- * <p>
* TODO Document simple node properties to create an index type
* </p>
* </p>
*/
-public interface IndexManager extends Closeable {
+public interface IndexManager extends CommitEditor, Closeable {
+
+ void registerIndexFactory(IndexFactory... factory);
+
+ void unregisterIndexFactory(IndexFactory factory);
/**
- * Creates an index by passing the {@link IndexDefinition} to the registered
- * {@link IndexFactory}(es)
- *
- * @param indexDefinition
+ * @return the index with the given name
*/
- void registerIndex(IndexDefinition... indexDefinition);
+ @CheckForNull
+ Index getIndex(String name, NodeState nodeState);
- void registerIndexFactory(IndexFactory factory);
-
- void init();
+ /**
+ * @return the index with the given definition
+ */
+ @CheckForNull
+ public Index getIndex(IndexDefinition definition);
+ /**
+ * @return the existing index definitions
+ */
@Nonnull
- Set<IndexDefinition> getIndexes();
+ List<IndexDefinition> getIndexDefinitions(NodeState nodeState);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManagerImpl.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexManagerImpl.java Tue Aug 28 14:56:15 2012
@@ -18,122 +18,155 @@ package org.apache.jackrabbit.oak.spi.qu
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.commit.CommitEditor;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.ImmutableSet;
-
-public class IndexManagerImpl implements IndexManager {
-
- // TODO implement an observation listener so that the {@link
- // IndexManagerImpl} automatically creates new indexes based on new nodes
- // added under {@link #indexConfigPath}
+public class IndexManagerImpl implements IndexManager, CommitEditor {
private static final Logger LOG = LoggerFactory
.getLogger(IndexManagerImpl.class);
private final String indexConfigPath;
- private final ContentSession session;
-
private final MicroKernel mk;
- private final Map<String, IndexFactory> indexFactories = new ConcurrentHashMap<String, IndexFactory>();
+ private final Map<IndexFactory, String[]> indexFactories = new ConcurrentHashMap<IndexFactory, String[]>();
- private final Map<IndexDefinition, Index> indexes = new ConcurrentHashMap<IndexDefinition, Index>();
-
- public IndexManagerImpl(String indexConfigPath, ContentSession session,
- MicroKernel mk) {
+ public IndexManagerImpl(String indexConfigPath, MicroKernel mk,
+ IndexFactory... factories) {
this.indexConfigPath = indexConfigPath;
- this.session = session;
this.mk = mk;
+ internalRegisterIndexFactory(factories);
}
@Override
- public void registerIndexFactory(IndexFactory factory) {
- factory.init(mk);
- for (String type : factory.getTypes()) {
- if (indexFactories.remove(type) != null) {
+ public void registerIndexFactory(IndexFactory... factories) {
+ internalRegisterIndexFactory(factories);
+ }
+
+ @Override
+ public void unregisterIndexFactory(IndexFactory factory) {
+ indexFactories.remove(factory);
+ }
+
+ private void internalRegisterIndexFactory(IndexFactory... factories) {
+ if (factories == null) {
+ return;
+ }
+ for (IndexFactory factory : factories) {
+ if (indexFactories.remove(factory) != null) {
// TODO is override allowed?
}
- indexFactories.put(type, factory);
+ factory.init(mk);
+ indexFactories.put(factory, factory.getTypes());
+ LOG.debug("Registered index factory {}.", factory);
}
}
- @Override
- public void init() {
- //
- // TODO hardwire default property indexes first ?
- // registerIndexFactory(type, factory);
- Tree definitions = session.getCurrentRoot().getTree(indexConfigPath);
+ /**
+ * Builds a list of the existing index definitions from the repository
+ *
+ */
+ private static List<IndexDefinition> buildIndexDefinitions(boolean log,
+ NodeState nodeState, String indexConfigPath) {
+
+ NodeState definitions = IndexUtils.getNode(nodeState, indexConfigPath);
if (definitions == null) {
- return;
+ return Collections.emptyList();
}
List<IndexDefinition> defs = new ArrayList<IndexDefinition>();
- for (Tree c : definitions.getChildren()) {
- IndexDefinition def = IndexUtils.getDefs(indexConfigPath, c);
+ for (ChildNodeEntry c : definitions.getChildNodeEntries()) {
+ IndexDefinition def = IndexUtils.getDefinition(indexConfigPath, c);
if (def == null) {
- LOG.warn("Skipping illegal index definition name {} @ {}",
- c.getName(), indexConfigPath);
- continue;
- }
- if (indexes.get(def.getName()) != null) {
- LOG.warn("Skipping existing index definition name {} @ {}",
- c.getName(), indexConfigPath);
+ if (log) {
+ LOG.warn("Skipping illegal index definition name {} @ {}",
+ c.getName(), indexConfigPath);
+ }
continue;
}
defs.add(def);
}
- registerIndex(defs.toArray(new IndexDefinition[defs.size()]));
+ return defs;
}
@Override
- public void registerIndex(IndexDefinition... indexDefinition) {
- for (IndexDefinition def : indexDefinition) {
- if (def == null) {
- continue;
- }
- IndexFactory f = indexFactories.get(def.getType());
- if (f == null) {
- LOG.warn(
- "Skipping unknown index definition type {}, name {} @ {}",
- new String[] { def.getType(), indexConfigPath,
- def.getName() });
- continue;
+ public Index getIndex(String name, NodeState nodeState) {
+ if (name == null) {
+ return null;
+ }
+ IndexDefinition id = null;
+ for (IndexDefinition def : getIndexDefinitions(nodeState)) {
+ if (name.equals(def.getName())) {
+ id = def;
+ break;
}
- Index index = f.createIndex(def);
- if (index != null) {
- indexes.put(def, index);
+ }
+ return getIndex(id);
+ }
+
+ @Override
+ public Index getIndex(IndexDefinition def) {
+ if (def == null) {
+ return null;
+ }
+ Iterator<IndexFactory> iterator = indexFactories.keySet().iterator();
+ while (iterator.hasNext()) {
+ IndexFactory factory = iterator.next();
+ for (String type : factory.getTypes()) {
+ if (type != null && type.equals(def.getType())) {
+ return factory.getIndex(def);
+ }
}
}
+ LOG.debug("Index definition {} doesn't have a known factory.", def);
+ return null;
}
@Override
- public Set<IndexDefinition> getIndexes() {
- return ImmutableSet.copyOf(indexes.keySet());
+ public List<IndexDefinition> getIndexDefinitions(NodeState nodeState) {
+ return buildIndexDefinitions(true, nodeState, indexConfigPath);
}
@Override
public synchronized void close() throws IOException {
- Iterator<IndexDefinition> iterator = indexes.keySet().iterator();
+ Iterator<IndexFactory> iterator = indexFactories.keySet().iterator();
while (iterator.hasNext()) {
- IndexDefinition id = iterator.next();
+ IndexFactory factory = iterator.next();
try {
- indexes.get(id).close();
+ factory.close();
} catch (IOException e) {
- LOG.error("error closing index {}", id.getName(), e);
+ LOG.error("error closing index factory {}", factory, e);
}
iterator.remove();
}
}
+
+ @Override
+ public NodeState editCommit(NodeStore store, NodeState before,
+ NodeState after) throws CommitFailedException {
+
+ NodeState newState = after;
+ for (IndexDefinition def : buildIndexDefinitions(true, after,
+ indexConfigPath)) {
+ Index index = getIndex(def);
+ if (index == null) {
+ continue;
+ }
+ newState = index.editCommit(store, before, newState);
+ }
+ return newState;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java?rev=1378156&r1=1378155&r2=1378156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java Tue Aug 28 14:56:15 2012
@@ -18,12 +18,14 @@ package org.apache.jackrabbit.oak.spi.qu
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
public class IndexUtils {
@@ -32,24 +34,28 @@ public class IndexUtils {
*/
public static final String DEFAULT_INDEX_HOME = "/oak-index";
- public static IndexDefinition getDefs(String path, Tree tree) {
- String name = tree.getName();
- PropertyState typeProp = tree
- .getProperty(IndexDefinition.TYPE_PROPERTY_NAME);
+ /**
+ * Builds an {@link IndexDefinition} out of a {@link ChildNodeEntry}
+ *
+ */
+ public static IndexDefinition getDefinition(String path, ChildNodeEntry def) {
+ String name = def.getName();
+ PropertyState typeProp = def.getNodeState().getProperty(
+ IndexDefinition.TYPE_PROPERTY_NAME);
if (typeProp == null || typeProp.isArray()) {
return null;
}
String type = typeProp.getValue().getString();
boolean unique = false;
- PropertyState uniqueProp = tree
- .getProperty(IndexDefinition.UNIQUE_PROPERTY_NAME);
+ PropertyState uniqueProp = def.getNodeState().getProperty(
+ IndexDefinition.UNIQUE_PROPERTY_NAME);
if (uniqueProp != null && !uniqueProp.isArray()) {
unique = uniqueProp.getValue().getBoolean();
}
Map<String, String> props = new HashMap<String, String>();
- for (PropertyState ps : tree.getProperties()) {
+ for (PropertyState ps : def.getNodeState().getProperties()) {
if (ps != null && !ps.isArray()) {
String v = ps.getValue().getString();
props.put(ps.getName(), v);
@@ -75,8 +81,25 @@ public class IndexUtils {
if (append != null && append.trim().length() != 0) {
paths.add(append);
}
-
return paths.toArray(new String[paths.size()]);
}
+ /**
+ * @return the 'destination' node if the path exists, null if otherwise
+ */
+ public static NodeState getNode(NodeState nodeState, String destination) {
+ NodeState retval = nodeState;
+ Iterator<String> pathIterator = PathUtils.elements(destination)
+ .iterator();
+ while (pathIterator.hasNext()) {
+ String path = pathIterator.next();
+ if (retval.hasChildNode(path)) {
+ retval = retval.getChildNode(path);
+ } else {
+ return null;
+ }
+ }
+ return retval;
+ }
+
}