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 2016/07/25 12:05:38 UTC
svn commit: r1753981 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/index/property/
main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
main/java/org/apache/jackrabbit/oak/plugins/index/reference/ ...
Author: alexparvulescu
Date: Mon Jul 25 12:05:37 2016
New Revision: 1753981
URL: http://svn.apache.org/viewvc?rev=1753981&view=rev
Log:
OAK-3403 Multiplexing store support in Property indexes
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java (with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditorProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexProvider.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/property/strategy/IndexStoreStrategy.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.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/plugins/index/reference/ReferenceEditorProvider.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java?rev=1753981&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java Mon Jul 25 12:05:37 2016
@@ -0,0 +1,154 @@
+/*
+ * 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.property;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.FilteringIndexStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.UniqueEntryStoreStrategy;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+
+import com.google.common.base.Predicate;
+
+public class Multiplexers {
+
+ static boolean RO_PRIVATE_UNIQUE_INDEX;
+
+ static {
+ String ro = System.getProperty(
+ "oak.multiplexing.readOnlyPrivateUniqueIndex", "true");
+ RO_PRIVATE_UNIQUE_INDEX = Boolean.parseBoolean(ro);
+ }
+
+ /** Index storage strategy */
+ private static final IndexStoreStrategy UNIQUE = new UniqueEntryStoreStrategy(
+ INDEX_CONTENT_NODE_NAME);
+
+ /** Index storage strategy */
+ private static final IndexStoreStrategy MIRROR = new ContentMirrorStoreStrategy(
+ INDEX_CONTENT_NODE_NAME);
+
+ public static Set<IndexStoreStrategy> getStrategies(boolean unique,
+ MountInfoProvider mountInfoProvider, NodeBuilder definition,
+ String defaultName) {
+ Iterable<String> children = definition.getChildNodeNames();
+ return getStrategies(unique, mountInfoProvider, children, defaultName);
+ }
+
+ public static Set<IndexStoreStrategy> getStrategies(boolean unique,
+ MountInfoProvider mountInfoProvider, NodeState definition,
+ String defaultName) {
+ Iterable<String> children = definition.getChildNodeNames();
+ return getStrategies(unique, mountInfoProvider, children, defaultName);
+ }
+
+ private static Set<IndexStoreStrategy> getStrategies(boolean unique,
+ MountInfoProvider mountInfoProvider, Iterable<String> children,
+ String defaultName) {
+ if (mountInfoProvider.hasNonDefaultMounts()) {
+ Set<String> names = new HashSet<String>();
+ // TODO should this be collected from the index def?
+ for (String name : children) {
+ if (isIndexStorageNode(name, defaultName)) {
+ names.add(name);
+ }
+ }
+ names.remove(defaultName);
+ Set<IndexStoreStrategy> strategies = new HashSet<IndexStoreStrategy>();
+ for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
+ String n = getNodeForMount(m, defaultName);
+ names.remove(n);
+ strategies.add(newStrategy(unique, false, n, m));
+ }
+
+ Mount defMount = mountInfoProvider.getDefaultMount();
+ // TODO what to do with non-default names that are not covered by
+ // the mount?
+ for (String n : names) {
+ strategies.add(newStrategy(unique, true, n, defMount));
+ }
+ // default mount
+ strategies.add(newStrategy(unique, true, defaultName, defMount));
+ return strategies;
+ } else {
+ return unique ? newHashSet(UNIQUE) : newHashSet(MIRROR);
+ }
+ }
+
+ private static IndexStoreStrategy newStrategy(boolean unique,
+ boolean defaultMount, String name, Mount m) {
+ Predicate<String> filter = newFilter(m);
+ boolean readOnly = unique && !m.isDefault() && RO_PRIVATE_UNIQUE_INDEX;
+ return unique ? new FilteringIndexStoreStrategy(
+ new UniqueEntryStoreStrategy(name), filter, readOnly)
+ : new FilteringIndexStoreStrategy(
+ new ContentMirrorStoreStrategy(name), filter);
+ }
+
+ private static Predicate<String> newFilter(final Mount m) {
+ return new Predicate<String>() {
+
+ @Override
+ public boolean apply(String p) {
+ return m.isMounted(p);
+ }
+ };
+ }
+
+ private static boolean isIndexStorageNode(String name, String defaultName) {
+ return NodeStateUtils.isHidden(name)
+ && (name.equals(defaultName) || name
+ .endsWith(asSuffix(defaultName)));
+ }
+
+ public static String getIndexNodeName(MountInfoProvider mountInfoProvider,
+ String path, String defaultName) {
+ Mount mount = mountInfoProvider.getMountByPath(path);
+ return getNodeForMount(mount, defaultName);
+ }
+
+ public static String getNodeForMount(Mount mount, String defaultName) {
+ if (mount.isDefault()) {
+ return defaultName;
+ }
+ return ":" + mount.getPathFragmentName() + asSuffix(defaultName);
+ }
+
+ private static String asSuffix(String name) {
+ return "-" + stripStartingColon(name);
+ }
+
+ private static String stripStartingColon(String name) {
+ if (name.startsWith(":")) {
+ return name.substring(1);
+ }
+ return name;
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/Multiplexers.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java Mon Jul 25 12:05:37 2016
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
@@ -98,11 +99,17 @@ class PropertyIndex implements QueryInde
private static final Logger LOG = LoggerFactory.getLogger(PropertyIndex.class);
+ private final MountInfoProvider mountInfoProvider;
+
/**
* Cached property index plan
*/
private PropertyIndexPlan plan;
+ PropertyIndex(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ }
+
static Set<String> encode(PropertyValue value) {
if (value == null) {
return null;
@@ -135,13 +142,14 @@ class PropertyIndex implements QueryInde
if (plan != null && plan.getFilter().toString().equals(filter.toString())) {
return plan;
} else {
- plan = createPlan(root, filter);
+ plan = createPlan(root, filter, mountInfoProvider);
this.plan = plan;
return plan;
}
}
- private static PropertyIndexPlan createPlan(NodeState root, Filter filter) {
+ private static PropertyIndexPlan createPlan(NodeState root, Filter filter,
+ MountInfoProvider mountInfoProvider) {
PropertyIndexPlan bestPlan = null;
// TODO support indexes on a path
@@ -152,7 +160,7 @@ class PropertyIndex implements QueryInde
if (PROPERTY.equals(definition.getString(TYPE_PROPERTY_NAME))
&& definition.hasChildNode(INDEX_CONTENT_NODE_NAME)) {
PropertyIndexPlan plan = new PropertyIndexPlan(
- entry.getName(), root, definition, filter);
+ entry.getName(), root, definition, filter, mountInfoProvider);
if (plan.getCost() != Double.POSITIVE_INFINITY) {
LOG.debug("property cost for {} is {}",
plan.getName(), plan.getCost());
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditor.java Mon Jul 25 12:05:37 2016
@@ -41,11 +41,10 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.index.IndexEditor;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
import org.apache.jackrabbit.oak.plugins.index.PathFilter;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.UniqueEntryStoreStrategy;
import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
import org.apache.jackrabbit.oak.spi.commit.Editor;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -60,14 +59,6 @@ import com.google.common.base.Predicate;
*/
class PropertyIndexEditor implements IndexEditor {
- /** Index storage strategy */
- private static final IndexStoreStrategy MIRROR =
- new ContentMirrorStoreStrategy();
-
- /** Index storage strategy */
- private static final IndexStoreStrategy UNIQUE =
- new UniqueEntryStoreStrategy();
-
/** Parent editor, or {@code null} if this is the root editor. */
private final PropertyIndexEditor parent;
@@ -115,8 +106,10 @@ class PropertyIndexEditor implements Ind
private final PathFilter.Result pathFilterResult;
+ private final MountInfoProvider mountInfoProvider;
+
public PropertyIndexEditor(NodeBuilder definition, NodeState root,
- IndexUpdateCallback updateCallback) {
+ IndexUpdateCallback updateCallback, MountInfoProvider mountInfoProvider) {
this.parent = null;
this.name = null;
this.path = "/";
@@ -152,6 +145,7 @@ class PropertyIndexEditor implements Ind
this.keysToCheckForUniqueness = null;
}
this.updateCallback = updateCallback;
+ this.mountInfoProvider = mountInfoProvider;
}
PropertyIndexEditor(PropertyIndexEditor parent, String name, PathFilter.Result pathFilterResult) {
@@ -166,6 +160,7 @@ class PropertyIndexEditor implements Ind
this.updateCallback = parent.updateCallback;
this.pathFilter = parent.pathFilter;
this.pathFilterResult = pathFilterResult;
+ this.mountInfoProvider = parent.mountInfoProvider;
}
/**
@@ -221,8 +216,9 @@ class PropertyIndexEditor implements Ind
return keys;
}
- IndexStoreStrategy getStrategy(boolean unique) {
- return unique ? UNIQUE : MIRROR;
+ Set<IndexStoreStrategy> getStrategies(boolean unique) {
+ return Multiplexers.getStrategies(unique, mountInfoProvider,
+ definition, INDEX_CONTENT_NODE_NAME);
}
@Override
@@ -285,15 +281,18 @@ class PropertyIndexEditor implements Ind
if (!beforeKeys.isEmpty() || !afterKeys.isEmpty()) {
updateCallback.indexUpdate();
- NodeBuilder index = definition.child(INDEX_CONTENT_NODE_NAME);
String properties = definition.getString(PROPERTY_NAMES);
boolean uniqueIndex = keysToCheckForUniqueness != null;
- if (uniqueIndex) {
- keysToCheckForUniqueness.addAll(
- getExistingKeys(afterKeys, index));
+ for (IndexStoreStrategy strategy : getStrategies(uniqueIndex)) {
+ NodeBuilder index = definition.child(strategy
+ .getIndexNodeName());
+ if (uniqueIndex) {
+ keysToCheckForUniqueness.addAll(getExistingKeys(
+ afterKeys, index, strategy));
+ }
+ strategy.update(index, getPath(), properties, definition,
+ beforeKeys, afterKeys);
}
- getStrategy(uniqueIndex).update(
- index, getPath(), properties, definition, beforeKeys, afterKeys);
}
}
@@ -328,11 +327,11 @@ class PropertyIndexEditor implements Ind
*
* @param keys the keys
* @param index the index
+ * @param s the index store strategy
* @return the set of keys that already exist in this unique index
*/
- private Set<String> getExistingKeys(Set<String> keys, NodeBuilder index) {
+ private Set<String> getExistingKeys(Set<String> keys, NodeBuilder index, IndexStoreStrategy s) {
Set<String> existing = null;
- IndexStoreStrategy s = getStrategy(true);
for (String key : keys) {
if (s.exists(index, key)) {
if (existing == null) {
@@ -346,7 +345,7 @@ class PropertyIndexEditor implements Ind
}
return existing;
}
-
+
/**
* From a set of keys, get the first that has multiple entries, if any.
*
@@ -355,10 +354,13 @@ class PropertyIndexEditor implements Ind
* @return the first duplicate, or null if none was found
*/
private String getFirstDuplicate(Set<String> keys, NodeState indexMeta) {
- IndexStoreStrategy s = getStrategy(true);
for (String key : keys) {
- if (s.count(root, indexMeta, singleton(key), 2) > 1) {
- return key;
+ long count = 0;
+ for (IndexStoreStrategy s : getStrategies(true)) {
+ count += s.count(root, indexMeta, singleton(key), 2);
+ if (count > 1) {
+ return key;
+ }
}
}
return null;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditorProvider.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexEditorProvider.java Mon Jul 25 12:05:37 2016
@@ -20,11 +20,14 @@ import javax.annotation.Nonnull;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -42,13 +45,20 @@ public class PropertyIndexEditorProvider
public static final String TYPE = "property";
+ @Reference
+ private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
+
@Override
public Editor getIndexEditor(
@Nonnull String type, @Nonnull NodeBuilder definition, @Nonnull NodeState root, @Nonnull IndexUpdateCallback callback) {
if (TYPE.equals(type)) {
- return new PropertyIndexEditor(definition, root, callback);
+ return new PropertyIndexEditor(definition, root, callback, mountInfoProvider);
}
return null;
}
+ public PropertyIndexEditorProvider with(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ return this;
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexLookup.java Mon Jul 25 12:05:37 2016
@@ -25,6 +25,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider.TYPE;
import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.encode;
+import java.util.List;
import java.util.Set;
import javax.annotation.CheckForNull;
@@ -35,13 +36,16 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.UniqueEntryStoreStrategy;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
/**
* Is responsible for querying the property index content.
* <br>
@@ -68,18 +72,17 @@ public class PropertyIndexLookup {
*/
static final int MAX_COST = 100;
- /** Index storage strategy */
- private static final IndexStoreStrategy MIRROR =
- new ContentMirrorStoreStrategy();
-
- /** Index storage strategy */
- private static final IndexStoreStrategy UNIQUE =
- new UniqueEntryStoreStrategy();
-
private final NodeState root;
+ private final MountInfoProvider mountInfoProvider;
+
public PropertyIndexLookup(NodeState root) {
+ this(root, Mounts.defaultMountInfoProvider());
+ }
+
+ public PropertyIndexLookup(NodeState root, MountInfoProvider mountInfoProvider) {
this.root = root;
+ this.mountInfoProvider = mountInfoProvider;
}
/**
@@ -107,19 +110,25 @@ public class PropertyIndexLookup {
return false;
}
- public Iterable<String> query(Filter filter, String propertyName, PropertyValue value) {
+ public Iterable<String> query(Filter filter, String propertyName,
+ PropertyValue value) {
NodeState indexMeta = getIndexNode(root, propertyName, filter);
if (indexMeta == null) {
throw new IllegalArgumentException("No index for " + propertyName);
}
- return getStrategy(indexMeta).query(filter, propertyName, indexMeta, encode(value));
+ List<Iterable<String>> iterables = Lists.newArrayList();
+ for (IndexStoreStrategy s : getStrategies(indexMeta)) {
+ iterables.add(s.query(filter, propertyName, indexMeta,
+ encode(value)));
+ }
+ return Iterables.concat(iterables);
}
- IndexStoreStrategy getStrategy(NodeState indexMeta) {
- if (indexMeta.getBoolean(IndexConstants.UNIQUE_PROPERTY_NAME)) {
- return UNIQUE;
- }
- return MIRROR;
+ Set<IndexStoreStrategy> getStrategies(NodeState definition) {
+ boolean unique = definition
+ .getBoolean(IndexConstants.UNIQUE_PROPERTY_NAME);
+ return Multiplexers.getStrategies(unique, mountInfoProvider,
+ definition, INDEX_CONTENT_NODE_NAME);
}
public double getCost(Filter filter, String propertyName, PropertyValue value) {
@@ -127,8 +136,12 @@ public class PropertyIndexLookup {
if (indexMeta == null) {
return Double.POSITIVE_INFINITY;
}
- return COST_OVERHEAD +
- getStrategy(indexMeta).count(filter, root, indexMeta, encode(value), MAX_COST);
+ Set<IndexStoreStrategy> strategies = getStrategies(indexMeta);
+ double cost = strategies.isEmpty() ? MAX_COST : COST_OVERHEAD;
+ for (IndexStoreStrategy s : strategies) {
+ cost += s.count(filter, root, indexMeta, encode(value), MAX_COST);
+ }
+ return cost;
}
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java Mon Jul 25 12:05:37 2016
@@ -22,25 +22,30 @@ import static com.google.common.collect.
import static com.google.common.collect.Sets.newLinkedHashSet;
import static java.util.Collections.emptySet;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
-import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.UNIQUE_PROPERTY_NAME;
import static org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.encode;
+import java.util.List;
import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.PathFilter;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.UniqueEntryStoreStrategy;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.spi.query.Cursors;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
/**
* Plan for querying a given property index using a given filter.
*/
@@ -56,21 +61,13 @@ public class PropertyIndexPlan {
*/
static final int MAX_COST = 100;
- /** Index storage strategy */
- private static final IndexStoreStrategy MIRROR =
- new ContentMirrorStoreStrategy();
-
- /** Index storage strategy */
- private static final IndexStoreStrategy UNIQUE =
- new UniqueEntryStoreStrategy();
-
private final NodeState definition;
private final String name;
private final Set<String> properties;
- private final IndexStoreStrategy strategy;
+ private final Set<IndexStoreStrategy> strategies;
private final Filter filter;
@@ -86,18 +83,18 @@ public class PropertyIndexPlan {
private final PathFilter pathFilter;
- PropertyIndexPlan(String name, NodeState root, NodeState definition, Filter filter) {
+ PropertyIndexPlan(String name, NodeState root, NodeState definition,
+ Filter filter){
+ this(name, root, definition, filter, Mounts.defaultMountInfoProvider());
+ }
+
+ PropertyIndexPlan(String name, NodeState root, NodeState definition,
+ Filter filter, MountInfoProvider mountInfoProvider) {
this.name = name;
this.definition = definition;
this.properties = newHashSet(definition.getNames(PROPERTY_NAMES));
pathFilter = PathFilter.from(definition.builder());
-
- if (definition.getBoolean(UNIQUE_PROPERTY_NAME)) {
- this.strategy = UNIQUE;
- } else {
- this.strategy = MIRROR;
- }
-
+ this.strategies = getStrategies(definition, mountInfoProvider);
this.filter = filter;
Iterable<String> types = definition.getNames(DECLARING_NODE_TYPES);
@@ -143,7 +140,11 @@ public class PropertyIndexPlan {
continue;
}
Set<String> values = getValues(restriction);
- double cost = strategy.count(filter, root, definition, values, MAX_COST);
+ double cost = strategies.isEmpty() ? MAX_COST : 0;
+ for (IndexStoreStrategy strategy : strategies) {
+ cost += strategy.count(filter, root, definition,
+ values, MAX_COST);
+ }
if (cost < bestCost) {
bestDepth = depth;
bestValues = values;
@@ -188,8 +189,11 @@ public class PropertyIndexPlan {
Cursor execute() {
QueryEngineSettings settings = filter.getQueryEngineSettings();
- Cursor cursor = Cursors.newPathCursor(
- strategy.query(filter, name, definition, values),
+ List<Iterable<String>> iterables = Lists.newArrayList();
+ for (IndexStoreStrategy s : strategies) {
+ iterables.add(s.query(filter, name, definition, values));
+ }
+ Cursor cursor = Cursors.newPathCursor(Iterables.concat(iterables),
settings);
if (depth > 1) {
cursor = Cursors.newAncestorCursor(cursor, depth - 1, settings);
@@ -201,6 +205,14 @@ public class PropertyIndexPlan {
return filter;
}
+ Set<IndexStoreStrategy> getStrategies(NodeState definition,
+ MountInfoProvider mountInfoProvider) {
+ boolean unique = definition
+ .getBoolean(IndexConstants.UNIQUE_PROPERTY_NAME);
+ return Multiplexers.getStrategies(unique, mountInfoProvider,
+ definition, INDEX_CONTENT_NODE_NAME);
+ }
+
//------------------------------------------------------------< Object >--
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexProvider.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexProvider.java Mon Jul 25 12:05:37 2016
@@ -21,7 +21,10 @@ import java.util.List;
import javax.annotation.Nonnull;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -40,8 +43,16 @@ import com.google.common.collect.Immutab
@Service(QueryIndexProvider.class)
public class PropertyIndexProvider implements QueryIndexProvider {
+ @Reference
+ private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
+
@Override @Nonnull
public List<QueryIndex> getQueryIndexes(NodeState state) {
- return ImmutableList.<QueryIndex>of(new PropertyIndex());
+ return ImmutableList.<QueryIndex>of(new PropertyIndex(mountInfoProvider));
+ }
+
+ public PropertyIndexProvider with(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ return this;
}
}
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=1753981&r1=1753980&r2=1753981&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 Mon Jul 25 12:05:37 2016
@@ -80,6 +80,16 @@ public class ContentMirrorStoreStrategy
*/
public static final int TRAVERSING_WARN = Integer.getInteger("oak.traversing.warn", 10000);
+ private final String indexName;
+
+ public ContentMirrorStoreStrategy() {
+ this(INDEX_CONTENT_NODE_NAME);
+ }
+
+ public ContentMirrorStoreStrategy(String indexName) {
+ this.indexName = indexName;
+ }
+
@Override
public void update(
NodeBuilder index, String path,
@@ -163,27 +173,22 @@ public class ContentMirrorStoreStrategy
}
@Override
- public Iterable<String> query(final Filter filter, final String indexName,
+ public Iterable<String> query(final Filter filter, final String name,
final NodeState indexMeta, final Iterable<String> values) {
- return query(filter, indexName, indexMeta, INDEX_CONTENT_NODE_NAME, values);
+ return query(filter, name, indexMeta, this.indexName, values);
}
@Override
public long count(NodeState root, NodeState indexMeta, Set<String> values, int max) {
- return count(root, indexMeta, INDEX_CONTENT_NODE_NAME, values, max);
+ return count(null, root, indexMeta, this.indexName, values, max);
}
@Override
public long count(final Filter filter, NodeState root, NodeState indexMeta, Set<String> values, int max) {
- return count(filter, root, indexMeta, INDEX_CONTENT_NODE_NAME, values, max);
+ return count(filter, root, indexMeta, this.indexName, values, max);
}
- public long count(NodeState root, NodeState indexMeta, final String indexStorageNodeName,
- Set<String> values, int max) {
- return count(null, root, indexMeta, indexStorageNodeName, values, max);
- }
-
- public long count(Filter filter, NodeState root, NodeState indexMeta, final String indexStorageNodeName,
+ long count(Filter filter, NodeState root, NodeState indexMeta, final String indexStorageNodeName,
Set<String> values, int max) {
NodeState index = indexMeta.getChildNode(indexStorageNodeName);
long count = -1;
@@ -586,4 +591,8 @@ public class ContentMirrorStoreStrategy
throw new UnsupportedOperationException();
}
+ @Override
+ public String getIndexNodeName() {
+ return indexName;
+ }
}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java?rev=1753981&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java Mon Jul 25 12:05:37 2016
@@ -0,0 +1,96 @@
+/*
+ * 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.property.strategy;
+
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.base.Predicate;
+
+/**
+ * A delegating IndexStoreStrategy that filters out updates that are not
+ * accepted by the given predicate
+ */
+public class FilteringIndexStoreStrategy implements IndexStoreStrategy {
+
+ private final IndexStoreStrategy strategy;
+ private final Predicate<String> filter;
+ private final boolean readOnly;
+
+ public FilteringIndexStoreStrategy(IndexStoreStrategy strategy,
+ Predicate<String> filter) {
+ this(strategy, filter, false);
+ }
+
+ public FilteringIndexStoreStrategy(IndexStoreStrategy strategy,
+ Predicate<String> filter, boolean readOnly) {
+ this.strategy = strategy;
+ this.filter = filter;
+ this.readOnly = readOnly;
+ }
+
+ @Override
+ public void update(NodeBuilder index, String path, String indexName,
+ NodeBuilder indexMeta, Set<String> beforeKeys, Set<String> afterKeys)
+ throws CommitFailedException {
+ if (filter.apply(path)) {
+ if (readOnly) {
+ throw new CommitFailedException(
+ CommitFailedException.UNSUPPORTED, 0,
+ "Unsupported commit to a read-only store!",
+ new Throwable("Commit path: " + path));
+ }
+ strategy.update(index, path, indexName, indexMeta, beforeKeys,
+ afterKeys);
+ }
+ }
+
+ @Override
+ public boolean exists(NodeBuilder index, String key) {
+ return strategy.exists(index, key);
+ }
+
+ @Override
+ public Iterable<String> query(Filter filter, String indexName,
+ NodeState indexMeta, Iterable<String> values) {
+ return strategy.query(filter, indexName, indexMeta, values);
+ }
+
+ @Override
+ public long count(NodeState root, NodeState indexMeta, Set<String> values,
+ int max) {
+ return strategy.count(root, indexMeta, values, max);
+ }
+
+ @Override
+ public long count(Filter filter, NodeState root, NodeState indexMeta,
+ Set<String> values, int max) {
+ return strategy.count(filter, root, indexMeta, values, max);
+ }
+
+ @Override
+ public String getIndexNodeName() {
+ return strategy.getIndexNodeName();
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/FilteringIndexStoreStrategy.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/IndexStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/IndexStoreStrategy.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/IndexStoreStrategy.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/IndexStoreStrategy.java Mon Jul 25 12:05:37 2016
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.plugin
import java.util.Set;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -41,7 +42,7 @@ public interface IndexStoreStrategy {
void update(
NodeBuilder index, String path,
String indexName, NodeBuilder indexMeta,
- Set<String> beforeKeys, Set<String> afterKeys);
+ Set<String> beforeKeys, Set<String> afterKeys) throws CommitFailedException;
/**
* Check whether an entry for the given key exists.
@@ -88,4 +89,6 @@ public interface IndexStoreStrategy {
*/
long count(Filter filter, NodeState root, NodeState indexMeta, Set<String> values, int max);
+ String getIndexNodeName();
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/UniqueEntryStoreStrategy.java Mon Jul 25 12:05:37 2016
@@ -47,6 +47,16 @@ public class UniqueEntryStoreStrategy im
static final Logger LOG = LoggerFactory.getLogger(UniqueEntryStoreStrategy.class);
+ private final String indexName;
+
+ public UniqueEntryStoreStrategy() {
+ this(INDEX_CONTENT_NODE_NAME);
+ }
+
+ public UniqueEntryStoreStrategy(String indexName) {
+ this.indexName = indexName;
+ }
+
@Override
public void update(
NodeBuilder index, String path,
@@ -108,7 +118,7 @@ public class UniqueEntryStoreStrategy im
@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);
+ final NodeState index = indexMeta.getChildNode(getIndexNodeName());
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
@@ -157,7 +167,7 @@ public class UniqueEntryStoreStrategy im
@Override
public long count(NodeState root, NodeState indexMeta, Set<String> values, int max) {
- NodeState index = indexMeta.getChildNode(INDEX_CONTENT_NODE_NAME);
+ NodeState index = indexMeta.getChildNode(getIndexNodeName());
long count = 0;
if (values == null) {
PropertyState ec = indexMeta.getProperty(ENTRY_COUNT_PROPERTY_NAME);
@@ -193,5 +203,9 @@ public class UniqueEntryStoreStrategy im
public long count(final Filter filter, NodeState root, NodeState indexMeta, Set<String> values, int max) {
return count(root, indexMeta, values, max);
}
-
+
+ @Override
+ public String getIndexNodeName() {
+ return indexName;
+ }
}
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=1753981&r1=1753980&r2=1753981&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 Mon Jul 25 12:05:37 2016
@@ -42,9 +42,11 @@ import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.plugins.index.IndexEditor;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.index.property.Multiplexers;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
import org.apache.jackrabbit.oak.spi.commit.Editor;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -54,8 +56,6 @@ import org.apache.jackrabbit.oak.spi.sta
*/
class ReferenceEditor extends DefaultEditor implements IndexEditor {
- private static final ContentMirrorStoreStrategy STORE = new ContentMirrorStoreStrategy();
-
/** Parent editor, or {@code null} if this is the root editor. */
private final ReferenceEditor parent;
@@ -101,13 +101,15 @@ class ReferenceEditor extends DefaultEdi
*/
private final Set<String> newIds;
+ private final MountInfoProvider mountInfoProvider;
+
/**
* flag marking a reindex, case in which we don't need to keep track of the
* newIds set
*/
private boolean isReindex;
- public ReferenceEditor(NodeBuilder definition, NodeState root) {
+ public ReferenceEditor(NodeBuilder definition, NodeState root,MountInfoProvider mountInfoProvider) {
this.parent = null;
this.name = null;
this.path = "/";
@@ -119,6 +121,7 @@ class ReferenceEditor extends DefaultEdi
this.rmWeakRefs = newHashMap();
this.rmIds = newHashSet();
this.newIds = newHashSet();
+ this.mountInfoProvider = mountInfoProvider;
}
private ReferenceEditor(ReferenceEditor parent, String name) {
@@ -134,6 +137,7 @@ class ReferenceEditor extends DefaultEdi
this.rmIds = parent.rmIds;
this.newIds = parent.newIds;
this.isReindex = parent.isReindex;
+ this.mountInfoProvider = parent.mountInfoProvider;
}
/**
@@ -158,6 +162,8 @@ class ReferenceEditor extends DefaultEdi
public void leave(NodeState before, NodeState after)
throws CommitFailedException {
if (parent == null) {
+ Set<IndexStoreStrategy> refStores = getStrategies(false, REF_NAME);
+ Set<IndexStoreStrategy> weakRefStores = getStrategies(false, WEAK_REF_NAME);
// update references
for (Entry<String, Set<String>> ref : rmRefs.entrySet()) {
String uuid = ref.getKey();
@@ -166,7 +172,7 @@ class ReferenceEditor extends DefaultEdi
if (newRefs.containsKey(uuid)) {
add = newRefs.remove(uuid);
}
- update(definition, REF_NAME, uuid, add, rm);
+ update(refStores, definition, REF_NAME, uuid, add, rm);
}
for (Entry<String, Set<String>> ref : newRefs.entrySet()) {
String uuid = ref.getKey();
@@ -175,10 +181,10 @@ class ReferenceEditor extends DefaultEdi
}
Set<String> add = ref.getValue();
Set<String> rm = emptySet();
- update(definition, REF_NAME, uuid, add, rm);
+ update(refStores, definition, REF_NAME, uuid, add, rm);
}
- checkReferentialIntegrity(root, definition.getNodeState(),
+ checkReferentialIntegrity(refStores, root, definition.getNodeState(),
Sets.difference(rmIds, newIds));
// update weak references
@@ -189,17 +195,22 @@ class ReferenceEditor extends DefaultEdi
if (newWeakRefs.containsKey(uuid)) {
add = newWeakRefs.remove(uuid);
}
- update(definition, WEAK_REF_NAME, uuid, add, rm);
+ update(weakRefStores, definition, WEAK_REF_NAME, uuid, add, rm);
}
for (Entry<String, Set<String>> ref : newWeakRefs.entrySet()) {
String uuid = ref.getKey();
Set<String> add = ref.getValue();
Set<String> rm = emptySet();
- update(definition, WEAK_REF_NAME, uuid, add, rm);
+ update(weakRefStores, definition, WEAK_REF_NAME, uuid, add, rm);
}
}
}
+ Set<IndexStoreStrategy> getStrategies(boolean unique, String index) {
+ return Multiplexers.getStrategies(unique, mountInfoProvider,
+ definition, index);
+ }
+
@Override
public void propertyAdded(PropertyState after) {
propertyChanged(null, after);
@@ -292,35 +303,43 @@ class ReferenceEditor extends DefaultEdi
}
}
- 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 : rm) {
- STORE.update(index, p, name, child, of(key), empty);
- }
- for (String p : add) {
- // TODO do we still need to encode the values?
- STORE.update(index, p, name, child, empty, of(key));
+ private void update(Set<IndexStoreStrategy> refStores,
+ NodeBuilder definition, String name, String key, Set<String> add,
+ Set<String> rm) throws CommitFailedException {
+ for (IndexStoreStrategy store : refStores) {
+ Set<String> empty = of();
+ for (String p : rm) {
+ NodeBuilder index = definition.child(store.getIndexNodeName());
+ store.update(index, p, name, definition, of(key), empty);
+ }
+ for (String p : add) {
+ // TODO do we still need to encode the values?
+ NodeBuilder index = definition.child(store.getIndexNodeName());
+ store.update(index, p, name, definition, empty, of(key));
+ }
}
}
- private static boolean hasReferences(NodeState root,
- NodeState definition,
- String name,
- String key) {
+ private static boolean hasReferences(IndexStoreStrategy refStore,
+ NodeState root,
+ NodeState definition,
+ String name,
+ String key) {
return definition.hasChildNode(name)
- && STORE.count(root, definition, name, of(key), 1) > 0;
+ && refStore.count(root, definition, of(key), 1) > 0;
}
- private static void checkReferentialIntegrity(NodeState root,
- NodeState definition,
- Set<String> idsOfRemovedNodes)
+ private static void checkReferentialIntegrity(Set<IndexStoreStrategy> refStores,
+ NodeState root,
+ NodeState definition,
+ Set<String> idsOfRemovedNodes)
throws CommitFailedException {
- for (String id : idsOfRemovedNodes) {
- if (hasReferences(root, definition, REF_NAME, id)) {
- throw new CommitFailedException(INTEGRITY, 1,
- "Unable to delete referenced node");
+ for (IndexStoreStrategy store : refStores) {
+ for (String id : idsOfRemovedNodes) {
+ if (hasReferences(store, root, definition, REF_NAME, id)) {
+ throw new CommitFailedException(INTEGRITY, 1,
+ "Unable to delete referenced node");
+ }
}
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditorProvider.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceEditorProvider.java Mon Jul 25 12:05:37 2016
@@ -16,17 +16,20 @@
*/
package org.apache.jackrabbit.oak.plugins.index.reference;
-import javax.annotation.Nonnull;
-
import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.TYPE;
+import javax.annotation.Nonnull;
+
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
import org.apache.jackrabbit.oak.spi.commit.Editor;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -35,13 +38,21 @@ import org.apache.jackrabbit.oak.spi.sta
@Property(name = IndexConstants.TYPE_PROPERTY_NAME , value = NodeReferenceConstants.TYPE, propertyPrivate = true)
public class ReferenceEditorProvider implements IndexEditorProvider {
+ @Reference
+ private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
+
@Override
public Editor getIndexEditor(@Nonnull String type, @Nonnull NodeBuilder definition,
@Nonnull NodeState root, @Nonnull IndexUpdateCallback callback) {
if (TYPE.equals(type)) {
- return new ReferenceEditor(definition, root);
+ return new ReferenceEditor(definition, root, mountInfoProvider);
}
return null;
}
+ public ReferenceEditorProvider with(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ return this;
+ }
+
}
Modified: 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=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndex.java Mon Jul 25 12:05:37 2016
@@ -31,9 +31,14 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.spi.query.Cursors.newPathCursor;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
-import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
+import org.apache.jackrabbit.oak.plugins.index.property.Multiplexers;
+import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
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;
@@ -43,6 +48,8 @@ import org.apache.jackrabbit.oak.spi.sta
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
/**
* Provides a QueryIndex that does lookups for node references based on a custom
@@ -51,10 +58,18 @@ import com.google.common.collect.Immutab
*/
class ReferenceIndex implements QueryIndex {
- private static final ContentMirrorStoreStrategy STORE = new ContentMirrorStoreStrategy();
-
private static final double COST = 1;
+ private final MountInfoProvider mountInfoProvider;
+
+ ReferenceIndex() {
+ this(Mounts.defaultMountInfoProvider());
+ }
+
+ ReferenceIndex(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ }
+
@Override
public double getMinimumCost() {
return COST;
@@ -110,15 +125,19 @@ class ReferenceIndex implements QueryInd
return newPathCursor(new ArrayList<String>(), filter.getQueryEngineSettings());
}
- private static Cursor lookup(NodeState root, String uuid,
+ private Cursor lookup(NodeState root, String uuid,
final String name, String index, Filter filter) {
NodeState indexRoot = root.getChildNode(INDEX_DEFINITIONS_NAME)
.getChildNode(NAME);
if (!indexRoot.exists()) {
return newPathCursor(new ArrayList<String>(), filter.getQueryEngineSettings());
}
- Iterable<String> paths = STORE.query(new FilterImpl(), index + "("
- + uuid + ")", indexRoot, index, ImmutableSet.of(uuid));
+ List<Iterable<String>> iterables = Lists.newArrayList();
+ for (IndexStoreStrategy s : getStrategies(indexRoot, mountInfoProvider, index)) {
+ iterables.add(s.query(new FilterImpl(), index + "("
+ + uuid + ")", indexRoot, ImmutableSet.of(uuid)));
+ }
+ Iterable<String> paths = Iterables.concat(iterables);
if (!"*".equals(name)) {
paths = filter(paths, new Predicate<String>() {
@@ -137,6 +156,12 @@ class ReferenceIndex implements QueryInd
return newPathCursor(paths, filter.getQueryEngineSettings());
}
+ private static Set<IndexStoreStrategy> getStrategies(NodeState definition,
+ MountInfoProvider mountInfoProvider, String index) {
+ return Multiplexers.getStrategies(false, mountInfoProvider, definition,
+ index);
+ }
+
@Override
public String getPlan(Filter filter, NodeState root) {
StringBuilder buff = new StringBuilder("reference");
Modified: 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=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexProvider.java Mon Jul 25 12:05:37 2016
@@ -21,7 +21,10 @@ import java.util.List;
import javax.annotation.Nonnull;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -35,9 +38,17 @@ import com.google.common.collect.Immutab
@Service(QueryIndexProvider.class)
public class ReferenceIndexProvider implements QueryIndexProvider {
+ @Reference
+ private MountInfoProvider mountInfoProvider = Mounts.defaultMountInfoProvider();
+
@Override
@Nonnull
public List<QueryIndex> getQueryIndexes(NodeState state) {
- return ImmutableList.<QueryIndex> of(new ReferenceIndex());
+ return ImmutableList.<QueryIndex> of(new ReferenceIndex(mountInfoProvider));
+ }
+
+ public ReferenceIndexProvider with(MountInfoProvider mountInfoProvider) {
+ this.mountInfoProvider = mountInfoProvider;
+ return this;
}
}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java?rev=1753981&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java Mon Jul 25 12:05:37 2016
@@ -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.index.property;
+
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.property.Multiplexers.getIndexNodeName;
+import static org.apache.jackrabbit.oak.plugins.index.property.Multiplexers.getNodeForMount;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.jackrabbit.oak.plugins.multiplex.SimpleMountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
+import org.junit.Test;
+
+public class MultiplexersTest {
+
+ @Test
+ public void defaultSetup() throws Exception {
+ assertEquals(
+ INDEX_CONTENT_NODE_NAME,
+ getIndexNodeName(Mounts.defaultMountInfoProvider(), "/foo",
+ INDEX_CONTENT_NODE_NAME));
+ assertEquals(INDEX_CONTENT_NODE_NAME,
+ getNodeForMount(Mounts.defaultMount(), INDEX_CONTENT_NODE_NAME));
+ }
+
+ @Test
+ public void customNodeName() throws Exception {
+ MountInfoProvider mip = SimpleMountInfoProvider.newBuilder()
+ .mount("foo", "/a", "/b").build();
+
+ Mount m = mip.getMountByName("foo");
+
+ assertEquals(":index",
+ getIndexNodeName(mip, "/foo", INDEX_CONTENT_NODE_NAME));
+ assertEquals(":index",
+ getNodeForMount(mip.getDefaultMount(), INDEX_CONTENT_NODE_NAME));
+
+ assertEquals(":" + m.getPathFragmentName() + "-index",
+ getIndexNodeName(mip, "/a", INDEX_CONTENT_NODE_NAME));
+ assertEquals(":" + m.getPathFragmentName() + "-index",
+ getNodeForMount(m, INDEX_CONTENT_NODE_NAME));
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/MultiplexersTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java Mon Jul 25 12:05:37 2016
@@ -21,6 +21,7 @@ import static org.apache.jackrabbit.JcrC
import static org.apache.jackrabbit.JcrConstants.NT_BASE;
import static org.apache.jackrabbit.JcrConstants.NT_FILE;
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_PATH;
import static org.apache.jackrabbit.oak.plugins.index.IndexUtils.createIndexDefinition;
@@ -30,6 +31,7 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.apache.jackrabbit.oak.spi.state.NodeStateUtils.getNode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -43,6 +45,7 @@ import org.apache.jackrabbit.oak.api.Typ
import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
import org.apache.jackrabbit.oak.plugins.index.property.strategy.ContentMirrorStoreStrategy;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
+import org.apache.jackrabbit.oak.plugins.multiplex.SimpleMountInfoProvider;
import org.apache.jackrabbit.oak.query.NodeStateNodeTypeInfoProvider;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.query.ast.NodeTypeInfo;
@@ -53,6 +56,8 @@ import org.apache.jackrabbit.oak.query.i
import org.apache.jackrabbit.oak.query.index.TraversingIndex;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -746,6 +751,107 @@ public class PropertyIndexTest {
assertEquals("/oak:index/foo", idxDefn.getString(INDEX_PATH));
}
+ @Test
+ public void singleMount() throws Exception {
+ NodeState root = INITIAL_CONTENT;
+
+ // Add index definition
+ NodeBuilder builder = root.builder();
+ NodeBuilder index = createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
+ true, false, ImmutableSet.of("foo"), null);
+ index.setProperty("entryCount", -1);
+ NodeState before = builder.getNodeState();
+
+ // Add some content and process it through the property index hook
+ builder.child("a").setProperty("foo", "abc");
+ builder.child("b").child("x").setProperty("foo", "abc");
+ builder.child("a").child("x").setProperty("foo", "abc");
+ builder.child("m").child("n").setProperty("foo", "abc");
+ builder.child("m").child("n").child("o").setProperty("foo", "abc");
+ builder.child("m").setProperty("foo", "abc");
+
+ NodeState after = builder.getNodeState();
+
+ MountInfoProvider mip = SimpleMountInfoProvider.newBuilder()
+ .mount("foo", "/a", "/m/n")
+ .build();
+
+ Mount fooMount = mip.getMountByName("foo");
+ Mount defMount = mip.getDefaultMount();
+
+ EditorHook hook = new EditorHook(
+ new IndexUpdateProvider(new PropertyIndexEditorProvider().with(mip)));
+
+ NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY);
+
+ FilterImpl f = createFilter(indexed, NT_BASE);
+
+ // Query the index
+ PropertyIndexLookup lookup = new PropertyIndexLookup(indexed,mip);
+ assertEquals(ImmutableSet.of("a", "b/x", "a/x", "m", "m/n", "m/n/o"), find(lookup, "foo", "abc", f));
+ assertEquals(ImmutableSet.of(), find(lookup, "foo", "ghi", f));
+
+ assertTrue(getNode(indexed, "/oak:index/foo/:index").exists());
+
+ //Separate node for mount
+ assertTrue(getNode(indexed, "/oak:index/foo/"+ getNodeForMount(fooMount)).exists());
+
+ //Index entries for paths in foo mount should go to :oak:foo-index
+ assertTrue(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/a", "abc")).exists());
+ assertTrue(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/a/x", "abc")).exists());
+ assertTrue(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/m/n", "abc")).exists());
+ assertTrue(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/m/n/o", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/a", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/a/x", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/m/n", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/m/n/o", "abc")).exists());
+
+ //All other index entries should go to :index
+ assertTrue(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/b", "abc")).exists());
+ assertTrue(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/b/x", "abc")).exists());
+ assertTrue(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/m", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/b", "abc")).exists());
+ assertFalse(getNode(indexed, pathInIndex(fooMount, "/oak:index/foo", "/b/x", "abc")).exists());
+
+ //System.out.println(NodeStateUtils.toString(getNode(indexed, "/oak:index/foo")));
+
+ }
+
+ @Test(expected = CommitFailedException.class)
+ public void mountAndUniqueIndexes() throws Exception {
+ NodeState root = INITIAL_CONTENT;
+
+ // Add index definition
+ NodeBuilder builder = root.builder();
+ NodeBuilder index = createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
+ true, true, ImmutableSet.of("foo"), null);
+ index.setProperty("entryCount", -1);
+ NodeState before = builder.getNodeState();
+
+ MountInfoProvider mip = SimpleMountInfoProvider.newBuilder()
+ .mount("foo", "/a")
+ .build();
+
+ builder.child("a").setProperty("foo", "abc");
+ builder.child("b").setProperty("foo", Arrays.asList("abc", "def"),
+ Type.STRINGS);
+ NodeState after = builder.getNodeState();
+
+ EditorHook hook = new EditorHook(
+ new IndexUpdateProvider(new PropertyIndexEditorProvider().with(mip)));
+ // should throw
+ hook.processCommit(before, after, CommitInfo.EMPTY);
+ }
+
+ private static String pathInIndex(Mount mount,
+ String indexPath, String indexedPath, String indexedValue){
+ return indexPath + "/" + getNodeForMount(mount) + "/" + indexedValue + indexedPath;
+ }
+
+ private static String getNodeForMount(Mount mount) {
+ return Multiplexers.getNodeForMount(mount, INDEX_CONTENT_NODE_NAME);
+ }
+
private int getResultSize(NodeState indexed, String name, String value){
FilterImpl f = createFilter(indexed, NT_BASE);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java?rev=1753981&r1=1753980&r2=1753981&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java Mon Jul 25 12:05:37 2016
@@ -63,7 +63,7 @@ public class ContentMirrorStoreStrategyT
* </ul>
*/
@Test
- public void testIndexPruning() {
+ public void testIndexPruning() throws CommitFailedException {
IndexStoreStrategy store = new ContentMirrorStoreStrategy();
NodeState root = EMPTY_NODE;
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java?rev=1753981&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java Mon Jul 25 12:05:37 2016
@@ -0,0 +1,150 @@
+/*
+ * 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.Collections;
+import java.util.List;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
+import org.apache.jackrabbit.oak.plugins.multiplex.SimpleMountInfoProvider;
+import org.apache.jackrabbit.oak.query.NodeStateNodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfo;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.ast.Operator;
+import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.junit.Test;
+
+import static com.google.common.collect.ImmutableList.of;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.apache.jackrabbit.JcrConstants.NT_BASE;
+import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.apache.jackrabbit.oak.spi.query.PropertyValues.newReference;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+public class ReferenceIndexTest {
+
+ @Test
+ public void basicReferenceHandling() throws Exception{
+ NodeState root = INITIAL_CONTENT;
+
+ NodeBuilder builder = root.builder();
+ NodeState before = builder.getNodeState();
+
+ builder.child("a").setProperty(createProperty("foo", "u1", Type.REFERENCE));
+ builder.child("b").setProperty(createProperty("foo", "u1", Type.REFERENCE));
+ builder.child("c").setProperty(createProperty("foo", "u2", Type.WEAKREFERENCE));
+
+ NodeState after = builder.getNodeState();
+ EditorHook hook = new EditorHook(
+ new IndexUpdateProvider(new ReferenceEditorProvider()));
+
+ NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY);
+ FilterImpl f = createFilter(indexed, NT_BASE);
+ f.restrictProperty("*", Operator.EQUAL, newReference("u1"), PropertyType.REFERENCE);
+
+ assertFilter(f, new ReferenceIndex(), indexed, of("/a", "/b"));
+
+ FilterImpl f2 = createFilter(indexed, NT_BASE);
+ f2.restrictProperty("*", Operator.EQUAL, newReference("u2"), PropertyType.WEAKREFERENCE);
+ assertFilter(f2, new ReferenceIndex(), indexed, of("/c"));
+ }
+
+ @Test
+ public void referenceHandlingWithMounts() throws Exception{
+ NodeState root = INITIAL_CONTENT;
+
+ NodeBuilder builder = root.builder();
+ NodeState before = builder.getNodeState();
+
+ builder.child("a").child("x").setProperty(createProperty("foo", "u1", Type.REFERENCE));
+ builder.child("b").setProperty(createProperty("foo", "u1", Type.REFERENCE));
+ builder.child("c").setProperty(createProperty("foo", "u1", Type.WEAKREFERENCE));
+
+ builder.child("d").setProperty(createProperty("foo", "u2", Type.WEAKREFERENCE));
+ builder.child("a").child("y").setProperty(createProperty("foo", "u1", Type.WEAKREFERENCE));
+
+ NodeState after = builder.getNodeState();
+
+ MountInfoProvider mip = SimpleMountInfoProvider.newBuilder()
+ .mount("foo", "/a")
+ .build();
+
+ EditorHook hook = new EditorHook(
+ new IndexUpdateProvider(new ReferenceEditorProvider().with(mip)));
+
+ ReferenceIndex referenceIndex = new ReferenceIndex(mip);
+
+ NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY);
+ FilterImpl f = createFilter(indexed, NT_BASE);
+ f.restrictProperty("*", Operator.EQUAL, newReference("u1"), PropertyType.REFERENCE);
+
+ // System.out.println(NodeStateUtils.toString(NodeStateUtils.getNode(indexed, "/oak:index/reference")));
+ assertFilter(f, referenceIndex, indexed, of("/a/x", "/b"));
+
+ FilterImpl f2 = createFilter(indexed, NT_BASE);
+ f2.restrictProperty("*", Operator.EQUAL, newReference("u1"), PropertyType.WEAKREFERENCE);
+ assertFilter(f2, referenceIndex, indexed, of("/c", "/a/y"));
+ }
+
+
+ //TODO Integrity check - Add node with id=1 and add a reference to that and then remove the node
+ //Removal
+
+ @SuppressWarnings("Duplicates")
+ private static FilterImpl createFilter(NodeState root, String nodeTypeName) {
+ NodeTypeInfoProvider nodeTypes = new NodeStateNodeTypeInfoProvider(root);
+ NodeTypeInfo type = nodeTypes.getNodeTypeInfo(nodeTypeName);
+ SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
+ return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + "]", new QueryEngineSettings());
+ }
+
+ private static List<String> assertFilter(Filter filter, QueryIndex queryIndex,
+ NodeState indexed, List<String> expected) {
+ Cursor cursor = queryIndex.query(filter, indexed);
+ List<String> paths = newArrayList();
+ while (cursor.hasNext()) {
+ paths.add(cursor.next().getPath());
+ }
+ Collections.sort(paths);
+ for (String p : expected) {
+ assertTrue("Expected path " + p + " not found", paths.contains(p));
+ }
+ assertEquals("Result set size is different \nExpected: " +
+ expected + "\nActual: " + paths, expected.size(), paths.size());
+ return paths;
+ }
+
+}
\ No newline at end of file
Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/reference/ReferenceIndexTest.java
------------------------------------------------------------------------------
svn:eol-style = native