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 th...@apache.org on 2015/06/03 16:22:04 UTC
svn commit: r1683343 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/
oak-core/src/main/java/org/apache...
Author: thomasm
Date: Wed Jun 3 14:22:03 2015
New Revision: 1683343
URL: http://svn.apache.org/r1683343
Log:
OAK-2926 Fast result size estimate
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentIdTableBenchmark.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/UtilsTest.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/SizeEstimator.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/ResultSizeTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIterator.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIteratorTest.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java Wed Jun 3 14:22:03 2015
@@ -59,4 +59,43 @@ public interface Result {
*/
long getSize();
+ /**
+ * Get the number of rows, if known. If the size is not known, -1 is
+ * returned.
+ *
+ * @param precision the required precision
+ * @param max the maximum number that should be returned (Long.MAX_VALUE for
+ * unlimited). For EXACT, the cost of the operation is at most
+ * O(max). For approximations, the cost of the operation should
+ * be at most O(log max).
+ * @return the (approximate) size. If an implementation does know the exact
+ * value, it returns it (even if the value is higher than max). If
+ * the implementation does not know the value, and the child node
+ * count is higher than max, it returns Long.MAX_VALUE.
+ */
+ long getSize(SizePrecision precision, long max);
+
+ enum SizePrecision {
+
+ /**
+ * If the exact number is needed.
+ */
+ EXACT,
+
+ /**
+ * If a good, and secure estimate is needed (the actual number can be
+ * lower or higher). This is supposed to be faster than exact count, but
+ * slower than a fast approximation.
+ */
+ APPROXIMATION,
+
+ /**
+ * If a rough estimate is needed (the actual number can be lower or
+ * higher). This is supposed to be faster than a good approximation. It
+ * could be (for example) the expected cost of the query.
+ */
+ FAST_APPROXIMATION,
+
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/package-info.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/package-info.java Wed Jun 3 14:22:03 2015
@@ -18,7 +18,7 @@
/**
* Oak repository API
*/
-@Version("1.0")
+@Version("2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.api;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Wed Jun 3 14:22:03 2015
@@ -55,7 +55,21 @@ public interface Query {
Iterator<ResultRowImpl> getRows();
+ /**
+ * Get the size if known.
+ *
+ * @return the size, or -1 if unknown
+ */
long getSize();
+
+ /**
+ * Get the size if known.
+ *
+ * @param precision the required precision
+ * @param max the maximum nodes read (for an exact size)
+ * @return the size, or -1 if unknown
+ */
+ long getSize(Result.SizePrecision precision, long max);
void setExplain(boolean explain);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Wed Jun 3 14:22:03 2015
@@ -13,6 +13,7 @@
*/
package org.apache.jackrabbit.oak.query;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -25,6 +26,7 @@ import java.util.Set;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.namepath.JcrPathParser;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.query.ast.AndImpl;
@@ -979,6 +981,12 @@ public class QueryImpl implements Query
public long getSize() {
return size;
}
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ // Note: DISTINCT is ignored
+ return Math.min(limit, source.getSize(precision, max));
+ }
public String getStatement() {
return statement;
@@ -996,5 +1004,20 @@ public class QueryImpl implements Query
public ExecutionContext getExecutionContext() {
return context;
}
+
+ /**
+ * Add two values, but don't let it overflow or underflow.
+ *
+ * @param x the first value
+ * @param y the second value
+ * @return the sum, or Long.MIN_VALUE for underflow, or Long.MAX_VALUE for
+ * overflow
+ */
+ public static long saturatedAdd(long x, long y) {
+ BigInteger min = BigInteger.valueOf(Long.MIN_VALUE);
+ BigInteger max = BigInteger.valueOf(Long.MAX_VALUE);
+ BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y));
+ return sum.min(max).max(min).longValue();
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java Wed Jun 3 14:22:03 2015
@@ -80,4 +80,9 @@ public class ResultImpl implements Resul
return query.getSize();
}
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ return query.getSize(precision, max);
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Wed Jun 3 14:22:03 2015
@@ -22,6 +22,7 @@ import java.util.List;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.query.ast.ColumnImpl;
import org.apache.jackrabbit.oak.query.ast.OrderingImpl;
@@ -144,7 +145,16 @@ public class UnionQueryImpl implements Q
public long getSize() {
return size;
}
-
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ // Note: this does not respect the "unionAll == false" case
+ // (this can result in a larger reported size, but it is not a security problem)
+ return QueryImpl.saturatedAdd(
+ left.getSize(precision, max),
+ right.getSize(precision, max));
+ }
+
@Override
public void setExplain(boolean explain) {
this.explain = explain;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/JoinImpl.java Wed Jun 3 14:22:03 2015
@@ -16,6 +16,7 @@ package org.apache.jackrabbit.oak.query.
import java.util.ArrayList;
import java.util.List;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
import org.apache.jackrabbit.oak.query.plan.JoinExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Filter;
@@ -266,4 +267,10 @@ public class JoinImpl extends SourceImpl
return left.isOuterJoinRightHandSide() || right.isOuterJoinRightHandSide();
}
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ // we don't know
+ return -1;
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Wed Jun 3 14:22:03 2015
@@ -41,6 +41,7 @@ import javax.annotation.Nonnull;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -752,4 +753,12 @@ public class SelectorImpl extends Source
return query;
}
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ if (cursor == null) {
+ return -1;
+ }
+ return cursor.getSize(precision, max);
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SourceImpl.java Wed Jun 3 14:22:03 2015
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.query.
import java.util.Collections;
import java.util.List;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -153,4 +154,13 @@ public abstract class SourceImpl extends
*/
public abstract boolean isOuterJoinRightHandSide();
+ /**
+ * Get the size if known.
+ *
+ * @param precision the required precision
+ * @param max the maximum nodes read (for an exact size)
+ * @return the size, or -1 if unknown
+ */
+ public abstract long getSize(SizePrecision precision, long max);
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/package-info.java Wed Jun 3 14:22:03 2015
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.query;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursor.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursor.java Wed Jun 3 14:22:03 2015
@@ -20,6 +20,8 @@ package org.apache.jackrabbit.oak.spi.qu
import java.util.Iterator;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
+
/**
* A cursor to read a number of nodes sequentially.
*/
@@ -50,5 +52,14 @@ public interface Cursor extends Iterator
*/
@Override
IndexRow next();
+
+ /**
+ * Get the size if known.
+ *
+ * @param precision the required precision
+ * @param max the maximum nodes read (for an exact size)
+ * @return the size, or -1 if unknown
+ */
+ long getSize(SizePrecision precision, long max);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java Wed Jun 3 14:22:03 2015
@@ -24,6 +24,7 @@ import java.util.List;
import javax.annotation.Nullable;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
import org.apache.jackrabbit.oak.query.FilterIterators;
@@ -124,6 +125,11 @@ public class Cursors {
throw new UnsupportedOperationException();
}
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ return -1;
+ }
+
}
/**
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/package-info.java Wed Jun 3 14:22:03 2015
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0.1")
+@Version("2.0.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.query;
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentIdTableBenchmark.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentIdTableBenchmark.java?rev=1683343&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentIdTableBenchmark.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentIdTableBenchmark.java Wed Jun 3 14:22:03 2015
@@ -0,0 +1,122 @@
+/*
+ * 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.segment;
+
+import java.lang.ref.WeakReference;
+import java.util.Random;
+
+import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
+
+public class SegmentIdTableBenchmark {
+ public static void main(String... args) {
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ }
+
+ private static void test() {
+ long time;
+ int repeat = 10000;
+ int count = 10000;
+
+ long[] array = new long[count];
+ Random r = new Random(1);
+ for (int i = 0; i < array.length; i++) {
+ array[i] = r.nextLong();
+ }
+
+ time = System.currentTimeMillis();
+ SegmentTracker tracker = new MemoryStore().getTracker();
+ final SegmentIdTable tbl = new SegmentIdTable(tracker);
+ for (int i = 0; i < repeat; i++) {
+ for (int j = 0; j < count; j++) {
+ tbl.getSegmentId(j, array[j]);
+ }
+ }
+ time = System.currentTimeMillis() - time;
+ System.out.println("SegmentIdTable: " + time);
+
+ time = System.currentTimeMillis();
+ ConcurrentTable cm = new ConcurrentTable(tracker, 16 * 1024);
+ for (int i = 0; i < repeat; i++) {
+ for (int j = 0; j < count; j++) {
+ cm.getSegmentId(j, array[j]);
+ }
+ }
+ time = System.currentTimeMillis() - time;
+ System.out.println("ConcurrentTable: " + time);
+
+// time = System.currentTimeMillis();
+// WeakHashMap<SegmentId, SegmentId> map = new WeakHashMap<SegmentId, SegmentId>(count);
+// for (int i = 0; i < repeat; i++) {
+// for (int j = 0; j < count; j++) {
+// SegmentId id = new SegmentId(tracker, j, j);
+// if (map.get(id) == null) {
+// map.put(id, id);
+// }
+// }
+// }
+// time = System.currentTimeMillis() - time;
+// System.out.println("WeakHashMap: " + time);
+ }
+
+ static class ConcurrentTable {
+ private final SegmentTracker tracker;
+ volatile WeakReference<SegmentId>[] map;
+ @SuppressWarnings("unchecked")
+ ConcurrentTable(SegmentTracker tracker, int size) {
+ this.tracker = tracker;
+ map = (WeakReference<SegmentId>[]) new WeakReference[size];
+ }
+ SegmentId getSegmentId(long a, long b) {
+ outer:
+ while (true) {
+ int increment = 1;
+ WeakReference<SegmentId>[] m = map;
+ int length = m.length;
+ int index = (int) (b & (length - 1));
+ while (true) {
+ WeakReference<SegmentId> ref = m[index];
+ if (ref == null) {
+ SegmentId id = new SegmentId(tracker, a, b);
+ ref = new WeakReference<SegmentId>(id);
+ m[index] = ref;
+ if (m != map) {
+ continue outer;
+ }
+ return id;
+ }
+ SegmentId id = ref.get();
+ if (id != null) {
+ if (id.getMostSignificantBits() == a && id.getLeastSignificantBits() == b) {
+ return id;
+ }
+ }
+ index = (index + increment) & (length - 1);
+ increment += increment;
+ if (increment > 100) {
+ System.out.println("inc " + increment);
+ }
+ }
+ }
+ }
+ }
+
+}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java Wed Jun 3 14:22:03 2015
@@ -39,6 +39,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.QueryEngine;
import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
@@ -265,6 +266,23 @@ public abstract class AbstractQueryTest
protected List<String> assertQuery(String sql, List<String> expected) {
return assertQuery(sql, SQL2, expected);
}
+
+ protected void assertResultSize(String query, String language, long expected) {
+ long time = System.currentTimeMillis();
+ try {
+ Result result = executeQuery(query, language, NO_BINDINGS);
+ // currently needed to iterate to really execute the query
+ result.getRows().iterator().hasNext();
+ long got = result.getSize(SizePrecision.APPROXIMATION, 0);
+ assertEquals(expected, got);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ time = System.currentTimeMillis() - time;
+ if (time > 10000 && !isDebugModeEnabled()) {
+ fail("Query took too long: " + query + " took " + time + " ms");
+ }
+ }
protected List<String> assertQuery(String sql, String language,
List<String> expected) {
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/UtilsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/UtilsTest.java?rev=1683343&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/UtilsTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/UtilsTest.java Wed Jun 3 14:22:03 2015
@@ -0,0 +1,61 @@
+/*
+ * 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.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+public class UtilsTest {
+
+ @Test
+ public void saturatedAdd() {
+ assertEquals(3, QueryImpl.saturatedAdd(1, 2));
+ assertEquals(Long.MAX_VALUE, QueryImpl.saturatedAdd(1, Long.MAX_VALUE));
+ assertEquals(Long.MAX_VALUE, QueryImpl.saturatedAdd(Long.MAX_VALUE, 1));
+ assertEquals(Long.MAX_VALUE, QueryImpl.saturatedAdd(Long.MAX_VALUE, Long.MAX_VALUE));
+ long[] test = {Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 10,
+ -1000, -10, -1, 0, 1, 3, 10000,
+ Long.MAX_VALUE - 20, Long.MAX_VALUE - 1, Long.MAX_VALUE};
+ Random r = new Random(1);
+ for (int i = 0; i < 10000; i++) {
+ long x = r.nextBoolean() ? test[r.nextInt(test.length)] : r
+ .nextLong();
+ long y = r.nextBoolean() ? test[r.nextInt(test.length)] : r
+ .nextLong();
+ long alt = altSaturatedAdd(x, y);
+ long got = QueryImpl.saturatedAdd(x, y);
+ assertEquals(x + "+" + y, alt, got);
+ }
+ }
+
+ private static long altSaturatedAdd(long x, long y) {
+ // see also http://stackoverflow.com/questions/2632392/saturated-addition-of-two-signed-java-long-values
+ if (x > 0 != y > 0) {
+ // different signs
+ return x + y;
+ } else if (x > 0) {
+ // can overflow
+ return Long.MAX_VALUE - x < y ? Long.MAX_VALUE : x + y;
+ } else {
+ // can underflow
+ return Long.MIN_VALUE - x > y ? Long.MIN_VALUE : x + y;
+ }
+ }
+}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java Wed Jun 3 14:22:03 2015
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.junit.Test;
@@ -99,6 +100,11 @@ public class CursorsTest {
public IndexRow next() {
return rows.next();
}
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ return -1;
+ }
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIterator.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIterator.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIterator.java Wed Jun 3 14:22:03 2015
@@ -22,6 +22,9 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
+
/**
* An iterator that pre-fetches a number of items in order to calculate the size
* of the result if possible. This iterator loads at least a number of items,
@@ -33,7 +36,11 @@ import java.util.NoSuchElementException;
* @param <K> the iterator data type
*/
public class PrefetchIterator<K> implements Iterator<K> {
-
+
+ private final boolean fastSize = Boolean.getBoolean("oak.fastQuerySize");
+
+ private final Result result;
+
private final Iterator<K> it;
private final long minPrefetch, timeout, maxPrefetch;
private boolean prefetchDone;
@@ -48,13 +55,19 @@ public class PrefetchIterator<K> impleme
* @param timeout the maximum time to pre-fetch in milliseconds
* @param max the maximum number of items to pre-fetch
* @param size the size (prefetching is only required if -1)
+ * @param result (optional) the result to get the size from
*/
- PrefetchIterator(Iterator<K> it, long min, long timeout, long max, long size) {
+ PrefetchIterator(Iterator<K> it, long min, long timeout, long max,
+ long size, Result result) {
this.it = it;
this.minPrefetch = min;
+ if (fastSize) {
+ timeout = 0;
+ }
this.timeout = timeout;
this.maxPrefetch = max;
this.size = size;
+ this.result = result;
}
@Override
@@ -97,9 +110,14 @@ public class PrefetchIterator<K> impleme
* @return the size, or -1 if unknown
*/
public long size() {
- if (size != -1 || prefetchDone || position > maxPrefetch) {
+ if (size != -1) {
return size;
}
+ if (!fastSize) {
+ if (prefetchDone || position > maxPrefetch) {
+ return -1;
+ }
+ }
prefetchDone = true;
ArrayList<K> list = new ArrayList<K>();
long end;
@@ -126,6 +144,11 @@ public class PrefetchIterator<K> impleme
prefetchIterator = list.iterator();
position -= list.size();
}
+ if (size == -1 && fastSize) {
+ if (result != null) {
+ size = result.getSize(SizePrecision.EXACT, Long.MAX_VALUE);
+ }
+ }
return size;
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java Wed Jun 3 14:22:03 2015
@@ -137,7 +137,7 @@ public class QueryResultImpl implements
final PrefetchIterator<RowImpl> prefIt = new PrefetchIterator<RowImpl>(
sessionDelegate.sync(rowIterator),
PREFETCH_MIN, PREFETCH_TIMEOUT, PREFETCH_MAX,
- result.getSize());
+ result.getSize(), result);
return new RowIteratorAdapter(prefIt) {
@Override
public long getSize() {
@@ -151,9 +151,8 @@ public class QueryResultImpl implements
if (tree != null && tree.exists()) {
NodeDelegate node = new NodeDelegate(sessionDelegate, tree);
return NodeImpl.createNode(node, sessionContext);
- } else {
- return null;
}
+ return null;
}
@Override
@@ -217,8 +216,8 @@ public class QueryResultImpl implements
};
final PrefetchIterator<NodeImpl<? extends NodeDelegate>> prefIt = new PrefetchIterator<NodeImpl<? extends NodeDelegate>>(
sessionDelegate.sync(nodeIterator),
- PREFETCH_MIN, PREFETCH_TIMEOUT, PREFETCH_MAX,
- result.getSize());
+ PREFETCH_MIN, PREFETCH_TIMEOUT, PREFETCH_MAX,
+ result.getSize(), result);
return new NodeIteratorAdapter(prefIt) {
@Override
public long getSize() {
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIteratorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIteratorTest.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIteratorTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/PrefetchIteratorTest.java Wed Jun 3 14:22:03 2015
@@ -36,7 +36,7 @@ public class PrefetchIteratorTest {
Iterable<Integer> s;
PrefetchIterator<Integer> it;
s = seq(0, 100);
- it = new PrefetchIterator<Integer>(s.iterator(), 5, 0, 10, 200);
+ it = new PrefetchIterator<Integer>(s.iterator(), 5, 0, 10, 200, null);
// reports the 'wrong' value as it was set manually
assertEquals(200, it.size());
}
@@ -49,12 +49,12 @@ public class PrefetchIteratorTest {
// long delay (10 ms per row)
long timeout = 10;
s = seq(0, 100, 10);
- it = new PrefetchIterator<Integer>(s.iterator(), 5, timeout, 1000, -1);
+ it = new PrefetchIterator<Integer>(s.iterator(), 5, timeout, 1000, -1, null);
assertEquals(-1, it.size());
// no delay
s = seq(0, 100);
- it = new PrefetchIterator<Integer>(s.iterator(), 5, timeout, 1000, -1);
+ it = new PrefetchIterator<Integer>(s.iterator(), 5, timeout, 1000, -1, null);
assertEquals(100, it.size());
}
@@ -68,7 +68,7 @@ public class PrefetchIteratorTest {
long timeout = size % 3 == 0 ? 100 : 0;
Iterable<Integer> s = seq(0, size);
PrefetchIterator<Integer> it =
- new PrefetchIterator<Integer>(s.iterator(), 20, timeout, 30, -1);
+ new PrefetchIterator<Integer>(s.iterator(), 20, timeout, 30, -1, null);
for (int x : seq(0, readBefore)) {
boolean hasNext = it.hasNext();
if (!hasNext) {
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java Wed Jun 3 14:22:03 2015
@@ -56,6 +56,7 @@ import com.google.common.collect.Sets;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.MoreLikeThisHelper;
@@ -1132,6 +1133,12 @@ public class LuceneIndex implements Adva
};
}
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ // not yet supported
+ return -1;
+ }
}
private static class PathStoredFieldVisitor extends StoredFieldVisitor {
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java Wed Jun 3 14:22:03 2015
@@ -38,6 +38,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
@@ -92,6 +93,7 @@ import org.apache.lucene.search.SortFiel
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.TotalHitCountCollector;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.spell.SuggestWord;
import org.apache.lucene.search.suggest.Lookup;
@@ -449,7 +451,31 @@ public class LucenePropertyIndex impleme
this.lastSearchIndexerVersion = currentVersion;
}
};
- return new LucenePathCursor(itr, plan, settings);
+ SizeEstimator sizeEstimator = new SizeEstimator() {
+ @Override
+ public long getSize() {
+ IndexNode indexNode = acquireIndexNode(plan);
+ checkState(indexNode != null);
+ try {
+ IndexSearcher searcher = indexNode.getSearcher();
+ LuceneRequestFacade luceneRequestFacade = getLuceneRequest(plan, searcher.getIndexReader());
+ if (luceneRequestFacade.getLuceneRequest() instanceof Query) {
+ Query query = (Query) luceneRequestFacade.getLuceneRequest();
+ LOG.debug("estimate size for query " + query);
+ TotalHitCountCollector collector = new TotalHitCountCollector();
+ searcher.search(query, collector);
+ return collector.getTotalHits();
+ }
+ LOG.debug("estimate size: not a Query: " + luceneRequestFacade.getLuceneRequest());
+ } catch (IOException e) {
+ LOG.warn("query via {} failed.", LucenePropertyIndex.this, e);
+ } finally {
+ indexNode.release();
+ }
+ return -1;
+ }
+ };
+ return new LucenePathCursor(itr, plan, settings, sizeEstimator);
}
@Override
@@ -1169,9 +1195,12 @@ public class LucenePropertyIndex impleme
private final Cursor pathCursor;
private final String pathPrefix;
LuceneResultRow currentRow;
+ private final SizeEstimator sizeEstimator;
+ private long estimatedSize;
- LucenePathCursor(final Iterator<LuceneResultRow> it, final IndexPlan plan, QueryEngineSettings settings) {
+ LucenePathCursor(final Iterator<LuceneResultRow> it, final IndexPlan plan, QueryEngineSettings settings, SizeEstimator sizeEstimator) {
pathPrefix = plan.getPathPrefix();
+ this.sizeEstimator = sizeEstimator;
Iterator<String> pathIterator = new Iterator<String>() {
@Override
@@ -1234,6 +1263,15 @@ public class LucenePropertyIndex impleme
};
}
+
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ if (estimatedSize != 0) {
+ return estimatedSize;
+ }
+ return estimatedSize = sizeEstimator.getSize();
+ }
}
private static class PathStoredFieldVisitor extends StoredFieldVisitor {
Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/SizeEstimator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/SizeEstimator.java?rev=1683343&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/SizeEstimator.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/SizeEstimator.java Wed Jun 3 14:22:03 2015
@@ -0,0 +1,30 @@
+/*
+ * 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.lucene;
+
+public interface SizeEstimator {
+
+ /**
+ * Get the estimated size, or -1 if not known.
+ *
+ * @return the size
+ */
+ long getSize();
+
+}
Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/ResultSizeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/ResultSizeTest.java?rev=1683343&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/ResultSizeTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/ResultSizeTest.java Wed Jun 3 14:22:03 2015
@@ -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.jcr.query;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+import org.apache.jackrabbit.core.query.AbstractQueryTest;
+
+public class ResultSizeTest extends AbstractQueryTest {
+
+ public void testResultSize() throws Exception {
+ Session session = superuser;
+ QueryManager qm = session.getWorkspace().getQueryManager();
+ for (int i = 0; i < 200; i++) {
+ Node n = testRootNode.addNode("node" + i);
+ n.setProperty("text", "Hello World");
+ }
+ session.save();
+
+ String xpath = "/jcr:root//*[jcr:contains(@text, 'Hello World')]";
+
+ Query q;
+ long result;
+
+ // fast (insecure) case
+ System.setProperty("oak.fastQuerySize", "true");
+ q = qm.createQuery(xpath, "xpath");
+ result = q.execute().getRows().getSize();
+ assertTrue("size: " + result, result > 150 && result < 250);
+
+ q = qm.createQuery(xpath, "xpath");
+ q.setLimit(90);
+ assertEquals(90, q.execute().getRows().getSize());
+
+ // default (secure) case
+ System.clearProperty("oak.fastQuerySize");
+ q = qm.createQuery(xpath, "xpath");
+ result = q.execute().getRows().getSize();
+ assertEquals(-1, q.execute().getRows().getSize());
+
+ }
+
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java?rev=1683343&r1=1683342&r2=1683343&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java (original)
+++ jackrabbit/oak/trunk/oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/SolrQueryIndex.java Wed Jun 3 14:22:03 2015
@@ -32,6 +32,7 @@ import com.google.common.collect.Iterabl
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
import org.apache.jackrabbit.oak.plugins.index.solr.configuration.OakSolrConfiguration;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
@@ -541,6 +542,12 @@ public class SolrQueryIndex implements F
};
}
+
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ return -1;
+ }
}
@Override