use of org.apache.jackrabbit.oak.api.PropertyState 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.api.PropertyState in project jackrabbit-oak by apache.
the class UniqueEntryStoreStrategy method insert.
private static void insert(NodeBuilder index, String key, String value) {
ApproximateCounter.adjustCountSync(index, 1);
NodeBuilder k = index.child(key);
ArrayList<String> list = new ArrayList<String>();
list.add(value);
if (k.hasProperty("entry")) {
// duplicate key (to detect duplicate entries)
// this is just set temporarily,
// while trying to add a duplicate entry
PropertyState s = k.getProperty("entry");
for (int i = 0; i < s.count(); i++) {
String r = s.getValue(Type.STRING, i);
if (!list.contains(r)) {
list.add(r);
}
}
}
PropertyState s2 = MultiStringPropertyState.stringProperty("entry", list);
k.setProperty(s2);
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class UniqueEntryStoreStrategy method remove.
private static void remove(NodeBuilder index, String key, String value) {
ApproximateCounter.adjustCountSync(index, -1);
NodeBuilder builder = index.getChildNode(key);
if (builder.exists()) {
// there could be (temporarily) multiple entries
// we need to remove the right one
PropertyState s = builder.getProperty("entry");
if (s.count() == 1) {
builder.remove();
} else {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < s.count(); i++) {
String r = s.getValue(Type.STRING, i);
if (!r.equals(value)) {
list.add(r);
}
}
PropertyState s2 = MultiStringPropertyState.stringProperty("entry", list);
builder.setProperty(s2);
}
}
}
use of org.apache.jackrabbit.oak.api.PropertyState 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();
}
};
}
use of org.apache.jackrabbit.oak.api.PropertyState in project jackrabbit-oak by apache.
the class AbstractTypeDefinition method getValues.
private String[] getValues(String oakName, Type<String> type) {
String[] values = null;
PropertyState property = definition.getProperty(checkNotNull(oakName));
if (property != null) {
int n = property.count();
if (n > 0) {
values = new String[n];
for (int i = 0; i < n; i++) {
values[i] = property.getValue(type, i);
}
} else {
values = NO_STRINGS;
}
}
return values;
}
Aggregations