use of org.apache.jackrabbit.oak.spi.state.NodeState in project jackrabbit-oak by apache.
the class PropertyIndex method createPlan.
private static PropertyIndexPlan createPlan(NodeState root, Filter filter, MountInfoProvider mountInfoProvider) {
PropertyIndexPlan bestPlan = null;
// TODO support indexes on a path
// currently, only indexes on the root node are supported
NodeState state = root.getChildNode(INDEX_DEFINITIONS_NAME);
for (ChildNodeEntry entry : state.getChildNodeEntries()) {
NodeState definition = entry.getNodeState();
if (PROPERTY.equals(definition.getString(TYPE_PROPERTY_NAME)) && definition.hasChildNode(INDEX_CONTENT_NODE_NAME)) {
PropertyIndexPlan plan = new PropertyIndexPlan(entry.getName(), root, definition, filter, mountInfoProvider);
if (plan.getCost() != Double.POSITIVE_INFINITY) {
LOG.debug("property cost for {} is {}", plan.getName(), plan.getCost());
if (bestPlan == null || plan.getCost() < bestPlan.getCost()) {
bestPlan = plan;
// Stop comparing if the costs are the minimum
if (plan.getCost() == PropertyIndexPlan.COST_OVERHEAD) {
break;
}
}
}
}
}
return bestPlan;
}
use of org.apache.jackrabbit.oak.spi.state.NodeState in project jackrabbit-oak by apache.
the class PropertyIndexInfoProvider method getInfo.
@Override
public IndexInfo getInfo(String indexPath) throws IOException {
NodeState idxState = NodeStateUtils.getNode(nodeStore.getRoot(), indexPath);
checkArgument(PropertyIndexEditorProvider.TYPE.equals(idxState.getString(IndexConstants.TYPE_PROPERTY_NAME)), "Index definition at [%s] is not of type 'property'", indexPath);
PropertyIndexInfo info = new PropertyIndexInfo(indexPath);
computeCountEstimate(info, idxState);
return info;
}
use of org.apache.jackrabbit.oak.spi.state.NodeState in project jackrabbit-oak by apache.
the class ContentMirrorStoreStrategy method query.
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() {
PathIterator it = new PathIterator(filter, indexName, "");
if (values == null) {
it.setPathContainsValue(true);
it.enqueue(getChildNodeEntries(index).iterator());
} else {
for (String p : values) {
NodeState property = index.getChildNode(p);
if (property.exists()) {
// we have an entry for this value, so use it
it.enqueue(Iterators.singletonIterator(new MemoryChildNodeEntry("", property)));
}
}
}
return it;
}
};
}
use of org.apache.jackrabbit.oak.spi.state.NodeState in project jackrabbit-oak by apache.
the class ContentMirrorStoreStrategy method count.
long count(Filter filter, NodeState root, NodeState indexMeta, final String indexStorageNodeName, Set<String> values, int max) {
NodeState index = indexMeta.getChildNode(indexStorageNodeName);
long count = -1;
if (values == null) {
// property is not null
PropertyState ec = indexMeta.getProperty(ENTRY_COUNT_PROPERTY_NAME);
if (ec != null) {
// negative value implies fall-back to counting
count = ec.getValue(Type.LONG);
} else {
// negative value means that approximation isn't available
count = ApproximateCounter.getCountSync(index);
}
if (count < 0) {
CountingNodeVisitor v = new CountingNodeVisitor(max);
v.visit(index);
count = v.getEstimatedCount();
if (count >= max) {
// "is not null" queries typically read more data
count *= 10;
}
}
} else {
// property = x, or property in (x, y, z)
int size = values.size();
if (size == 0) {
return 0;
}
PropertyState ec = indexMeta.getProperty(ENTRY_COUNT_PROPERTY_NAME);
if (ec != null) {
count = ec.getValue(Type.LONG);
if (count >= 0) {
// assume 10*NodeCounterEditor.DEFAULT_RESOLUTION entries per key, so that this index is used
// instead of traversal, but not instead of a regular property index
long keyCount = count / (10 * NodeCounterEditor.DEFAULT_RESOLUTION);
ec = indexMeta.getProperty(KEY_COUNT_PROPERTY_NAME);
if (ec != null) {
keyCount = ec.getValue(Type.LONG);
}
// cast to double to avoid overflow
// (entryCount could be Long.MAX_VALUE)
// the cost is not multiplied by the size,
// otherwise the traversing index might be used
keyCount = Math.max(1, keyCount);
count = (long) ((double) count / keyCount) + size;
}
} else {
// for this index, property "entryCount" is not set
long approxMax = 0;
long approxCount = ApproximateCounter.getCountSync(index);
if (approxCount != -1) {
// check approximate counts for each value
for (String p : values) {
NodeState s = index.getChildNode(p);
if (s.exists()) {
long a = ApproximateCounter.getCountSync(s);
if (a != -1) {
approxMax += a;
} else if (approxMax > 0) {
// in absence of approx count for a key we should be conservative
approxMax += 10 * NodeCounterEditor.DEFAULT_RESOLUTION;
}
}
}
if (approxMax > 0) {
count = approxMax;
}
}
}
// and we don't know the count ("entryCount" = -1)
if (count < 0) {
count = 0;
max = Math.max(10, max / size);
int i = 0;
for (String p : values) {
if (count > max && i > 3) {
// the total count is extrapolated from the the number
// of values counted so far to the total number of values
count = count * size / i;
break;
}
NodeState s = index.getChildNode(p);
if (s.exists()) {
CountingNodeVisitor v = new CountingNodeVisitor(max);
v.visit(s);
count += v.getEstimatedCount();
}
i++;
}
}
}
String filterRootPath = null;
if (filter != null && filter.getPathRestriction().equals(Filter.PathRestriction.ALL_CHILDREN)) {
filterRootPath = filter.getPath();
}
if (filterRootPath != null) {
// scale cost according to path restriction
long totalNodesCount = NodeCounter.getEstimatedNodeCount(root, "/", true);
if (totalNodesCount != -1) {
long filterPathCount = NodeCounter.getEstimatedNodeCount(root, filterRootPath, true);
if (filterPathCount != -1) {
// assume nodes in the index are evenly distributed in the repository (old idea)
long countScaledDown = (long) ((double) count / totalNodesCount * filterPathCount);
// assume 80% of the indexed nodes are in this subtree
long mostNodesFromThisSubtree = (long) (filterPathCount * 0.8);
// count can at most be the assumed subtree size
count = Math.min(count, mostNodesFromThisSubtree);
// this in theory should not have any effect,
// except if the above estimates are incorrect,
// so this is just for safety feature
count = Math.max(count, countScaledDown);
}
}
}
return count;
}
use of org.apache.jackrabbit.oak.spi.state.NodeState in project jackrabbit-oak by apache.
the class UniqueEntryStoreStrategy method query.
@Override
public Iterable<String> query(final Filter filter, final String indexName, final NodeState indexMeta, final Iterable<String> values) {
final NodeState index = indexMeta.getChildNode(getIndexNodeName());
return new Iterable<String>() {
@Override
public Iterator<String> iterator() {
if (values == null) {
return new Iterator<String>() {
Iterator<? extends ChildNodeEntry> it = index.getChildNodeEntries().iterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public String next() {
PropertyState s = it.next().getNodeState().getProperty("entry");
return s.getValue(Type.STRING, 0);
}
@Override
public void remove() {
it.remove();
}
};
}
ArrayList<String> list = new ArrayList<String>();
for (String p : values) {
NodeState key = index.getChildNode(p);
if (key.exists()) {
// we have an entry for this value, so use it
PropertyState s = key.getProperty("entry");
String v = s.getValue(Type.STRING, 0);
list.add(v);
}
}
return list.iterator();
}
};
}
Aggregations