You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by al...@apache.org on 2013/11/19 11:41:23 UTC
svn commit: r1543371 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/core/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strateg...
Author: alexparvulescu
Date: Tue Nov 19 10:41:23 2013
New Revision: 1543371
URL: http://svn.apache.org/r1543371
Log:
OAK-1137 Node.getReferences() is slow due to missing property index
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
jackrabbit/oak/trunk/oak-jcr/pom.xml
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java Tue Nov 19 10:41:23 2013
@@ -28,6 +28,7 @@ import org.apache.jackrabbit.mk.api.Micr
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -57,6 +58,8 @@ public abstract class AbstractTree imple
// TODO: make this configurable
private static final String[] INTERNAL_NODE_NAMES = {
IndexConstants.INDEX_CONTENT_NODE_NAME,
+ NodeReferenceConstants.REF_NAME,
+ NodeReferenceConstants.WEAK_REF_NAME,
MicroKernel.CONFLICT_NAME};
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java Tue Nov 19 10:41:23 2013
@@ -27,7 +27,6 @@ import java.text.ParseException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
import javax.annotation.CheckForNull;
@@ -38,7 +37,6 @@ import javax.jcr.query.Query;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
-import com.google.common.collect.Sets;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -51,6 +49,7 @@ import org.apache.jackrabbit.oak.commons
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
+import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -188,23 +187,21 @@ public class IdentifierManager {
* specified {@code tree} and matching the constraints.
*/
@Nonnull
- public Set<String> getReferences(boolean weak, Tree tree, final String propertyName, final String... nodeTypeNames) {
+ public Iterable<String> getReferences(boolean weak, Tree tree, final String propertyName, final String... nodeTypeNames) {
if (!nodeTypeManager.isNodeType(tree, JcrConstants.MIX_REFERENCEABLE)) {
return Collections.emptySet(); // shortcut
}
- try {
- final String uuid = getIdentifier(tree);
- String reference = weak ? PropertyType.TYPENAME_WEAKREFERENCE : PropertyType.TYPENAME_REFERENCE;
- String pName = propertyName == null ? "*" : propertyName; // TODO: sanitize against injection attacks!?
- Map<String, ? extends PropertyValue> bindings = Collections.singletonMap("uuid", PropertyValues.newString(uuid));
+ final String uuid = getIdentifier(tree);
+ String reference = weak ? PropertyType.TYPENAME_WEAKREFERENCE : PropertyType.TYPENAME_REFERENCE;
+ String pName = propertyName == null ? "*" : propertyName; // TODO: sanitize against injection attacks!?
+ Map<String, ? extends PropertyValue> bindings = Collections.singletonMap("uuid", PropertyValues.newString(uuid));
+ try {
Result result = root.getQueryEngine().executeQuery(
"SELECT * FROM [nt:base] WHERE PROPERTY([" + pName + "], '" + reference + "') = $uuid",
Query.JCR_SQL2, Long.MAX_VALUE, 0, bindings, new NamePathMapper.Default());
-
- Iterable<String> paths = findPaths(result, uuid, propertyName, nodeTypeNames);
- return Sets.newHashSet(paths);
+ return findPaths(result, uuid, propertyName, nodeTypeNames);
} catch (ParseException e) {
log.error("query failed", e);
return Collections.emptySet();
@@ -242,7 +239,7 @@ public class IdentifierManager {
}
// skip references from the version storage (OAK-1196)
- if (!rowPath.startsWith("/jcr:system/jcr:versionStorage/")) {
+ if (!rowPath.startsWith(VersionConstants.VERSION_STORE_PATH)) {
Tree tree = root.getTree(rowPath);
if (nodeTypeNames.length == 0 || containsNodeType(tree, nodeTypeNames)) {
if (propertyName == null) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java Tue Nov 19 10:41:23 2013
@@ -115,10 +115,10 @@ public class ContentMirrorStoreStrategy
builder.setProperty("match", true);
}
- @Override
- public Iterable<String> query(final Filter filter, final String indexName,
- final NodeState indexMeta, final Iterable<String> values) {
- final NodeState index = indexMeta.getChildNode(INDEX_CONTENT_NODE_NAME);
+ public Iterable<String> query(final Filter filter, final String indexName,
+ final NodeState indexMeta, final String indexStorageNodeName,
+ final Iterable<String> values) {
+ final NodeState index = indexMeta.getChildNode(indexStorageNodeName);
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
@@ -142,8 +142,19 @@ public class ContentMirrorStoreStrategy
}
@Override
+ public Iterable<String> query(final Filter filter, final String indexName,
+ final NodeState indexMeta, final Iterable<String> values) {
+ return query(filter, indexName, indexMeta, INDEX_CONTENT_NODE_NAME, values);
+ }
+
+ @Override
public long count(NodeState indexMeta, Set<String> values, int max) {
- NodeState index = indexMeta.getChildNode(INDEX_CONTENT_NODE_NAME);
+ return count(indexMeta, INDEX_CONTENT_NODE_NAME, values, max);
+ }
+
+ public long count(NodeState indexMeta, final String indexStorageNodeName,
+ Set<String> values, int max) {
+ NodeState index = indexMeta.getChildNode(indexStorageNodeName);
int count = 0;
if (values == null) {
PropertyState ec = indexMeta.getProperty(ENTRY_COUNT_PROPERTY_NAME);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditor.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditor.java Tue Nov 19 10:41:23 2013
@@ -16,8 +16,10 @@
*/
package org.apache.jackrabbit.oak.plugins.index.reference;
+import static com.google.common.collect.ImmutableSet.of;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static org.apache.jackrabbit.oak.api.CommitFailedException.INTEGRITY;
import static org.apache.jackrabbit.oak.api.Type.REFERENCE;
@@ -28,8 +30,10 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.api.Type.WEAKREFERENCES;
import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
+import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.REF_NAME;
import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.WEAK_REF_NAME;
+import static org.apache.jackrabbit.oak.plugins.version.VersionConstants.SYSTEM_PATHS;
import java.util.Map;
import java.util.Map.Entry;
@@ -37,12 +41,11 @@ import java.util.Set;
import javax.annotation.Nonnull;
-import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.core.ImmutableRoot;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
-import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -54,9 +57,7 @@ import org.apache.jackrabbit.oak.spi.sta
*/
class ReferenceEditor extends DefaultEditor {
- // TODO
- // - look into using a storage strategy (trees)
- // - what happens when you move a node? who updates the backlinks?
+ private static ContentMirrorStoreStrategy STORE = new ContentMirrorStoreStrategy();
/** Parent editor, or {@code null} if this is the root editor. */
private final ReferenceEditor parent;
@@ -111,6 +112,13 @@ class ReferenceEditor extends DefaultEdi
*/
private final Set<String> discardedIds;
+ /**
+ * set of ids that were added during this commit. we need it to reconcile
+ * moves
+ *
+ */
+ private final Set<String> newIds;
+
public ReferenceEditor(NodeBuilder builder) {
this.parent = null;
this.name = null;
@@ -123,6 +131,7 @@ class ReferenceEditor extends DefaultEdi
this.rmWeakRefs = newHashMap();
this.rmIds = newHashSet();
this.discardedIds = newHashSet();
+ this.newIds = newHashSet();
}
private ReferenceEditor(ReferenceEditor parent, String name, String uuid) {
@@ -137,6 +146,7 @@ class ReferenceEditor extends DefaultEdi
this.rmWeakRefs = parent.rmWeakRefs;
this.rmIds = parent.rmIds;
this.discardedIds = parent.discardedIds;
+ this.newIds = parent.newIds;
}
/**
@@ -174,6 +184,7 @@ class ReferenceEditor extends DefaultEdi
if (parent == null) {
Set<String> offending = newHashSet(rmIds);
offending.removeAll(rmRefs.keySet());
+ offending.removeAll(newIds);
if (!offending.isEmpty()) {
throw new CommitFailedException(INTEGRITY, 1,
"Unable to delete referenced node");
@@ -198,7 +209,7 @@ class ReferenceEditor extends DefaultEdi
if (newRefs.containsKey(uuid)) {
add = newRefs.remove(uuid);
}
- set(child, REF_NAME, add, rm);
+ update(child, REF_NAME, uuid, add, rm);
}
for (Entry<String, Set<String>> ref : newRefs.entrySet()) {
String uuid = ref.getKey();
@@ -213,7 +224,7 @@ class ReferenceEditor extends DefaultEdi
}
Set<String> add = ref.getValue();
Set<String> rm = newHashSet();
- set(child, REF_NAME, add, rm);
+ update(child, REF_NAME, uuid, add, rm);
}
for (Entry<String, Set<String>> ref : rmWeakRefs.entrySet()) {
String uuid = ref.getKey();
@@ -231,7 +242,7 @@ class ReferenceEditor extends DefaultEdi
if (newWeakRefs.containsKey(uuid)) {
add = newWeakRefs.remove(uuid);
}
- set(child, WEAK_REF_NAME, add, rm);
+ update(child, WEAK_REF_NAME, uuid, add, rm);
}
for (Entry<String, Set<String>> ref : newWeakRefs.entrySet()) {
String uuid = ref.getKey();
@@ -246,7 +257,7 @@ class ReferenceEditor extends DefaultEdi
}
Set<String> add = ref.getValue();
Set<String> rm = newHashSet();
- set(child, WEAK_REF_NAME, add, rm);
+ update(child, WEAK_REF_NAME, uuid, add, rm);
}
}
}
@@ -260,11 +271,13 @@ class ReferenceEditor extends DefaultEdi
public void propertyChanged(PropertyState before, PropertyState after) {
if (before != null) {
if (before.getType() == REFERENCE || before.getType() == REFERENCES) {
- put(rmRefs, before.getValue(STRINGS), concat(getPath(), before.getName()));
+ put(rmRefs, before.getValue(STRINGS),
+ concat(getPath(), before.getName()));
}
if (before.getType() == WEAKREFERENCE
|| before.getType() == WEAKREFERENCES) {
- put(rmWeakRefs, before.getValue(STRINGS), concat(getPath(), before.getName()));
+ put(rmWeakRefs, before.getValue(STRINGS),
+ concat(getPath(), before.getName()));
}
if (JCR_UUID.equals(before.getName())) {
// node remove + add -> changed uuid
@@ -276,11 +289,13 @@ class ReferenceEditor extends DefaultEdi
}
if (after != null) {
if (after.getType() == REFERENCE || after.getType() == REFERENCES) {
- put(newRefs, after.getValue(STRINGS), concat(getPath(), after.getName()));
+ put(newRefs, after.getValue(STRINGS),
+ concat(getPath(), after.getName()));
}
if (after.getType() == WEAKREFERENCE
|| after.getType() == WEAKREFERENCES) {
- put(newWeakRefs, after.getValue(STRINGS), concat(getPath(), after.getName()));
+ put(newWeakRefs, after.getValue(STRINGS),
+ concat(getPath(), after.getName()));
}
}
}
@@ -296,7 +311,11 @@ class ReferenceEditor extends DefaultEdi
if (isVersionStorePath(path)) {
return null;
}
- return new ReferenceEditor(this, name, after.getString(JCR_UUID));
+ String uuid = after.getString(JCR_UUID);
+ if (uuid != null) {
+ newIds.add(uuid);
+ }
+ return new ReferenceEditor(this, name, uuid);
}
@Override
@@ -317,10 +336,8 @@ class ReferenceEditor extends DefaultEdi
return null;
}
String uuid = before.getString(JCR_UUID);
- if (before.hasProperty(REF_NAME)) {
- if (uuid != null) {
- rmIds.add(uuid);
- }
+ if (uuid != null && check(before, REF_NAME, uuid)) {
+ rmIds.add(uuid);
}
return new ReferenceEditor(this, name, uuid);
}
@@ -354,8 +371,8 @@ class ReferenceEditor extends DefaultEdi
}
private static boolean isVersionStorePath(@Nonnull String oakPath) {
- if (oakPath.indexOf(JcrConstants.JCR_SYSTEM) == 1) {
- for (String p : VersionConstants.SYSTEM_PATHS) {
+ if (oakPath.indexOf(JCR_SYSTEM) == 1) {
+ for (String p : SYSTEM_PATHS) {
if (oakPath.startsWith(p)) {
return true;
}
@@ -366,35 +383,32 @@ class ReferenceEditor extends DefaultEdi
private static void put(Map<String, Set<String>> map,
Iterable<String> keys, String value) {
+ String asRelative = isAbsolute(value) ? value.substring(1) : value;
for (String key : keys) {
Set<String> values = map.get(key);
if (values == null) {
values = newHashSet();
}
- values.add(value);
+ values.add(asRelative);
map.put(key, values);
}
}
- private static void set(NodeBuilder child, String name, Set<String> add,
- Set<String> rm) {
- // TODO should we optimize for the remove/add case? intersect the
- // sets, work on the diffs?
-
- Set<String> vals;
- PropertyState ref = child.getProperty(name);
- if (ref != null) {
- vals = newHashSet(ref.getValue(STRINGS));
- } else {
- vals = newHashSet();
- }
- vals.addAll(add);
- vals.removeAll(rm);
- if (!vals.isEmpty()) {
- child.setProperty(name, vals, STRINGS);
- } else {
- child.removeProperty(name);
+ private static void update(NodeBuilder child, String name, String key,
+ Set<String> add, Set<String> rm) {
+ NodeBuilder index = child.child(name);
+ Set<String> empty = of();
+ for (String p : add) {
+ // TODO do we still need to encode the values?
+ STORE.update(index, p, empty, of(key));
+ }
+ for (String p : rm) {
+ STORE.update(index, p, of(key), empty);
}
}
+ private static boolean check(NodeState ns, String name, String key) {
+ return ns.hasChildNode(name) && STORE.count(ns, name, of(key), 1) > 0;
+ }
+
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java?rev=1543371&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java Tue Nov 19 10:41:23 2013
@@ -0,0 +1,151 @@
+/*
+ * 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.reference;
+
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static java.lang.Double.POSITIVE_INFINITY;
+import static javax.jcr.PropertyType.REFERENCE;
+import static javax.jcr.PropertyType.WEAKREFERENCE;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
+import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
+import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
+import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.REF_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.WEAK_REF_NAME;
+import static org.apache.jackrabbit.oak.spi.query.Cursors.newPathCursor;
+
+import java.util.ArrayList;
+
+import org.apache.jackrabbit.oak.core.ImmutableRoot;
+import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+
+/**
+ * Provides a QueryIndex that does lookups for node references based on a custom
+ * index saved on hidden property names
+ *
+ */
+class ReferenceIndex implements QueryIndex {
+
+ private static ContentMirrorStoreStrategy STORE = new ContentMirrorStoreStrategy();
+
+ @Override
+ public String getIndexName() {
+ return "reference";
+ }
+
+ @Override
+ public double getCost(Filter filter, NodeState root) {
+ // TODO don't call getCost for such queries
+ if (filter.getFullTextConstraint() != null) {
+ // not an appropriate index for full-text search
+ return POSITIVE_INFINITY;
+ }
+ for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
+ if (pr.propertyType == REFERENCE
+ || pr.propertyType == WEAKREFERENCE) {
+ return 1;
+ }
+ }
+ // not an appropriate index
+ return POSITIVE_INFINITY;
+ }
+
+ @Override
+ public Cursor query(Filter filter, NodeState root) {
+ for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
+ if (pr.propertyType == REFERENCE) {
+ String uuid = pr.first.getValue(STRING);
+ String name = pr.propertyName;
+ return lookup(root, uuid, name, REF_NAME);
+ }
+ if (pr.propertyType == WEAKREFERENCE) {
+ String uuid = pr.first.getValue(STRING);
+ String name = pr.propertyName;
+ return lookup(root, uuid, name, WEAK_REF_NAME);
+ }
+ }
+ return newPathCursor(new ArrayList<String>());
+ }
+
+ private static Cursor lookup(NodeState state, String uuid,
+ final String name, String index) {
+ String path = getIdManager(state).resolveUUID(uuid);
+ NodeState child = state;
+ for (String p : elements(path)) {
+ child = child.getChildNode(p);
+ }
+ if (!child.exists()) {
+ return newPathCursor(new ArrayList<String>());
+ }
+ Iterable<String> paths = STORE.query(new FilterImpl(), index + "("
+ + uuid + ")", child, index, null);
+
+ if (!"*".equals(name)) {
+ paths = filter(paths, new Predicate<String>() {
+ @Override
+ public boolean apply(String path) {
+ return name.equals(getName(path));
+ }
+ });
+ }
+ paths = transform(paths, new Function<String, String>() {
+ @Override
+ public String apply(String path) {
+ return getParentPath(path);
+ }
+ });
+ return newPathCursor(paths);
+ }
+
+ private static IdentifierManager getIdManager(NodeState state) {
+ return new IdentifierManager(new ImmutableRoot(state));
+ }
+
+ @Override
+ public String getPlan(Filter filter, NodeState root) {
+ StringBuilder buff = new StringBuilder("reference");
+ for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
+ if (pr.propertyType == REFERENCE) {
+ buff.append(" PROPERTY([");
+ buff.append(pr.propertyName);
+ buff.append("], 'Reference') = ");
+ buff.append(pr.first.getValue(STRING));
+ return buff.toString();
+ }
+ if (pr.propertyType == WEAKREFERENCE) {
+ buff.append(" PROPERTY([");
+ buff.append(pr.propertyName);
+ buff.append("], 'WeakReference') = ");
+ buff.append(pr.first.getValue(STRING));
+ return buff.toString();
+ }
+ }
+ return buff.toString();
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java?rev=1543371&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java Tue Nov 19 10:41:23 2013
@@ -0,0 +1,43 @@
+/*
+ * 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.reference;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A provider for node references indices.
+ */
+@Component
+@Service(QueryIndexProvider.class)
+public class ReferenceIndexProvider implements QueryIndexProvider {
+
+ @Override
+ @Nonnull
+ public List<QueryIndex> getQueryIndexes(NodeState state) {
+ return ImmutableList.<QueryIndex> of(new ReferenceIndex());
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Tue Nov 19 10:41:23 2013
@@ -101,7 +101,7 @@ class MembershipProvider extends Authori
@Nonnull
Iterator<String> getMembership(Tree authorizableTree, boolean includeInherited) {
Set<String> groupPaths = new HashSet<String>();
- Set<String> refPaths = identifierManager.getReferences(true, authorizableTree, REP_MEMBERS, NT_REP_GROUP, NT_REP_MEMBERS);
+ Iterable<String> refPaths = identifierManager.getReferences(true, authorizableTree, REP_MEMBERS, NT_REP_GROUP, NT_REP_MEMBERS);
for (String propPath : refPaths) {
int index = propPath.indexOf('/' + REP_MEMBERS);
if (index > 0) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Tue Nov 19 10:41:23 2013
@@ -44,6 +44,8 @@ import org.apache.jackrabbit.oak.api.Roo
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
@@ -78,6 +80,8 @@ public abstract class AbstractSecurityTe
public void before() throws Exception {
Oak oak = new Oak()
.with(new InitialContent())
+ .with(new ReferenceEditorProvider())
+ .with(new ReferenceIndexProvider())
.with(new PropertyIndexEditorProvider())
.with(new PropertyIndexProvider())
.with(new RegistrationEditorProvider())
Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Tue Nov 19 10:41:23 2013
@@ -50,9 +50,6 @@
org.apache.jackrabbit.test.api.WorkspaceMoveSameNameSibsTest#testMoveNodesOrderingSupportedByParent <!-- OAK-118 -->
org.apache.jackrabbit.test.api.WorkspaceMoveTest#testMoveNodesLocked <!-- OAK-118 -->
- org.apache.jackrabbit.oak.jcr.ReferencesTest#testMovedReferences <!-- OAK-1195 -->
- org.apache.jackrabbit.oak.jcr.ReferencesTest#testMovedVersionedReferences <!-- OAK-1195 -->
-
<!-- Locking : not fully implemented -->
org.apache.jackrabbit.test.api.lock.LockTest#testNodeLocked
org.apache.jackrabbit.test.api.lock.LockTest#testParentChildDeepLock
@@ -96,7 +93,6 @@
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreLabel
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreLabelJcr2
org.apache.jackrabbit.test.api.version.WorkspaceRestoreTest
- org.apache.jackrabbit.test.api.version.GetReferencesNodeTest#testGetReferencesNeverFromVersions <!-- Node.getReferences must not return references from version storage -->
org.apache.jackrabbit.test.api.version.MergeCancelMergeTest
org.apache.jackrabbit.test.api.version.MergeCheckedoutSubNodeTest
org.apache.jackrabbit.test.api.version.MergeDoneMergeTest
@@ -176,9 +172,6 @@
<!-- Node Types -->
org.apache.jackrabbit.oak.jcr.nodetype.MixinTest#testRemoveAddMixVersionable1 <!-- OAK-1118 -->
-
- org.apache.jackrabbit.test.api.SessionUUIDTest#testSaveReferentialIntegrityException <!-- OAK-685 -->
- org.apache.jackrabbit.test.api.NodeUUIDTest#testSaveReferentialIntegrityException <!-- OAK-685 -->
</known.issues>
</properties>
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java Tue Nov 19 10:41:23 2013
@@ -32,6 +32,8 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider;
import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider;
import org.apache.jackrabbit.oak.plugins.name.NamespaceValidatorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
@@ -70,6 +72,8 @@ public class Jcr {
with(new TypeEditorProvider());
with(new RegistrationEditorProvider());
with(new ConflictValidatorProvider());
+ with(new ReferenceEditorProvider());
+ with(new ReferenceIndexProvider());
with(new PropertyIndexEditorProvider());
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java?rev=1543371&r1=1543370&r2=1543371&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java Tue Nov 19 10:41:23 2013
@@ -748,7 +748,7 @@ public class NodeImpl<T extends NodeDele
public PropertyIterator perform() throws InvalidItemStateException {
IdentifierManager idManager = sessionDelegate.getIdManager();
- Set<String> propertyOakPaths = idManager.getReferences(weak, node.getTree(), name); // TODO: oak name?
+ Iterable<String> propertyOakPaths = idManager.getReferences(weak, node.getTree(), name); // TODO: oak name?
Iterable<Property> properties = Iterables.transform(
propertyOakPaths,
new Function<String, Property>() {
@@ -760,7 +760,7 @@ public class NodeImpl<T extends NodeDele
}
);
- return new PropertyIteratorAdapter(properties.iterator(), propertyOakPaths.size());
+ return new PropertyIteratorAdapter(properties.iterator());
}
});
}