jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alexparvule...@apache.org
Subject svn commit: r1382692 [1/2] - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/ oak-core/src/...
Date Mon, 10 Sep 2012 08:43:44 GMT
Author: alexparvulescu
Date: Mon Sep 10 08:43:42 2012
New Revision: 1382692

URL: http://svn.apache.org/viewvc?rev=1382692&view=rev
Log:
OAK-154 Full text search index
 - QueryIndexProvider now uses a NodeStore to fetch the available indexes
 - removed the IndexFactory&IndexManager ideas&code
 - removed the Index interface
  - added PropertyIndexer which will replace Indexer in the near future

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java   (with props)
Removed:
    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/plugins/lucene/LuceneIndexUtils.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Index.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/test/java/org/apache/jackrabbit/oak/spi/query/IndexManagerTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiIndexProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PrefixIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PrefixContentIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/QueryIndexProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/CompositeQueryIndexProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/IndexUtils.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditorTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_explain.txt
    jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiIndexProvider.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiIndexProvider.java Mon Sep 10 08:43:42 2012
@@ -18,19 +18,19 @@
  */
 package org.apache.jackrabbit.oak.osgi;
 
-import org.apache.jackrabbit.mk.api.MicroKernel;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.jackrabbit.oak.spi.QueryIndex;
 import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 /**
  * This index provider combines all indexes of all available OSGi index
  * providers.
@@ -80,11 +80,11 @@ public class OsgiIndexProvider implement
     }
 
     @Override
-    public List<? extends QueryIndex> getQueryIndexes(MicroKernel mk) {
+    public List<? extends QueryIndex> getQueryIndexes(NodeStore nodeStore) {
         if (providers.isEmpty()) {
             return Collections.emptyList();
         } else if (providers.size() == 1) {
-            return providers.entrySet().iterator().next().getValue().getQueryIndexes(mk);
+            return providers.entrySet().iterator().next().getValue().getQueryIndexes(nodeStore);
         } else {
             // TODO combine indexes
             return null;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTree.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTree.java Mon Sep 10 08:43:42 2012
@@ -23,21 +23,21 @@ import org.apache.jackrabbit.oak.commons
  * A tree allows to query a value for a given key, similar to
  * {@code java.util.SortedMap}.
  */
