Github user jpountz commented on a diff in the pull request: https://github.com/apache/lucene-solr/pull/497#discussion_r232738340 --- Diff: lucene/core/src/java/org/apache/lucene/index/ExitableDirectoryReader.java --- @@ -100,13 +109,157 @@ public CacheHelper getCoreCacheHelper() { } + /** + * Wrapper class for another PointValues implementation that is used by ExitableFields. + */ + public static class ExitablePointValues extends PointValues { + + private final PointValues in; + private final QueryTimeout queryTimeout; + + public ExitablePointValues(PointValues in, QueryTimeout queryTimeout) { + this.in = in; + this.queryTimeout = queryTimeout; + checkAndThrow(); + } + + /** + * Throws {@link ExitingReaderException} if {@link QueryTimeout#shouldExit()} returns true, + * or if {@link Thread#interrupted()} returns true. + */ + private void checkAndThrow() { + if (queryTimeout.shouldExit()) { + throw new ExitingReaderException("The request took too long to iterate over point values. Timeout: " + + queryTimeout.toString() + + ", PointValues=" + in + ); + } else if (Thread.interrupted()) { + throw new ExitingReaderException("Interrupted while iterating over point values. PointValues=" + in); + } + } + + @Override + public void intersect(IntersectVisitor visitor) throws IOException { + checkAndThrow(); + in.intersect(new ExitableIntersectVisitor(visitor, queryTimeout)); + } + + @Override + public long estimatePointCount(IntersectVisitor visitor) { + checkAndThrow(); + return in.estimatePointCount(visitor); + } + + @Override + public byte[] getMinPackedValue() throws IOException { + checkAndThrow(); + return in.getMinPackedValue(); + } + + @Override + public byte[] getMaxPackedValue() throws IOException { + checkAndThrow(); + return in.getMaxPackedValue(); + } + + @Override + public int getNumDataDimensions() throws IOException { + checkAndThrow(); + return in.getNumDataDimensions(); + } + + @Override + public int getNumIndexDimensions() throws IOException { + checkAndThrow(); + return in.getNumIndexDimensions(); + } + + @Override + public int getBytesPerDimension() throws IOException { + checkAndThrow(); + return in.getBytesPerDimension(); + } + + @Override + public long size() { + checkAndThrow(); + return in.size(); + } + + @Override + public int getDocCount() { + checkAndThrow(); + return in.getDocCount(); + } + } + + public static class ExitableIntersectVisitor implements PointValues.IntersectVisitor { + + public static final int DEFAULT_MAX_CALLS_BEFORE_QUERY_TIMEOUT_CHECK = 10; + + private final PointValues.IntersectVisitor in; + private final QueryTimeout queryTimeout; + private final int maxCallsBeforeQueryTimeoutCheck; + private int calls = 0; + + public ExitableIntersectVisitor(PointValues.IntersectVisitor in, QueryTimeout queryTimeout) { + this(in, queryTimeout, DEFAULT_MAX_CALLS_BEFORE_QUERY_TIMEOUT_CHECK); + } + + public ExitableIntersectVisitor(PointValues.IntersectVisitor in, + QueryTimeout queryTimeout, int maxCallsBeforeQueryTimeoutCheck) { + this.in = in; + this.queryTimeout = queryTimeout; + this.maxCallsBeforeQueryTimeoutCheck = maxCallsBeforeQueryTimeoutCheck; + } + + /** + * Throws {@link ExitingReaderException} if {@link QueryTimeout#shouldExit()} returns true, + * or if {@link Thread#interrupted()} returns true. + */ + private void checkAndThrow() { + if (calls++ % maxCallsBeforeQueryTimeoutCheck == 0 && queryTimeout.shouldExit()) { + throw new ExitingReaderException("The request took too long to intersect point values. Timeout: " + + queryTimeout.toString() + + ", PointValues=" + in + ); + } else if (Thread.interrupted()) { --- End diff -- should this also not be called everytime and moved under the `if (calls++ % maxCallsBeforeQueryTimeoutCheck == 0)` test?
--- --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@lucene.apache.org For additional commands, e-mail: dev-h...@lucene.apache.org