jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1347985 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/mk/index/ main/java/org/apache/jackrabbit/oak/query/index/ test/java/org/apache/jackrabbit/mk/index/ test/java/org/apache/jackrabbit/mk/wrapper/ test/java/org...
Date Fri, 08 Jun 2012 09:49:57 GMT
Author: thomasm
Date: Fri Jun  8 09:49:56 2012
New Revision: 1347985

URL: http://svn.apache.org/viewvc?rev=1347985&view=rev
Log:
OAK-137 Query: content index (improved robustness, moved code away from the index wrapper
to the indexer, don't use a colon in the node name for JCR compatibility)

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreePage.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Index.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/IndexWrapper.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PrefixIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PropertyIndex.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/PropertyContentIndex.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/IndexTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PrefixIndexTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PropertyIndexTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/wrapper/IndexWrapperTest.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/queryTest.txt

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTree.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
Fri Jun  8 09:49:56 2012
@@ -129,7 +129,7 @@ public class BTree {
         JsopBuilder jsop = new JsopBuilder();
         path = PathUtils.concat(name, path);
         jsop.tag('^').key(PathUtils.concat(path, propertyName));
-        if (data.length == 0) {
+        if (data == null) {
             jsop.value(null);
         } else {
             jsop.array();
@@ -208,7 +208,6 @@ public class BTree {
                 break;
             }
         }
-        commit();
         return true;
     }
 
@@ -240,8 +239,6 @@ public class BTree {
                     // other node now)
                     n = parent;
                 }
-                // subsequent operations are based on the new structure
-                commit();
             }
             if (n instanceof BTreeNode) {
                 BTreeNode page = (BTreeNode) n;
@@ -269,11 +266,6 @@ public class BTree {
                 break;
             }
         }
-        commit();
-    }
-
-    void commit() {
-        indexer.commit();
     }
 
     String getName() {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
Fri Jun  8 09:49:56 2012
@@ -29,6 +29,7 @@ class BTreeLeaf extends BTreePage {
 
     BTreeLeaf(BTree tree, BTreeNode parent, String name, String[] data, String[] paths) {
         super(tree, parent, name, data, paths);
+        verify();
     }
 
     BTreeLeaf nextLeaf() {
@@ -56,22 +57,27 @@ class BTreeLeaf extends BTreePage {
         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);
         JsopBuilder jsop = new JsopBuilder();
         jsop.tag('+').key(PathUtils.concat(tree.getName(), getPath())).object();
@@ -90,4 +96,12 @@ class BTreeLeaf extends BTreePage {
         tree.buffer(jsop.toString());
     }
 
+    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));
+        }
+    }
+
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
Fri Jun  8 09:49:56 2012
@@ -31,6 +31,7 @@ class BTreeNode extends BTreePage {
     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() {
@@ -65,6 +66,7 @@ class BTreeNode extends BTreePage {
         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(
@@ -95,6 +97,7 @@ class BTreeNode extends BTreePage {
     }
 
     void writeData() {
+        verify();
         tree.modified(this);
         tree.bufferSetArray(getPath(), "keys", keys);
         tree.bufferSetArray(getPath(), "values", values);
@@ -103,6 +106,7 @@ class BTreeNode extends BTreePage {
 
     @Override
     void writeCreate() {
+        verify();
         tree.modified(this);
         JsopBuilder jsop = new JsopBuilder();
         jsop.tag('+').key(PathUtils.concat(tree.getName(), getPath())).object();
@@ -138,6 +142,7 @@ class BTreeNode extends BTreePage {
             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) {
@@ -145,10 +150,26 @@ class BTreeNode extends BTreePage {
         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;
     }
 
+    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));
+            }
+        }
+    }
+
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreePage.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreePage.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreePage.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/BTreePage.java
Fri Jun  8 09:49:56 2012
@@ -57,7 +57,6 @@ abstract class BTreePage {
             name = newName;
             tree.moveCache(oldPath);
             tree.modified(this);
-            tree.commit();
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Index.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Index.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Index.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Index.java
Fri Jun  8 09:49:56 2012
@@ -31,7 +31,7 @@ public interface Index {
      *
      * @return the index name
      */
-    String getName();
+    String getIndexNodeName();
 
     /**
      * The given node was added or removed.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/IndexWrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/IndexWrapper.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/IndexWrapper.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/IndexWrapper.java
Fri Jun  8 09:49:56 2012
@@ -17,34 +17,25 @@
 package org.apache.jackrabbit.mk.index;
 
 import java.io.InputStream;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.mk.json.JsopReader;
 import org.apache.jackrabbit.mk.json.JsopStream;
-import org.apache.jackrabbit.mk.simple.NodeImpl;
-import org.apache.jackrabbit.mk.simple.NodeMap;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.mk.wrapper.MicroKernelWrapper;
 import org.apache.jackrabbit.mk.wrapper.MicroKernelWrapperBase;
-import org.apache.jackrabbit.oak.spi.QueryIndexProvider;
 
 /**
  * The index mechanism, as a wrapper.
  */
 public class IndexWrapper extends MicroKernelWrapperBase implements MicroKernel {
 
-    private static final String TYPE_PREFIX = "prefix:";
-    private static final String TYPE_PROPERTY = "property:";
-    private static final String UNIQUE = "unique";
-
     private final MicroKernelWrapper mk;
     private final Indexer indexer;
-    private final NodeMap map = new NodeMap();
-    private final HashMap<String, PrefixIndex> prefixIndexes = new HashMap<String,
PrefixIndex>();
-    private final HashMap<String, PropertyIndex> propertyIndexes = new HashMap<String,
PropertyIndex>();
+    private final HashSet<String> branchRevisions = new HashSet<String>();
 
     public IndexWrapper(MicroKernel mk) {
         this.mk = MicroKernelWrapperBase.wrap(mk);
@@ -52,7 +43,7 @@ public class IndexWrapper extends MicroK
         indexer.init();
     }
 
-    public QueryIndexProvider getIndexer() {
+    public Indexer getIndexer() {
         return indexer;
     }
 
@@ -97,81 +88,33 @@ public class IndexWrapper extends MicroK
 
     @Override
     public String branch(String trunkRevisionId) {
-        return mk.branch(trunkRevisionId);
+        String branchRevision = mk.branch(trunkRevisionId);
+        branchRevisions.add(branchRevision);
+        return branchRevision;
     }
 
     @Override
     public String merge(String branchRevisionId, String message) {
-        return mk.merge(branchRevisionId, message);
+        String headRevision = mk.merge(branchRevisionId, message);
+        branchRevisions.remove(branchRevisionId);
+        indexer.updateUntil(headRevision);
+        return mk.getHeadRevision();
     }
 
     @Override
     public String commitStream(String rootPath, JsopReader jsonDiff, String revisionId, String
message) {
-        String indexRoot = indexer.getIndexRootNode();
-        if (!rootPath.startsWith(indexRoot)) {
+        if (branchRevisions.remove(revisionId)) {
+            // TODO update the index in the branch as well, if required
             String rev = mk.commitStream(rootPath, jsonDiff, revisionId, message);
-            jsonDiff.resetReader();
-            indexer.updateIndex(rootPath, jsonDiff, rev);
-            rev = mk.getHeadRevision();
-            rev = indexer.updateEnd(rev);
+            branchRevisions.add(rev);
             return rev;
         }
-        JsopReader t = jsonDiff;
-        while (true) {
-            int r = t.read();
-            if (r == JsopReader.END) {
-                break;
-            }
-            String path;
-            if (rootPath == null) {
-                path = t.readString();
-            } else {
-                path = PathUtils.concat(rootPath, t.readString());
-            }
-            switch (r) {
-            case '+':
-                t.read(':');
-                t.read('{');
-                // parse but ignore
-                NodeImpl.parse(map, t, 0);
-                path = PathUtils.relativize(indexRoot, path);
-                if (path.startsWith(TYPE_PREFIX)) {
-                    String prefix = path.substring(TYPE_PREFIX.length());
-                    PrefixIndex idx = indexer.createPrefixIndex(prefix);
-                    prefixIndexes.put(path, idx);
-                } else if (path.startsWith(TYPE_PROPERTY)) {
-                    String property = path.substring(TYPE_PROPERTY.length());
-                    boolean unique = false;
-                    if (property.endsWith("," + UNIQUE)) {
-                        unique = true;
-                        property = property.substring(0, property.length() - UNIQUE.length()
- 1);
-                    }
-                    PropertyIndex idx = indexer.createPropertyIndex(property, unique);
-                    propertyIndexes.put(path, idx);
-                } else {
-                    throw ExceptionFactory.get("Unknown index type: " + path);
-                }
-                break;
-            case '-':
-                path = PathUtils.relativize(indexRoot, path);
-                if (path.startsWith(TYPE_PREFIX)) {
-                    String prefix = path.substring(TYPE_PREFIX.length());
-                    indexer.removePrefixIndex(prefix);
-                } else if (path.startsWith(TYPE_PROPERTY)) {
-                    String property = path.substring(TYPE_PROPERTY.length());
-                    boolean unique = false;
-                    if (property.endsWith("," + UNIQUE)) {
-                        unique = true;
-                        property = property.substring(0, property.length() - UNIQUE.length()
- 1);
-                    }
-                    indexer.removePropertyIndex(property, unique);
-                }
-                break;
-            default:
-                throw ExceptionFactory.get("token: " + (char) t.getTokenType());
-            }
-        }
-        return null;
+        String rev = mk.commitStream(rootPath, jsonDiff, revisionId, message);
+        jsonDiff.resetReader();
+        indexer.updateIndex(rootPath, jsonDiff, rev);
+        rev = mk.getHeadRevision();
+        rev = indexer.updateEnd(rev);
+        return rev;
     }
 
     @Override
@@ -183,39 +126,33 @@ public class IndexWrapper extends MicroK
         String index = PathUtils.relativize(indexRoot, path);
         int idx = index.indexOf('?');
         if (idx < 0) {
-            // invalid query - expected: /index/prefix:x?y
-            return null;
+            // not a query (expected: /index/prefix:x?y) - treat as regular node lookup
+            return mk.getNodesStream(path, revisionId, depth, offset, count, filter);
         }
         String data = index.substring(idx + 1);
         index = index.substring(0, idx);
         JsopStream s = new JsopStream();
         s.array();
-        if (index.startsWith(TYPE_PREFIX)) {
-            PrefixIndex prefixIndex = prefixIndexes.get(index);
+        if (index.startsWith(Indexer.TYPE_PREFIX)) {
+            String prefix = index.substring(Indexer.TYPE_PREFIX.length());
+            PrefixIndex prefixIndex = indexer.getPrefixIndex(prefix);
             if (prefixIndex == null) {
-                if (mk.nodeExists(path, mk.getHeadRevision())) {
-                    prefixIndex = indexer.createPrefixIndex(index);
-                } else {
-                    throw ExceptionFactory.get("Unknown index: " + index);
-                }
+                throw ExceptionFactory.get("Unknown index: " + index);
             }
             Iterator<String> it = prefixIndex.getPaths(data, revisionId);
             while (it.hasNext()) {
                 s.value(it.next());
             }
-        } else if (index.startsWith(TYPE_PROPERTY)) {
-            PropertyIndex propertyIndex = propertyIndexes.get(index);
-            boolean unique = index.endsWith("," + UNIQUE);
+        } else if (index.startsWith(Indexer.TYPE_PROPERTY)) {
+            String property = index.substring(Indexer.TYPE_PROPERTY.length());
+            boolean unique = false;
+            if (property.endsWith("," + Indexer.UNIQUE)) {
+                unique = true;
+                property = property.substring(0, property.length() - Indexer.UNIQUE.length()
- 1);
+            }
+            PropertyIndex propertyIndex = indexer.getPropertyIndex(property);
             if (propertyIndex == null) {
-                if (mk.nodeExists(path, mk.getHeadRevision())) {
-                    String indexName = index;
-                    if (unique) {
-                        indexName = index.substring(0, index.length() - UNIQUE.length() -
1);
-                    }
-                    propertyIndex = indexer.createPropertyIndex(indexName, unique);
-                } else {
-                    throw ExceptionFactory.get("Unknown index: " + index);
-                }
+                throw ExceptionFactory.get("Unknown index: " + index);
             }
             if (unique) {
                 String value = propertyIndex.getPath(data, revisionId);
@@ -257,4 +194,8 @@ public class IndexWrapper extends MicroK
         // do nothing
     }
 
+    public MicroKernel getBaseKernel() {
+        return mk;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
Fri Jun  8 09:49:56 2012
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.mk.index;
 
-import org.apache.jackrabbit.mk.core.MicroKernelImpl;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
 import org.apache.jackrabbit.mk.json.JsopReader;
@@ -46,23 +45,57 @@ public class Indexer implements QueryInd
     // TODO discuss where to store index config data
     public static final String INDEX_CONFIG_ROOT = "/jcr:system/indexes";
 
+    /**
+     * The node name prefix of a prefix index.
+     */
+    static final String TYPE_PREFIX = "prefix@";
+
+    /**
+     * The node name prefix of a property index.
+     */
+    static final String TYPE_PROPERTY = "property@";
+
+    /**
+     * Marks a unique index.
+     */
+    static final String UNIQUE = "unique";
+
     private static final boolean DISABLED = Boolean.getBoolean("mk.indexDisabled");
 
     private MicroKernel mk;
     private MicroKernel mkWrapper;
     private String revision;
     private String indexRootNode;
+    private int indexRootNodeDepth;
     private StringBuilder buffer;
-    private HashMap<String, Index> indexes = new HashMap<String, Index>();
     private ArrayList<QueryIndex> queryIndexList;
     private HashMap<String, BTreePage> modified = new HashMap<String, BTreePage>();
     private SimpleLRUCache<String, BTreePage> cache = SimpleLRUCache.newInstance(100);
     private String readRevision;
     private boolean init;
 
+    /**
+     * An index node name to index map.
+     */
+    private HashMap<String, Index> indexes = new HashMap<String, Index>();
+
+    /**
+     * A prefix to prefix index map.
+     */
+    private final HashMap<String, PrefixIndex> prefixIndexes = new HashMap<String,
PrefixIndex>();
+
+    /**
+     * A property name to property index map.
+     */
+    private final HashMap<String, PropertyIndex> propertyIndexes = new HashMap<String,
PropertyIndex>();
+
     public Indexer(MicroKernel mkWrapper, MicroKernel mk, String indexRootNode) {
         this.mkWrapper = mkWrapper;
-        this.mk = mk;
+        if (mkWrapper instanceof IndexWrapper) {
+            this.mk = ((IndexWrapper) mkWrapper).getBaseKernel();
+        } else {
+            this.mk = mk;
+        }
         this.indexRootNode = indexRootNode;
     }
 
@@ -82,6 +115,7 @@ public class Indexer implements QueryInd
         if (!PathUtils.isAbsolute(indexRootNode)) {
             indexRootNode = "/" + indexRootNode;
         }
+        indexRootNodeDepth = PathUtils.getDepth(indexRootNode);
         revision = mk.getHeadRevision();
         readRevision = revision;
         if (!mk.nodeExists(indexRootNode, revision)) {
@@ -111,12 +145,16 @@ public class Indexer implements QueryInd
                 readRevision = rev;
             }
             for (String k : map.keySet()) {
-                Index p = PropertyIndex.fromNodeName(this, k);
-                if (p == null) {
-                    p = PrefixIndex.fromNodeName(this, k);
+                PropertyIndex prop = PropertyIndex.fromNodeName(this, k);
+                if (prop != null) {
+                    indexes.put(prop.getIndexNodeName(), prop);
+                    propertyIndexes.put(prop.getPropertyName(), prop);
+                    queryIndexList = null;
                 }
-                if (p != null) {
-                    indexes.put(p.getName(), p);
+                PrefixIndex pref = PrefixIndex.fromNodeName(this, k);
+                if (pref != null) {
+                    indexes.put(pref.getIndexNodeName(), pref);
+                    prefixIndexes.put(pref.getPrefix(), pref);
                     queryIndexList = null;
                 }
             }
@@ -124,34 +162,40 @@ public class Indexer implements QueryInd
     }
 
     public void removePropertyIndex(String property, boolean unique) {
-        PropertyIndex index = new PropertyIndex(this, property, unique);
-        indexes.remove(index.getName());
+        PropertyIndex index = propertyIndexes.remove(property);
+        indexes.remove(index.getIndexNodeName());
         queryIndexList = null;
     }
 
     public PropertyIndex createPropertyIndex(String property, boolean unique) {
-        PropertyIndex index = new PropertyIndex(this, property, unique);
-        PropertyIndex existing = (PropertyIndex) indexes.get(index.getName());
+        PropertyIndex existing = propertyIndexes.get(property);
         if (existing != null) {
             return existing;
         }
-        buildAndAddIndex(index);
+        PropertyIndex index = new PropertyIndex(this, property, unique);
+        buildIndex(index);
+        indexes.put(index.getIndexNodeName(), index);
+        propertyIndexes.put(index.getPropertyName(), index);
+        queryIndexList = null;
         return index;
     }
 
     public void removePrefixIndex(String prefix) {
-        PrefixIndex index = new PrefixIndex(this, prefix);
-        indexes.remove(index.getName());
-        queryIndexList = null;
+         PrefixIndex index = prefixIndexes.remove(prefix);
+         indexes.remove(index.getIndexNodeName());
+         queryIndexList = null;
     }
 
     public PrefixIndex createPrefixIndex(String prefix) {
-        PrefixIndex index = new PrefixIndex(this, prefix);
-        PrefixIndex existing = (PrefixIndex) indexes.get(index.getName());
+        PrefixIndex existing = prefixIndexes.get(prefix);
         if (existing != null) {
             return existing;
         }
-        buildAndAddIndex(index);
+        PrefixIndex index = new PrefixIndex(this, prefix);
+        buildIndex(index);
+        indexes.put(index.getIndexNodeName(), index);
+        prefixIndexes.put(index.getPrefix(), index);
+        queryIndexList = null;
         return index;
     }
 
@@ -230,16 +274,9 @@ public class Indexer implements QueryInd
 
     void buffer(String diff) {
         if (buffer == null) {
-            buffer = new StringBuilder(diff.length());
-        }
-        buffer.append(diff);
-    }
-
-    void commit() {
-        // TODO remove this method once MicroKernelImpl supports
-        // move + add node
-        if (mk instanceof MicroKernelImpl) {
-            commitChanges();
+            buffer = new StringBuilder(diff);
+        } else {
+            buffer.append(diff);
         }
     }
 
@@ -428,7 +465,13 @@ public class Indexer implements QueryInd
     }
 
     private void addOrRemoveRecursive(NodeImpl n, boolean remove, boolean add) {
-        if (isInIndex(n.getPath())) {
+        String path = n.getPath();
+        if (isInIndex(path)) {
+            if (n.getPropertyCount() == 0) {
+                // add or remove the index itself - otherwise it's
+                // changing the root page of the index
+                addOrRemoveIndex(path, remove, add);
+            }
             // don't index the index
             return;
         }
@@ -445,8 +488,43 @@ public class Indexer implements QueryInd
         }
     }
 
+    private void addOrRemoveIndex(String path, boolean remove, boolean add) {
+        // check the depth first for speed
+        if (PathUtils.getDepth(path) == indexRootNodeDepth + 1) {
+            // actually not required, just to make sure
+            if (PathUtils.getParentPath(path).equals(indexRootNode)) {
+                String name = PathUtils.getName(path);
+                if (name.startsWith(Indexer.TYPE_PREFIX)) {
+                    String prefix = name.substring(Indexer.TYPE_PREFIX.length());
+                    if (remove) {
+                        removePrefixIndex(prefix);
+                    }
+                    if (add) {
+                        createPrefixIndex(prefix);
+                    }
+                } else if (name.startsWith(Indexer.TYPE_PROPERTY)) {
+                    String property = name.substring(Indexer.TYPE_PROPERTY.length());
+                    boolean unique = false;
+                    if (property.endsWith("," + Indexer.UNIQUE)) {
+                        unique = true;
+                        property = property.substring(0, property.length() - Indexer.UNIQUE.length()
- 1);
+                    }
+                    if (remove) {
+                        removePropertyIndex(property, unique);
+                    }
+                    if (add) {
+                        createPropertyIndex(property, unique);
+                    }
+                }
+            }
+        }
+    }
+
     private boolean isInIndex(String path) {
-        return PathUtils.isAncestor(indexRootNode, path) || indexRootNode.equals(path);
+        if (PathUtils.isAncestor(indexRootNode, path) || indexRootNode.equals(path)) {
+            return true;
+        }
+        return false;
     }
 
     private void removeProperty(String path, String lastRevision) {
@@ -487,6 +565,12 @@ public class Indexer implements QueryInd
 
     private void moveOrCopyNode(String sourcePath, boolean remove, String targetPath, String
lastRevision) {
         if (isInIndex(sourcePath)) {
+            if (remove) {
+                addOrRemoveIndex(sourcePath, true, false);
+            }
+            if (targetPath != null) {
+                addOrRemoveIndex(targetPath, false, true);
+            }
             // don't index the index
             return;
         }
@@ -511,10 +595,9 @@ public class Indexer implements QueryInd
         }
     }
 
-    private void buildAndAddIndex(Index index) {
+    private void buildIndex(Index index) {
+        // TODO index: add ability to start / stop / restart indexing; log the progress
         addRecursive(index, "/");
-        indexes.put(index.getName(), index);
-        queryIndexList = null;
     }
 
     private void addRecursive(Index index, String path) {
@@ -554,4 +637,12 @@ public class Indexer implements QueryInd
         return queryIndexList;
     }
 
+    PrefixIndex getPrefixIndex(String prefix) {
+        return prefixIndexes.get(prefix);
+    }
+
+    PropertyIndex getPropertyIndex(String property) {
+        return propertyIndexes.get(property);
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PrefixIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PrefixIndex.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PrefixIndex.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PrefixIndex.java
Fri Jun  8 09:49:56 2012
@@ -33,20 +33,24 @@ public class PrefixIndex implements Inde
     public PrefixIndex(Indexer indexer, String prefix) {
         this.indexer = indexer;
         this.prefix = prefix;
-        this.tree = new BTree(indexer, "prefix:" + prefix, false);
+        this.tree = new BTree(indexer, Indexer.TYPE_PREFIX + prefix, false);
         tree.setMinSize(10);
     }
 
     public static PrefixIndex fromNodeName(Indexer indexer, String nodeName) {
-        if (!nodeName.startsWith("prefix:")) {
+        if (!nodeName.startsWith(Indexer.TYPE_PREFIX)) {
             return null;
         }
-        String prefix = nodeName.substring("prefix:".length());
+        String prefix = nodeName.substring(Indexer.TYPE_PREFIX.length());
         return new PrefixIndex(indexer, prefix);
     }
 
+    public String getPrefix() {
+        return prefix;
+    }
+
     @Override
-    public String getName() {
+    public String getIndexNodeName() {
         return tree.getName();
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PropertyIndex.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PropertyIndex.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/mk/index/PropertyIndex.java
Fri Jun  8 09:49:56 2012
@@ -35,22 +35,22 @@ public class PropertyIndex implements In
     public PropertyIndex(Indexer indexer, String propertyName, boolean unique) {
         this.indexer = indexer;
         this.propertyName = propertyName;
-        this.tree = new BTree(indexer, (unique ? "id:" : "property:") + propertyName, unique);
+        this.tree = new BTree(indexer, Indexer.TYPE_PROPERTY + propertyName +
+                (unique ? "," + Indexer.UNIQUE : ""), unique);
         tree.setMinSize(10);
     }
 
     public static PropertyIndex fromNodeName(Indexer indexer, String nodeName) {
-        boolean unique;
-        if (nodeName.startsWith("property:")) {
-            unique = false;
-        } else if (nodeName.startsWith("id:")) {
-            unique = true;
-        } else {
+        if (!nodeName.startsWith(Indexer.TYPE_PROPERTY)) {
             return null;
         }
-        int index = nodeName.indexOf(':');
-        String propertyName = nodeName.substring(index + 1);
-        return new PropertyIndex(indexer, propertyName, unique);
+        boolean unique = false;
+        if (nodeName.endsWith(Indexer.UNIQUE)) {
+            unique = true;
+            nodeName = nodeName.substring(0, nodeName.length() - Indexer.UNIQUE.length()
- 1);
+        }
+        String property = nodeName.substring(Indexer.TYPE_PROPERTY.length());
+        return new PropertyIndex(indexer, property, unique);
     }
 
     public String getPropertyName() {
@@ -58,7 +58,7 @@ public class PropertyIndex implements In
     }
 
     @Override
-    public String getName() {
+    public String getIndexNodeName() {
         return tree.getName();
     }
 

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=1347985&r1=1347984&r2=1347985&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
Fri Jun  8 09:49:56 2012
@@ -78,7 +78,7 @@ public class PropertyContentIndex implem
 
     @Override
     public String getIndexName() {
-        return index.getName();
+        return index.getIndexNodeName();
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/IndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/IndexTest.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/IndexTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/IndexTest.java
Fri Jun  8 09:49:56 2012
@@ -251,7 +251,7 @@ public class IndexTest {
 
     static void print(MicroKernel mk, BTree tree) {
         String head = mk.getHeadRevision();
-        String t = mk.getNodes("/index", head, 100, 0, -1, null);
+        String t = mk.getNodes(Indexer.INDEX_CONFIG_ROOT, head, 100, 0, -1, null);
         log(t);
         Cursor c = tree.findFirst("0");
         StringBuilder buff = new StringBuilder();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PrefixIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PrefixIndexTest.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PrefixIndexTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PrefixIndexTest.java
Fri Jun  8 09:49:56 2012
@@ -38,7 +38,7 @@ public class PrefixIndexTest {
 
         // meta data
         String meta = mk.getNodes("/index", head, 1, 0, -1, null);
-        Assert.assertEquals("{\":childNodeCount\":1,\"prefix:d:\":{\":childNodeCount\":0}}",
meta);
+        Assert.assertEquals("{\":childNodeCount\":1,\"prefix@d:\":{\":childNodeCount\":0}}",
meta);
 
         Assert.assertEquals("", getPathList(index, "d:1", head));
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PropertyIndexTest.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PropertyIndexTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/index/PropertyIndexTest.java
Fri Jun  8 09:49:56 2012
@@ -37,7 +37,7 @@ public class PropertyIndexTest {
 
         // meta data
         String meta = mk.getNodes("/index", head, 1, 0, -1, null);
-        Assert.assertEquals("{\":childNodeCount\":1,\"id:id\":{\":childNodeCount\":0}}",
meta);
+        Assert.assertEquals("{\":childNodeCount\":1,\"property@id,unique\":{\":childNodeCount\":0}}",
meta);
 
         String oldHead = head;
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/wrapper/IndexWrapperTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/wrapper/IndexWrapperTest.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/wrapper/IndexWrapperTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/mk/wrapper/IndexWrapperTest.java
Fri Jun  8 09:49:56 2012
@@ -42,41 +42,41 @@ public class IndexWrapperTest {
 
     @Test
     public void prefix() {
-        head = mk.commit("/jcr:system/indexes", "+ \"prefix:x\": {}", head, "");
+        head = mk.commit("/jcr:system/indexes", "+ \"prefix@x\": {}", head, "");
         head = mk.commit("/", "+ \"n1\": { \"value\":\"a:no\" }", head, "");
         head = mk.commit("/", "+ \"n2\": { \"value\":\"x:yes\" }", head, "");
         head = mk.commit("/", "+ \"n3\": { \"value\":\"x:a\" }", head, "");
         head = mk.commit("/", "+ \"n4\": { \"value\":\"x:a\" }", head, "");
-        String empty = mk.getNodes("/jcr:system/indexes/prefix:x?x:no", head, 1, 0, -1, null);
+        String empty = mk.getNodes("/jcr:system/indexes/prefix@x?x:no", head, 1, 0, -1, null);
         assertEquals("[]", empty);
-        String yes = mk.getNodes("/jcr:system/indexes/prefix:x?x:yes", head, 1, 0, -1, null);
+        String yes = mk.getNodes("/jcr:system/indexes/prefix@x?x:yes", head, 1, 0, -1, null);
         assertEquals("[\"/n2/value\"]", yes);
-        String a = mk.getNodes("/jcr:system/indexes/prefix:x?x:a", head, 1, 0, -1, null);
+        String a = mk.getNodes("/jcr:system/indexes/prefix@x?x:a", head, 1, 0, -1, null);
         assertEquals("[\"/n3/value\",\"/n4/value\"]", a);
     }
 
     @Test
     public void propertyUnique() {
-        head = mk.commit("/jcr:system/indexes", "+ \"property:id,unique\": {}", head, "");
+        head = mk.commit("/jcr:system/indexes", "+ \"property@id,unique\": {}", head, "");
         head = mk.commit("/", "+ \"n1\": { \"value\":\"empty\" }", head, "");
         head = mk.commit("/", "+ \"n2\": { \"id\":\"1\" }", head, "");
-        String empty = mk.getNodes("/jcr:system/indexes/property:id,unique?0", head, 1, 0,
-1, null);
+        String empty = mk.getNodes("/jcr:system/indexes/property@id,unique?0", head, 1, 0,
-1, null);
         assertEquals("[]", empty);
-        String one = mk.getNodes("/jcr:system/indexes/property:id,unique?1", head, 1, 0,
-1, null);
+        String one = mk.getNodes("/jcr:system/indexes/property@id,unique?1", head, 1, 0,
-1, null);
         assertEquals("[\"/n2\"]", one);
     }
 
     @Test
     public void propertyNonUnique() {
-        head = mk.commit("/jcr:system/indexes", "+ \"property:ref\": {}", head, "");
+        head = mk.commit("/jcr:system/indexes", "+ \"property@ref\": {}", head, "");
         head = mk.commit("/", "+ \"n1\": { \"ref\":\"a\" }", head, "");
         head = mk.commit("/", "+ \"n2\": { \"ref\":\"b\" }", head, "");
         head = mk.commit("/", "+ \"n3\": { \"ref\":\"b\" }", head, "");
-        String empty = mk.getNodes("/jcr:system/indexes/property:ref?no", head, 1, 0, -1,
null);
+        String empty = mk.getNodes("/jcr:system/indexes/property@ref?no", head, 1, 0, -1,
null);
         assertEquals("[]", empty);
-        String one = mk.getNodes("/jcr:system/indexes/property:ref?a", head, 1, 0, -1, null);
+        String one = mk.getNodes("/jcr:system/indexes/property@ref?a", head, 1, 0, -1, null);
         assertEquals("[\"/n1\"]", one);
-        String two = mk.getNodes("/jcr:system/indexes/property:ref?b", head, 1, 0, -1, null);
+        String two = mk.getNodes("/jcr:system/indexes/property@ref?b", head, 1, 0, -1, null);
         assertEquals("[\"/n2\",\"/n3\"]", two);
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
Fri Jun  8 09:49:56 2012
@@ -41,7 +41,7 @@ public abstract class AbstractQueryTest 
     {
         MicroKernel rawMk = new MicroKernelImpl();
         mk = new IndexWrapper(rawMk);
-        Indexer indexer = new Indexer(mk, rawMk, Indexer.INDEX_CONFIG_ROOT);
+        Indexer indexer = mk.getIndexer();
         rep = new ContentRepositoryImpl(mk, indexer, null);
         try {
             session = rep.login(new GuestCredentials(), "default");

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt?rev=1347985&r1=1347984&r2=1347985&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt
Fri Jun  8 09:49:56 2012
@@ -27,7 +27,7 @@ select * from [nt:base] as p inner join 
 java.lang.IllegalArgumentException: Two selectors with the same name: p
 
 commit / + "test": { "a": { "id": "10" }, "b": { "id" : "20" }}
-commit /jcr:system/indexes + "property:id": {}
+commit /jcr:system/indexes + "property@id,unique": {}
 
 explain select * from [nt:base] where id = '10'
 nt:base AS nt:base /* propertyIndex "id [10..10]" */
@@ -42,7 +42,7 @@ explain select * from [nt:base] where id
 nt:base AS nt:base /* traverse "//*" */
 
 commit / - "test"
-commit /jcr:system/indexes - "property:id"
+commit /jcr:system/indexes - "property@id,unique"
 
 # other tests
 



Mime
View raw message