-public class BTree {
+public class BTree implements PropertyIndexConstants {
 
     private static final int DEFAULT_MIN_SIZE = 2;
 
-    private Indexer indexer;
+    private BTreeHelper indexer;
 
     private String name;
     private boolean unique = true;
     private int minSize = DEFAULT_MIN_SIZE;
 
-    public BTree(Indexer indexer, String name, boolean unique) {
+    public BTree(BTreeHelper indexer, String name, boolean unique) {
         this.indexer = indexer;
         this.name = name;
         this.unique = unique;
-        indexer.createNodes(PathUtils.concat(name, Indexer.INDEX_CONTENT));
+        indexer.createNodes(PathUtils.concat(name, INDEX_CONTENT));
     }
 
     public void setMinSize(int minSize) {
@@ -123,7 +123,7 @@ public class BTree {
 
     void bufferSetArray(String path, String propertyName, String[] data) {
         JsopBuilder jsop = new JsopBuilder();
-        path = PathUtils.concat(name, Indexer.INDEX_CONTENT, path);
+        path = PathUtils.concat(name, INDEX_CONTENT, path);
         jsop.tag('^').key(PathUtils.concat(path, propertyName));
         if (data == null) {
             jsop.value(null);
@@ -147,7 +147,7 @@ public class BTree {
 
     void bufferDelete(String path) {
         JsopBuilder jsop = new JsopBuilder();
-        jsop.tag('-').value(PathUtils.concat(name, Indexer.INDEX_CONTENT, path));
+        jsop.tag('-').value(PathUtils.concat(name, INDEX_CONTENT, path));
         jsop.newline();
         indexer.buffer(jsop.toString());
     }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+public interface BTreeHelper {
+
+    BTreePage getPageIfCached(BTree tree, BTreeNode parent, String name);
+
+    BTreePage getPage(BTree tree, BTreeNode parent, String name);
+
+    void modified(BTree tree, BTreePage page, boolean deleted);
+
+    void moveCache(BTree tree, String oldPath);
+
+    void createNodes(String path);
+
+    void buffer(String diff);
+
+    void updateUntil(String toRevision);
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,116 @@
+/*
+ * 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 org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.util.ArrayUtils;
+
+/**
+ * An index leaf page.
+ */
+public class BTreeLeaf extends BTreePage implements PropertyIndexConstants {
+
+    public BTreeLeaf(BTree tree, BTreeNode parent, String name, String[] data, String[] paths) {
+        super(tree, parent, name, data, paths);
+        verify();
+    }
+
+    BTreeLeaf nextLeaf() {
+        return parent == null ? null : parent.next(this);
+    }
+
+    @Override
+    BTreeLeaf firstLeaf() {
+        return this;
+    }
+
+    @Override
+    void split(BTreeNode newParent, String newName, int pos, String siblingName) {
+        setParent(newParent, newName, true);
+        String[] k2 = Arrays.copyOfRange(keys, pos, keys.length, String[].class);
+        String[] v2 = Arrays.copyOfRange(values, pos, values.length, String[].class);
+        BTreeLeaf n2 = new BTreeLeaf(tree, parent, siblingName, k2, v2);
+        keys = Arrays.copyOfRange(keys, 0, pos, String[].class);
+        values = Arrays.copyOfRange(values, 0, pos, String[].class);
+        writeData();
+        n2.writeCreate();
+    }
+
+    void insert(int pos, String key, String value) {
+        tree.modified(this);
+        keys = ArrayUtils.arrayInsert(keys, pos, key);
+        values = ArrayUtils.arrayInsert(values, pos, value);
+        verify();
+    }
+
+    void delete(int pos) {
+        tree.modified(this);
+        keys = ArrayUtils.arrayRemove(keys, pos);
+        values = ArrayUtils.arrayRemove(values, pos);
+        verify();
+    }
+
+    void writeData() {
+        verify();
+        tree.modified(this);
+        tree.bufferSetArray(getPath(), "children", null);
+        tree.bufferSetArray(getPath(), "keys", keys);
+        tree.bufferSetArray(getPath(), "values", values);
+    }
+
+    @Override
+    void writeCreate() {
+        verify();
+        tree.modified(this);
+        tree.buffer(getJsop());
+    }
+
+    private void verify() {
+        if (values.length != keys.length) {
+            throw new IllegalArgumentException(
+                    "Number of values doesn't match number of keys: " +
+                    Arrays.toString(values) + " " + Arrays.toString(keys));
+        }
+    }
+
+    private String getJsop() {
+        JsopBuilder jsop = new JsopBuilder();
+        jsop.tag('+').key(PathUtils.concat(tree.getName(), INDEX_CONTENT, getPath())).object();
+        jsop.key("keys").array();
+        for (String k : keys) {
+            jsop.value(k);
+        }
+        jsop.endArray();
+        jsop.key("values").array();
+        for (String v : values) {
+            jsop.value(v);
+        }
+        jsop.endArray();
+        jsop.endObject();
+        jsop.newline();
+        return jsop.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "leaf: " + getJsop();
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,185 @@
+/*
+ * 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 org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.oak.util.ArrayUtils;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+/**
+ * An index node page.
+ */
+public class BTreeNode extends BTreePage implements PropertyIndexConstants {
+
+    private String[] children;
+
+    public BTreeNode(BTree tree, BTreeNode parent, String name, String[] keys, String[] values, String[] children) {
+        super(tree, parent, name, keys, values);
+        this.children = children;
+        verify();
+    }
+
+    String getNextChildPath() {
+        int max = 0;
+        for (String c : children) {
+            int x = Integer.parseInt(c);
+            if (x > max) {
+                max = x;
+            }
+        }
+        return Integer.toString(max + 1);
+    }
+
+    @Override
+    BTreeLeaf firstLeaf() {
+        return tree.getPage(this, children[0]).firstLeaf();
+    }
+
+    @Override
+    void split(BTreeNode newParent, String newName, int pos, String siblingName) {
+        setParent(newParent, newName, true);
+        String[] k2 = Arrays.copyOfRange(keys, pos + 1, keys.length, String[].class);
+        String[] v2 = Arrays.copyOfRange(values, pos + 1, values.length, String[].class);
+        String[] c2 = Arrays.copyOfRange(children, pos + 1, children.length, String[].class);
+        BTreeNode n2 = new BTreeNode(tree, parent, siblingName, k2, v2, c2);
+        for (String c : c2) {
+            BTreePage cp = tree.getPageIfCached(this, c);
+            if (cp != null) {
+                cp.setParent(n2, c, false);
+            }
+        }
+        keys = Arrays.copyOfRange(keys, 0, pos, String[].class);
+        values = Arrays.copyOfRange(values, 0, pos, String[].class);
+        children = Arrays.copyOfRange(children, 0, pos + 1, String[].class);
+        verify();
+        n2.writeCreate();
+        for (String c : n2.children) {
+            tree.bufferMove(
+                    PathUtils.concat(tree.getName(), INDEX_CONTENT, getPath(), c),
+                    PathUtils.concat(tree.getName(), INDEX_CONTENT, getParentPath(), siblingName, c)
+            );
+        }
+        tree.moveCache(getPath());
+        writeData();
+    }
+
+    BTreeLeaf next(BTreePage child) {
+        int i = 0;
+        String childName = child.name;
+        for (; i < children.length; i++) {
+            if (children[i].equals(childName)) {
+                break;
+            }
+        }
+        if (i == children.length - 1) {
+            return parent == null ? null : parent.next(this);
+        }
+        return tree.getPage(this, children[i + 1]).firstLeaf();
+    }
+
+    BTreePage getChild(int pos) {
+        return tree.getPage(this, children[pos]);
+    }
+
+    void writeData() {
+        verify();
+        tree.modified(this);
+        tree.bufferSetArray(getPath(), "keys", keys);
+        tree.bufferSetArray(getPath(), "values", values);
+        tree.bufferSetArray(getPath(), "children", children);
+    }
+
+    @Override
+    void writeCreate() {
+        verify();
+        tree.modified(this);
+        tree.buffer(getJsop());
+    }
+
+    void delete(int pos) {
+        tree.modified(this);
+        if (size() > 0) {
+            // empty parent
+            keys = ArrayUtils.arrayRemove(keys, Math.max(0, pos - 1));
+            values = ArrayUtils.arrayRemove(values, Math.max(0, pos - 1));
+        }
+        children = ArrayUtils.arrayRemove(children, pos);
+        verify();
+    }
+
+    void insert(int pos, String key, String value, String child) {
+        tree.modified(this);
+        keys = ArrayUtils.arrayInsert(keys, pos, key);
+        values = ArrayUtils.arrayInsert(values, pos, value);
+        children = ArrayUtils.arrayInsert(children, pos + 1, child);
+        verify();
+    }
+
+    boolean isEmpty() {
+        return children.length == 0;
+    }
+
+    private void verify() {
+        if (values.length != keys.length) {
+            throw new IllegalArgumentException(
+                    "Number of values doesn't match number of keys: " +
+                    Arrays.toString(values) + " " + Arrays.toString(keys) + " " + Arrays.toString(children));
+        }
+        if (children.length != keys.length + 1) {
+            if (children.length != 0 || keys.length != 0) {
+                throw new IllegalArgumentException(
+                        "Number of children doesn't match number of keys + 1: " +
+                        Arrays.toString(values) + " " + Arrays.toString(keys) + " " + Arrays.toString(children));
+            }
+        }
+    }
+
+    private String getJsop() {
+        JsopBuilder jsop = new JsopBuilder();
+        jsop.tag('+').key(PathUtils.concat(tree.getName(), INDEX_CONTENT, getPath())).object();
+        jsop.key("keys").array();
+        for (String k : keys) {
+            jsop.value(k);
+        }
+        jsop.endArray();
+        jsop.key("values").array();
+        for (String v : values) {
+            jsop.value(v);
+        }
+        jsop.endArray();
+        // could just use child node list, but then
+        // new children need to be ordered at the right position,
+        // and we would need a way to distinguish empty lists
+        // from a leaf
+        jsop.key("children").array();
+        for (String d : children) {
+            jsop.value(d);
+        }
+        jsop.endArray();
+        jsop.endObject();
+        jsop.newline();
+        return jsop.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "node: " + getJsop();
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,80 @@
+/*
+ * 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.commons.PathUtils;
+
+/**
+ * An index page.
+ */
+abstract public class BTreePage implements PropertyIndexConstants {
+
+    protected final BTree tree;
+    protected BTreeNode parent;
+    protected String name;
+    protected String[] keys;
+    protected String[] values;
+
+    BTreePage(BTree tree, BTreeNode parent, String name, String[] keys, String[] values) {
+        this.tree = tree;
+        this.parent = parent;
+        this.name = name;
+        this.keys = keys;
+        this.values = values;
+    }
+
+    abstract void writeCreate();
+    abstract void split(BTreeNode newParent, String newPath, int pos, String siblingPath);
+    abstract BTreeLeaf firstLeaf();
+
+    void setParent(BTreeNode newParent, String newName, boolean parentIsNew) {
+        if (newParent != null) {
+            String oldPath = getPath();
+            String temp = PathUtils.concat(INDEX_CONTENT, "temp");
+            tree.bufferMove(
+                    PathUtils.concat(tree.getName(), INDEX_CONTENT, getPath()),
+                    temp);
+            if (parentIsNew) {
+                newParent.writeCreate();
+            }
+            tree.bufferMove(
+                    temp,
+                    PathUtils.concat(tree.getName(), INDEX_CONTENT, getParentPath(), newName));
+            parent = newParent;
+            name = newName;
+            tree.moveCache(oldPath);
+            tree.modified(this);
+        }
+    }
+
+    String getParentPath() {
+        return parent == null ? "" : parent.getPath();
+    }
+
+    public String getPath() {
+        return PathUtils.concat(getParentPath(), name);
+    }
+
+    int size() {
+        return keys.length;
+    }
+
+    int find(String key, String value) {
+        return tree.find(key, value, keys, values);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java Mon Sep 10 08:43:42 2012
@@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.plugin
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map.Entry;
 
 import org.apache.jackrabbit.mk.ExceptionFactory;
@@ -33,49 +32,13 @@ import org.apache.jackrabbit.mk.simple.N
 import org.apache.jackrabbit.mk.simple.NodeMap;
 import org.apache.jackrabbit.mk.util.SimpleLRUCache;
 import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.plugins.unique.UniqueIndex;
-import org.apache.jackrabbit.oak.query.index.PrefixContentIndex;
-import org.apache.jackrabbit.oak.query.index.PropertyContentIndex;
-import org.apache.jackrabbit.oak.spi.QueryIndex;
-import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
-import org.apache.jackrabbit.oak.spi.query.Index;
-import org.apache.jackrabbit.oak.spi.query.IndexUtils;
 
 /**
  * A index mechanism. An index is bound to a certain repository, and supports
  * one or more indexes.
+ * 
  */
-public class Indexer implements QueryIndexProvider {
-
-    /**
-     * The root node of the index definition (configuration) nodes.
-     */
-    // TODO OAK-178 discuss where to store index config data
-    public static final String INDEX_CONFIG_PATH = IndexUtils.DEFAULT_INDEX_HOME + "/indexes";
-            //"/jcr:system/indexes";
-
-    /**
-     * For each index, the index content is stored relative to the index
-     * definition below this node. There is also such a node just below the
-     * index definition node, to store the last revision and for temporary data.
-     */
-    public static final String INDEX_CONTENT = ":data";
-
-    /**
-     * The node name prefix of a prefix index.
-     */
-    public static final String TYPE_PREFIX = "prefix@";
-
-    /**
-     * The node name prefix of a property index.
-     */
-    // TODO support multi-property indexes
-    public static final String TYPE_PROPERTY = "property@";
-
-    /**
-     * Marks a unique index.
-     */
-    public static final String UNIQUE = "unique";
+public class Indexer implements PropertyIndexConstants, BTreeHelper {
 
     /**
      * The maximum length of the write buffer.
@@ -86,10 +49,9 @@ public class Indexer implements QueryInd
 
     private MicroKernel mk;
     private String revision;
-    private String indexRootNode = INDEX_CONFIG_PATH;
-    private int indexRootNodeDepth;
+    private final String indexRootNode;
+    private final int indexRootNodeDepth;
     private StringBuilder buffer;
-    private ArrayList<QueryIndex> queryIndexList;
     private HashMap<String, BTreePage> modified = new HashMap<String, BTreePage>();
     private SimpleLRUCache<String, BTreePage> cache = SimpleLRUCache.newInstance(100);
     private String readRevision;
@@ -110,8 +72,17 @@ public class Indexer implements QueryInd
      */
     private final HashMap<String, PropertyIndex> propertyIndexes = new HashMap<String, PropertyIndex>();
 
-    public Indexer(MicroKernel mk) {
+    public Indexer(MicroKernel mk, String indexConfigPath) {
         this.mk = mk;
+        this.indexRootNode = indexConfigPath;
+        this.indexRootNodeDepth = PathUtils.getDepth(indexRootNode);
+    }
+
+    /**
+     * TODO test-only
+     */
+    public Indexer(MicroKernel mk) {
+        this(mk, INDEX_CONFIG_PATH);
     }
 
     /**
@@ -140,10 +111,6 @@ public class Indexer implements QueryInd
             return;
         }
         init = true;
-        if (!PathUtils.isAbsolute(indexRootNode)) {
-            indexRootNode = "/" + indexRootNode;
-        }
-        indexRootNodeDepth = PathUtils.getDepth(indexRootNode);
         revision = mk.getHeadRevision();
         readRevision = revision;
         boolean exists = mk.nodeExists(indexRootNode, revision);
@@ -162,15 +129,13 @@ public class Indexer implements QueryInd
                 String k = n.getChildNodeName(i);
                 PropertyIndex prop = PropertyIndex.fromNodeName(this, k);
                 if (prop != null) {
-                    indexes.put(prop.getDefinition().getName(), prop);
+                    indexes.put(prop.getIndexNodeName(), prop);
                     propertyIndexes.put(prop.getPropertyName(), prop);
-                    queryIndexList = null;
                 }
                 PrefixIndex pref = PrefixIndex.fromNodeName(this, k);
                 if (pref != null) {
-                    indexes.put(pref.getDefinition().getName(), pref);
+                    indexes.put(pref.getIndexNodeName(), pref);
                     prefixIndexes.put(pref.getPrefix(), pref);
-                    queryIndexList = null;
                 }
             }
         }
@@ -178,8 +143,7 @@ public class Indexer implements QueryInd
 
     private void removePropertyIndex(String property, boolean unique) {
         PropertyIndex index = propertyIndexes.remove(property);
-        indexes.remove(index.getDefinition().getName());
-        queryIndexList = null;
+        indexes.remove(index.getIndexNodeName());
     }
 
     public PropertyIndex createPropertyIndex(String property, boolean unique) {
@@ -189,16 +153,14 @@ public class Indexer implements QueryInd
         }
         PropertyIndex index = new PropertyIndex(this, property, unique);
         buildIndex(index);
-        indexes.put(index.getDefinition().getName(), index);
+        indexes.put(index.getIndexNodeName(), index);
         propertyIndexes.put(index.getPropertyName(), index);
-        queryIndexList = null;
         return index;
     }
 
     private void removePrefixIndex(String prefix) {
          PrefixIndex index = prefixIndexes.remove(prefix);
-         indexes.remove(index.getDefinition().getName());
-         queryIndexList = null;
+         indexes.remove(index.getIndexNodeName());
     }
 
     public PrefixIndex createPrefixIndex(String prefix) {
@@ -208,9 +170,8 @@ public class Indexer implements QueryInd
         }
         PrefixIndex index = new PrefixIndex(this, prefix);
         buildIndex(index);
-        indexes.put(index.getDefinition().getName(), index);
+        indexes.put(index.getIndexNodeName(), index);
         prefixIndexes.put(index.getPrefix(), index);
-        queryIndexList = null;
         return index;
     }
 
@@ -672,25 +633,6 @@ public class Indexer implements QueryInd
         return buffer != null && buffer.length() > MAX_BUFFER_LENGTH;
     }
 
-    @Override
-    public List<QueryIndex> getQueryIndexes(MicroKernel mk) {
-        init();
-        if (queryIndexList == null) {
-            queryIndexList = new ArrayList<QueryIndex>();
-            for (Index index : indexes.values()) {
-                QueryIndex qi = null;
-                if (index instanceof PropertyIndex) {
-                    qi = new PropertyContentIndex((PropertyIndex) index);
-                } else if (index instanceof PrefixIndex) {
-                    qi = new PrefixContentIndex((PrefixIndex) index);
-                }
-                queryIndexList.add(qi);
-            }
-            queryIndexList.add(new UniqueIndex());
-        }
-        return queryIndexList;
-    }
-
     public PrefixIndex getPrefixIndex(String prefix) {
         return prefixIndexes.get(prefix);
     }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,73 @@
+/*
+ * 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.Iterator;
+
+import org.apache.jackrabbit.mk.simple.NodeImpl;
+
+/**
+ * An index is a lookup mechanism. It typically uses a tree to store data. It
+ * updates the tree whenever a node was changed. The index is updated
+ * automatically.
+ */
+public interface PIndex {
+
+    /**
+     * Get the unique index name. This is also the name of the index node.
+     *
+     * @return the index name
+     */
+    String getIndexNodeName();
+
+    /**
+     * The given node was added or removed.
+     *
+     * @param node the node including (old or new) data
+     * @param add true if added, false if removed
+     */
+    void addOrRemoveNode(NodeImpl node, boolean add);
+
+    /**
+     * The given property was added or removed.
+     *
+     * @param nodePath the path of the node
+     * @param propertyName the property name
+     * @param value the old (when deleting) or new (when adding) value
+     * @param add true if added, false if removed
+     */
+    void addOrRemoveProperty(String nodePath, String propertyName,
+            String value, boolean add);
+
+    /**
+     * Get an iterator over the paths for the given value. For unique
+     * indexes, the iterator will contain at most one element.
+     *
+     * @param value the value, or null to return all indexed rows
+     * @param revision the revision
+     * @return an iterator of the paths (an empty iterator if not found)
+     */
+    Iterator<String> getPaths(String value, String revision);
+
+    /**
+     * Whether each value may only appear once in the index.
+     *
+     * @return true if unique
+     */
+    boolean isUnique();
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PIndex.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PrefixIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PrefixIndex.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PrefixIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PrefixIndex.java Mon Sep 10 08:43:42 2012
@@ -16,50 +16,34 @@
  */
 package org.apache.jackrabbit.oak.plugins.index;
 
-import java.io.IOException;
 import java.util.Iterator;
 
 import org.apache.jackrabbit.mk.json.JsopReader;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
 import org.apache.jackrabbit.mk.simple.NodeImpl;
-import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
-import org.apache.jackrabbit.oak.spi.query.IndexDefinitionImpl;
-import org.apache.jackrabbit.oak.spi.query.IndexUtils;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
 /**
  * An index for all values with a given prefix.
  */
-public class PrefixIndex implements PIndex {
+public class PrefixIndex implements PIndex, PropertyIndexConstants {
 
-    private final Indexer indexer;
+    private final BTreeHelper indexer;
     private final BTree tree;
     private final String prefix;
 
-    private final IndexDefinition indexDefinition;
-
-    public PrefixIndex(Indexer indexer, String prefix) {
-        this(indexer, prefix, new IndexDefinitionImpl(prefix,
-                PropertyIndexFactory.TYPE_PREFIX, PathUtils.concat(
-                        IndexUtils.DEFAULT_INDEX_HOME, prefix), false, null));
-    }
-
-    public PrefixIndex(Indexer indexer, String prefix, IndexDefinition indexDefinition) {
+    public PrefixIndex(BTreeHelper indexer, String prefix) {
         this.indexer = indexer;
         this.prefix = prefix;
-        this.tree = new BTree(indexer, Indexer.TYPE_PREFIX + prefix, false);
+        this.tree = new BTree(indexer, TYPE_PREFIX + prefix, false);
         tree.setMinSize(10);
-        this.indexDefinition = indexDefinition;
     }
 
-    public static PrefixIndex fromNodeName(Indexer indexer, String nodeName) {
-        if (!nodeName.startsWith(Indexer.TYPE_PREFIX)) {
+    public static PrefixIndex fromNodeName(BTreeHelper indexer, String nodeName) {
+        if (!nodeName.startsWith(TYPE_PREFIX)) {
             return null;
         }
-        String prefix = nodeName.substring(Indexer.TYPE_PREFIX.length());
+        String prefix = nodeName.substring(TYPE_PREFIX.length());
         return new PrefixIndex(indexer, prefix);
     }
 
@@ -68,11 +52,6 @@ public class PrefixIndex implements PInd
     }
 
     @Override
-    public IndexDefinition getDefinition() {
-        return indexDefinition;
-    }
-
-    @Override
     public void addOrRemoveNode(NodeImpl node, boolean add) {
         String nodePath = node.getPath();
         for (int i = 0, size = node.getPropertyCount(); i < size; i++) {
@@ -145,15 +124,13 @@ public class PrefixIndex implements PInd
     }
 
     @Override
-    public void close() throws IOException {
-        // not needed
+    public String getIndexNodeName() {
+        return tree.getName();
     }
 
     @Override
-    public NodeState processCommit(NodeStore store, NodeState before,
-            NodeState after) throws CommitFailedException {
-        // TODO wire-in the processCommit mechanism
-        return after;
+    public boolean isUnique() {
+        return tree.isUnique();
     }
 
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,140 @@
+/*
+ * 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.Iterator;
+
+import org.apache.jackrabbit.mk.json.JsopReader;
+import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.simple.NodeImpl;
+
+/**
+ * A node handler that maps the property value to the key, and the path of the
+ * node to the value. Only string and numbers are indexes (arrays, true, false,
+ * and null are not indexes).
+ */
+public class PropertyIndex implements PIndex, PropertyIndexConstants {
+
+    private final BTreeHelper indexer;
+    private final BTree tree;
+    private final String propertyName;
+
+    public PropertyIndex(BTreeHelper indexer, String propertyName, boolean unique) {
+        this.indexer = indexer;
+        this.propertyName = propertyName;
+        this.tree = new BTree(indexer, TYPE_PROPERTY + propertyName 
+                + (unique ? "," + UNIQUE : ""), unique);
+        tree.setMinSize(10);
+    }
+
+    public static PropertyIndex fromNodeName(BTreeHelper indexer, String nodeName) {
+        if (!nodeName.startsWith(TYPE_PROPERTY)) {
+            return null;
+        }
+        boolean unique = false;
+        if (nodeName.endsWith(UNIQUE)) {
+            unique = true;
+            nodeName = nodeName.substring(0, nodeName.length() - UNIQUE.length() - 1);
+        }
+        String property = nodeName.substring(TYPE_PROPERTY.length());
+        return new PropertyIndex(indexer, property, unique);
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    @Override
+    public void addOrRemoveNode(NodeImpl node, boolean add) {
+        String value = node.getProperty(propertyName);
+        if (value != null) {
+            addOrRemoveRaw(node.getPath(), value, add);
+        }
+    }
+
+    @Override
+    public void addOrRemoveProperty(String nodePath, String propertyName,
+            String value, boolean add) {
+        if (this.propertyName.equals(propertyName)) {
+            addOrRemoveRaw(nodePath, value, add);
+        }
+    }
+
+    private void addOrRemoveRaw(String nodePath, String value, boolean add) {
+        JsopTokenizer t = new JsopTokenizer(value);
+        if (t.matches(JsopReader.STRING) || t.matches(JsopReader.NUMBER)) {
+            String v = t.getToken();
+            addOrRemove(nodePath, v, add);
+        }
+    }
+
+    private void addOrRemove(String nodePath, String value, boolean add) {
+        if (add) {
+            tree.add(value, nodePath);
+        } else {
+            tree.remove(value, nodePath);
+        }
+    }
+
+    /**
+     * Get the path for the given property value. For unique indexes, this will
+     * return the only path (if found). For non-unique indexes, this will return
+     * only one path.
+     *
+     * @param propertyValue the value
+     * @param revision the revision
+     * @return the path, or null if not found
+     */
+    public String getPath(String propertyValue, String revision) {
+        indexer.updateUntil(revision);
+        Cursor c = tree.findFirst(propertyValue);
+        if (!c.hasNext()) {
+            return null;
+        }
+        String key = c.next();
+        if (key.equals(propertyValue)) {
+            return c.getValue();
+        }
+        return null;
+    }
+
+    /**
+     * Get an iterator over the paths for the given property value. For unique
+     * indexes, the iterator will contain at most one element.
+     *
+     * @param propertyValue the value, or null to return all indexed rows
+     * @param revision the revision
+     * @return an iterator of the paths (an empty iterator if not found)
+     */
+    @Override
+    public Iterator<String> getPaths(String propertyValue, String revision) {
+        indexer.updateUntil(revision);
+        Cursor c = tree.findFirst(propertyValue);
+        return new Cursor.RangeIterator(c, propertyValue);
+    }
+
+    @Override
+    public String getIndexNodeName() {
+        return tree.getName();
+    }
+
+    @Override
+    public boolean isUnique() {
+        return tree.isUnique();
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,55 @@
+/*
+ * 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.query.IndexUtils;
+
+public interface PropertyIndexConstants {
+
+    String INDEX_TYPE_PROPERTY = "property";
+
+    /**
+     * The root node of the index definition (configuration) nodes.
+     */
+    // TODO OAK-178 discuss where to store index config data
+    String INDEX_CONFIG_PATH = IndexUtils.DEFAULT_INDEX_HOME + "/indexes";
+    // "/jcr:system/indexes";
+
+    /**
+     * For each index, the index content is stored relative to the index
+     * definition below this node. There is also such a node just below the
+     * index definition node, to store the last revision and for temporary data.
+     */
+    String INDEX_CONTENT = ":data";
+
+    /**
+     * The node name prefix of a prefix index.
+     */
+    String TYPE_PREFIX = "prefix@";
+
+    /**
+     * The node name prefix of a property index.
+     */
+    // TODO support multi-property indexes
+    String TYPE_PROPERTY = "property@";
+
+    /**
+     * Marks a unique index.
+     */
+    String UNIQUE = "unique";
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexConstants.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,85 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.plugins.unique.UniqueIndex;
+import org.apache.jackrabbit.oak.query.index.PrefixContentIndex;
+import org.apache.jackrabbit.oak.query.index.PropertyContentIndex;
+import org.apache.jackrabbit.oak.spi.QueryIndex;
+import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
+import org.apache.jackrabbit.oak.spi.query.IndexUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+public class PropertyIndexer implements QueryIndexProvider, CommitHook,
+        PropertyIndexConstants {
+
+    private final String indexConfigPath = IndexUtils.DEFAULT_INDEX_HOME;
+
+    private final Indexer indexer;
+
+    public PropertyIndexer(Indexer indexer) {
+        this.indexer = indexer;
+    }
+
+    @Override
+    public NodeState processCommit(NodeStore store, NodeState before,
+            NodeState after) throws CommitFailedException {
+        // TODO update index data
+        return after;
+    }
+
+    @Override
+    public List<? extends QueryIndex> getQueryIndexes(NodeStore store) {
+        List<QueryIndex> queryIndexList = new ArrayList<QueryIndex>();
+        NodeBuilder rootBuilder = IndexUtils.getChildBuilder(store,
+                indexConfigPath);
+        List<IndexDefinition> indexDefinitions = IndexUtils
+                .buildIndexDefinitions(store.getRoot(), indexConfigPath,
+                        INDEX_TYPE_PROPERTY);
+        for (IndexDefinition def : indexDefinitions) {
+            NodeBuilder builder = rootBuilder.getChildBuilder(def.getName());
+            // create the global :data node
+            builder.getChildBuilder(INDEX_CONTENT);
+            for (String k : builder.getChildNodeNames()) {
+                PropertyIndex prop = PropertyIndex.fromNodeName(indexer, k);
+                if (prop != null) {
+                    // create the :data node
+                    builder.getChildBuilder(prop.getIndexNodeName())
+                            .getChildBuilder(INDEX_CONTENT);
+                    queryIndexList.add(new PropertyContentIndex(prop));
+                }
+                PrefixIndex pref = PrefixIndex.fromNodeName(indexer, k);
+                if (pref != null) {
+                    // create the :data node
+                    builder.getChildBuilder(pref.getIndexNodeName())
+                            .getChildBuilder(INDEX_CONTENT);
+                    queryIndexList.add(new PrefixContentIndex(pref));
+                }
+            }
+        }
+        queryIndexList.add(new UniqueIndex());
+        return queryIndexList;
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndexer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,235 @@
+/*
+ * 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.lucene;
+
+import static org.apache.jackrabbit.oak.plugins.lucene.FieldFactory.newPathField;
+import static org.apache.jackrabbit.oak.plugins.lucene.FieldFactory.newPropertyField;
+import static org.apache.jackrabbit.oak.plugins.lucene.TermFactory.newPathTerm;
+import static org.apache.jackrabbit.oak.spi.query.IndexUtils.split;
+
+import java.io.IOException;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+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.jackrabbit.oak.spi.state.NodeStore;
+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.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();
+
+    private static final Version VERSION = Version.LUCENE_40;
+
+    private static final Analyzer ANALYZER = new StandardAnalyzer(VERSION);
+
+    private static final IndexWriterConfig config = getIndexWriterConfig();
+
+    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 String[] path;
+
+    public LuceneEditor(IndexDefinition indexDefinition) {
+        this.path = split(indexDefinition.getPath(), INDEX_DATA_CHILD_NAME);
+    }
+
+    @Override
+    public NodeState processCommit(NodeStore store, NodeState before,
+            NodeState after) throws CommitFailedException {
+        try {
+            OakDirectory directory = new OakDirectory(store, after, path);
+
+            IndexWriter writer = new IndexWriter(directory, config);
+            try {
+                LuceneDiff diff = new LuceneDiff(writer, "");
+                after.compareAgainstBaseState(before, diff);
+                diff.postProcess(after);
+                writer.commit();
+            } finally {
+                writer.close();
+            }
+
+            return directory.getRoot();
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new CommitFailedException(
+                    "Failed to update 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(path + "/" + name, after);
+                } catch (IOException e) {
+                    exception = e;
+                }
+            }
+        }
+
+        @Override
+        public void childNodeChanged(String name, NodeState before,
+                NodeState after) {
+            if (NodeStateUtils.isHidden(name)) {
+                return;
+            }
+            if (exception == null) {
+                try {
+                    LuceneDiff diff = new LuceneDiff(writer, 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(path + "/" + name, before);
+                } catch (IOException e) {
+                    exception = e;
+                }
+            }
+        }
+
+        private void addSubtree(String path, NodeState state)
+                throws IOException {
+            writer.addDocument(makeDocument(path, state));
+            for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+                addSubtree(path + "/" + entry.getName(), entry.getNodeState());
+            }
+        }
+
+        private void deleteSubtree(String path, NodeState state)
+                throws IOException {
+            writer.deleteDocuments(newPathTerm(path));
+            for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+                deleteSubtree(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();
+                for (CoreValue value : property.getValues()) {
+                    document.add(newPropertyField(pname,
+                            parseStringValue(value)));
+                }
+            }
+            return document;
+        }
+
+        private static String parseStringValue(CoreValue value) {
+            String string;
+            if (value.getType() != PropertyType.BINARY) {
+                string = value.getString();
+            } else {
+                try {
+                    string = TIKA.parseToString(value.getNewStream());
+                } catch (IOException e) {
+                    string = "";
+                } catch (TikaException e) {
+                    string = "";
+                }
+            }
+            return string;
+        }
+
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneEditor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,62 @@
+/*
+ * 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.lucene;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.commit.CompositeHook;
+import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
+import org.apache.jackrabbit.oak.spi.query.IndexUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+
+public class LuceneHook implements CommitHook, LuceneIndexConstants {
+
+    private final String indexConfigPath;
+
+    public LuceneHook(String indexConfigPath) {
+        this.indexConfigPath = indexConfigPath;
+    }
+
+    /**
+     * TODO test only
+     */
+    public LuceneHook() {
+        this(IndexUtils.DEFAULT_INDEX_HOME);
+    }
+
+    @Override
+    public NodeState processCommit(NodeStore store, NodeState before,
+            NodeState after) throws CommitFailedException {
+
+        List<CommitHook> hooks = new ArrayList<CommitHook>();
+        List<IndexDefinition> indexDefinitions = IndexUtils
+                .buildIndexDefinitions(after, indexConfigPath, TYPE);
+        for (IndexDefinition def : indexDefinitions) {
+            hooks.add(new LuceneEditor(def));
+        }
+        if (hooks.isEmpty()) {
+            return after;
+        }
+
+        return new CompositeHook(hooks).processCommit(store, before, after);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneHook.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndex.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndex.java Mon Sep 10 08:43:42 2012
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.plugin
 
 import static org.apache.jackrabbit.oak.plugins.lucene.FieldNames.PATH;
 import static org.apache.jackrabbit.oak.plugins.lucene.FieldNames.PATH_SELECTOR;
-import static org.apache.jackrabbit.oak.plugins.lucene.LuceneIndexUtils.INDEX_DATA_CHILD_NAME;
 import static org.apache.jackrabbit.oak.plugins.lucene.TermFactory.newPathTerm;
 import static org.apache.jackrabbit.oak.spi.query.IndexUtils.split;
 
@@ -55,7 +54,7 @@ import org.apache.lucene.store.Directory
 /**
  * This index uses internally runs a query against a Lucene index.
  */
-public class LuceneIndex implements QueryIndex {
+public class LuceneIndex implements QueryIndex, LuceneIndexConstants {
 
     private final NodeStore store;
 

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java?rev=1382692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java Mon Sep 10 08:43:42 2012
@@ -0,0 +1,27 @@
+/*
+ * 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.lucene;
+
+public interface LuceneIndexConstants {
+
+    String TYPE = "lucene";
+
+    String DEFAULT_INDEX_NAME = "default-lucene";
+
+    String INDEX_DATA_CHILD_NAME = ":data";
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexConstants.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexProvider.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/lucene/LuceneIndexProvider.java Mon Sep 10 08:43:42 2012
@@ -16,91 +16,50 @@
  */
 package org.apache.jackrabbit.oak.plugins.lucene;
 
-import static org.apache.jackrabbit.oak.plugins.lucene.LuceneIndexUtils.getIndexInfos;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
 import org.apache.jackrabbit.oak.spi.QueryIndex;
 import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
 import org.apache.jackrabbit.oak.spi.query.IndexDefinition;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.query.IndexUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A provider for Lucene indexes. There is exactly one Lucene index instance per
- * MicroKernel.
+ * A provider for Lucene indexes.
  */
-public class LuceneIndexProvider implements QueryIndexProvider {
+public class LuceneIndexProvider implements QueryIndexProvider,
+        LuceneIndexConstants {
 
     private static final Logger LOG = LoggerFactory
             .getLogger(LuceneIndexProvider.class);
 
     private final String indexPath;
 
-    private boolean init;
-
-    /**
-     * The indexes list
-     * 
-     * lazy init
-     */
-    private List<QueryIndex> indexes = null;
-
     public LuceneIndexProvider(String indexPath) {
         this.indexPath = indexPath;
     }
 
-    private void init(MicroKernel mk) {
-        if (init) {
-            return;
-        }
-        LOG.debug("initializing indexes");
-
+    @Override
+    public List<QueryIndex> getQueryIndexes(NodeStore store) {
         if (!PathUtils.isValid(indexPath)) {
             LOG.warn("index path is not valid {}", indexPath);
-            indexes = Collections.<QueryIndex> emptyList();
-            init = true;
-            return;
-        }
-
-        NodeStore store = new KernelNodeStore(mk);
-        NodeState index = store.getRoot();
-        for (String e : PathUtils.elements(indexPath)) {
-            if (PathUtils.denotesRoot(e)) {
-                continue;
-            }
-            index = index.getChildNode(e);
-            if (index == null) {
-                break;
-            }
-        }
-
-        if (index == null) {
-            // TODO what should happen when the index node doesn't exist?
-            indexes = Collections.<QueryIndex> emptyList();
-            init = true;
-            return;
+            return Collections.<QueryIndex> emptyList();
         }
-
+        NodeBuilder builder = IndexUtils.getChildBuilder(store, indexPath);
         List<QueryIndex> tempIndexes = new ArrayList<QueryIndex>();
-        for (IndexDefinition childIndex : getIndexInfos(index, indexPath)) {
-            LOG.debug("adding a new lucene index instance @ {}", childIndex);
-            tempIndexes.add(new LuceneIndex(store, childIndex));
+        for (IndexDefinition child : IndexUtils.buildIndexDefinitions(
+                store.getRoot(), indexPath, TYPE)) {
+            // add :data node
+            builder.getChildBuilder(child.getName()).getChildBuilder(
+                    INDEX_DATA_CHILD_NAME);
+            tempIndexes.add(new LuceneIndex(store, child));
         }
-        indexes = new ArrayList<QueryIndex>(tempIndexes);
-        init = true;
-    }
-
-    @Override
-    public List<QueryIndex> getQueryIndexes(MicroKernel mk) {
-        init(mk);
-        return indexes;
+        return tempIndexes;
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java Mon Sep 10 08:43:42 2012
@@ -128,7 +128,7 @@ public class QueryEngineImpl {
     }
 
     private List<? extends QueryIndex> getIndexes() {
-        return indexProvider.getQueryIndexes(mk);
+        return indexProvider.getQueryIndexes(store);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PrefixContentIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PrefixContentIndex.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PrefixContentIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PrefixContentIndex.java Mon Sep 10 08:43:42 2012
@@ -98,7 +98,7 @@ public class PrefixContentIndex implemen
 
     @Override
     public String getIndexName() {
-        return index.getDefinition().getName();
+        return index.getIndexNodeName();
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java Mon Sep 10 08:43:42 2012
@@ -49,7 +49,7 @@ public class PropertyContentIndex implem
             // only support equality matches (for now)
             return Double.MAX_VALUE;
         }
-        boolean unique = index.getDefinition().isUnique();
+        boolean unique = index.isUnique();
         return unique ? 2 : 20;
     }
 
@@ -76,7 +76,7 @@ public class PropertyContentIndex implem
 
     @Override
     public String getIndexName() {
-        return index.getDefinition().getName();
+        return index.getIndexNodeName();
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/QueryIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/QueryIndexProvider.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/QueryIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/QueryIndexProvider.java Mon Sep 10 08:43:42 2012
@@ -19,7 +19,8 @@
 package org.apache.jackrabbit.oak.spi;
 
 import java.util.List;
-import org.apache.jackrabbit.mk.api.MicroKernel;
+
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
 /**
  * A mechanism to index data. Indexes might be added or removed at runtime,
@@ -29,11 +30,10 @@ import org.apache.jackrabbit.mk.api.Micr
 public interface QueryIndexProvider {
 
     /**
-     * Get the currently configured indexes for the given MicroKernel instance.
-     *
-     * @param mk the MicroKernel instance
+     * Get the currently configured indexes.
+     * 
      * @return the list of indexes
      */
-    List<? extends QueryIndex> getQueryIndexes(MicroKernel mk);
+    List<? extends QueryIndex> getQueryIndexes(NodeStore nodeStore);
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/CompositeQueryIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/CompositeQueryIndexProvider.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/CompositeQueryIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/CompositeQueryIndexProvider.java Mon Sep 10 08:43:42 2012
@@ -21,9 +21,10 @@ import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.oak.spi.QueryIndex;
 import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
 
 /**
  * This {@code QueryIndexProvider} aggregates a list of query index providers
@@ -47,10 +48,10 @@ public class CompositeQueryIndexProvider
     }
 
     @Override
-    public List<? extends QueryIndex> getQueryIndexes(MicroKernel mk) {
+    public List<? extends QueryIndex> getQueryIndexes(NodeStore nodeStore) {
         List<QueryIndex> indexes = new ArrayList<QueryIndex>();
         for (QueryIndexProvider qip : providers) {
-            List<? extends QueryIndex> t = qip.getQueryIndexes(mk);
+            List<? extends QueryIndex> t = qip.getQueryIndexes(nodeStore);
             if (t != null) {
                 indexes.addAll(t);
             }

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=1382692&r1=1382691&r2=1382692&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 Mon Sep 10 08:43:42 2012
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.oak.spi.query;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -25,7 +26,9 @@ import java.util.Map;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 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.NodeStore;
 
 public class IndexUtils {
 
@@ -34,6 +37,8 @@ public class IndexUtils {
      */
     public static final String DEFAULT_INDEX_HOME = "/oak-index";
 
+    private static final String TYPE_UNKNOWN = "unknown";
+
     /**
      * Builds an {@link IndexDefinition} out of a {@link ChildNodeEntry}
      * 
@@ -42,10 +47,10 @@ public class IndexUtils {
         String name = def.getName();
         PropertyState typeProp = def.getNodeState().getProperty(
                 IndexDefinition.TYPE_PROPERTY_NAME);
-        if (typeProp == null || typeProp.isArray()) {
-            return null;
+        String type = TYPE_UNKNOWN;
+        if (typeProp != null && !typeProp.isArray()) {
+            type = typeProp.getValue().getString();
         }
-        String type = typeProp.getValue().getString();
 
         boolean unique = false;
         PropertyState uniqueProp = def.getNodeState().getProperty(
@@ -102,4 +107,40 @@ public class IndexUtils {
         return retval;
     }
 
+    /**
+     * Builds a list of the existing index definitions from the repository
+     * 
+     */
+    public static List<IndexDefinition> buildIndexDefinitions(
+            NodeState nodeState, String indexConfigPath, String typeFilter) {
+        NodeState definitions = getNode(nodeState, indexConfigPath);
+        if (definitions == null) {
+            return Collections.emptyList();
+        }
+
+        List<IndexDefinition> defs = new ArrayList<IndexDefinition>();
+        for (ChildNodeEntry c : definitions.getChildNodeEntries()) {
+            IndexDefinition def = IndexUtils.getDefinition(indexConfigPath, c);
+            if (def == null
+                    || (typeFilter != null && !typeFilter.equals(def.getType()))) {
+                continue;
+            }
+            defs.add(def);
+        }
+        return defs;
+    }
+
+    public static NodeBuilder getChildBuilder(NodeStore store, String path) {
+        return getChildBuilder(store, store.getRoot(), path);
+    }
+
+    public static NodeBuilder getChildBuilder(NodeStore store, NodeState state,
+            String path) {
+        NodeBuilder builder = store.getBuilder(state);
+        for (String p : PathUtils.elements(path)) {
+            builder = builder.getChildBuilder(p);
+        }
+        return builder;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java?rev=1382692&r1=1382691&r2=1382692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java Mon Sep 10 08:43:42 2012
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.oak.plugins.lucene;
 
-import static org.apache.jackrabbit.oak.plugins.lucene.LuceneIndexUtils.DEFAULT_INDEX_NAME;
-import static org.apache.jackrabbit.oak.plugins.lucene.LuceneIndexUtils.createIndexNode;
 import static org.apache.jackrabbit.oak.spi.query.IndexUtils.DEFAULT_INDEX_HOME;
 
 import java.text.ParseException;
@@ -33,11 +31,7 @@ import org.apache.jackrabbit.oak.api.Cor
 import org.apache.jackrabbit.oak.api.Result;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.SessionQueryEngine;
-import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.core.ContentRepositoryImpl;
-import org.apache.jackrabbit.oak.core.DefaultConflictHandler;
-import org.apache.jackrabbit.oak.plugins.index.PropertyIndexFactory;
 import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceValidatorProvider;
 import org.apache.jackrabbit.oak.plugins.type.DefaultTypeEditor;
@@ -50,20 +44,16 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.commit.ValidatingHook;
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
 import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider;
-import org.apache.jackrabbit.oak.spi.query.IndexManager;
-import org.apache.jackrabbit.oak.spi.query.IndexManagerImpl;
-import org.apache.jackrabbit.oak.spi.query.IndexUtils;
 import org.junit.Before;
 
 /**
  * base class for lucene search tests
  */
-public abstract class AbstractLuceneQueryTest extends AbstractOakTest {
+public abstract class AbstractLuceneQueryTest extends AbstractOakTest implements
+        LuceneIndexConstants {
 
     protected static final String SQL2 = "JCR-SQL2";
 
-    private static final String TEST_INDEX_NAME = DEFAULT_INDEX_NAME;
-
     protected MicroKernel mk;
     protected ContentSession session;
     protected CoreValueFactory vf;
@@ -78,8 +68,6 @@ public abstract class AbstractLuceneQuer
         root = session.getCurrentRoot();
         vf = session.getCoreValueFactory();
         qe = session.getQueryEngine();
-        cleanupIndexNode();
-
     }
 
     @Override
@@ -91,13 +79,10 @@ public abstract class AbstractLuceneQuer
     }
 
     private CommitHook buildDefaultCommitHook() {
-        IndexManager im = new IndexManagerImpl(IndexUtils.DEFAULT_INDEX_HOME,
-                mk, new PropertyIndexFactory(), new LuceneIndexFactory());
-
         List<CommitHook> hooks = new ArrayList<CommitHook>();
         hooks.add(new DefaultTypeEditor());
         hooks.add(new ValidatingHook(createDefaultValidatorProvider()));
-        hooks.add(im);
+        hooks.add(new LuceneHook(DEFAULT_INDEX_HOME));
         return new CompositeHook(hooks);
     }
 
@@ -110,33 +95,6 @@ public abstract class AbstractLuceneQuer
         return new CompositeValidatorProvider(providers);
     }
 
-    /**
-     * Recreates an empty index node, ready to be used in tests
-     * 
-     * @throws Exception
-     */
-    private void cleanupIndexNode() throws Exception {
-        Tree index = root.getTree(DEFAULT_INDEX_HOME);
-        if (index != null) {
-            index = index.getChild(TEST_INDEX_NAME);
-            if (index != null) {
-                index.remove();
-            }
-        } else {
-            index = root.getTree("/");
-            for (String p : PathUtils.elements(DEFAULT_INDEX_HOME)) {
-                if (index.hasChild(p)) {
-                    index = index.getChild(p);
-                } else {
-                    index = index.addChild(p);
-                }
-            }
-        }
-
-        createIndexNode(root.getTree(DEFAULT_INDEX_HOME), TEST_INDEX_NAME, vf);
-        root.commit(DefaultConflictHandler.OURS);
-    }
-
     protected Result executeQuery(String statement) throws ParseException {
         return qe.executeQuery(statement, SQL2, Long.MAX_VALUE, 0, null, null);
     }



Mime
View raw message