2021-10-13 00:23:56 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2022-02-11 13:32:50 +01:00
|
|
|
package org.apache.lucene.search;
|
2021-10-13 00:23:56 +02:00
|
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
|
|
|
/** Used for defining custom algorithms to allow searches to early terminate */
|
2022-02-11 13:32:50 +01:00
|
|
|
public abstract class CustomHitsThresholdChecker {
|
|
|
|
/** Implementation of CustomHitsThresholdChecker which allows global hit counting */
|
|
|
|
private static class GlobalHitsThresholdChecker extends CustomHitsThresholdChecker {
|
2021-10-15 22:03:53 +02:00
|
|
|
private final long totalHitsThreshold;
|
2021-10-13 00:23:56 +02:00
|
|
|
private final AtomicLong globalHitCount;
|
|
|
|
|
2021-10-15 22:03:53 +02:00
|
|
|
public GlobalHitsThresholdChecker(long totalHitsThreshold) {
|
2021-10-13 00:23:56 +02:00
|
|
|
|
|
|
|
if (totalHitsThreshold < 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"totalHitsThreshold must be >= 0, got " + totalHitsThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.totalHitsThreshold = totalHitsThreshold;
|
|
|
|
this.globalHitCount = new AtomicLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void incrementHitCount() {
|
|
|
|
globalHitCount.incrementAndGet();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-10-15 22:03:53 +02:00
|
|
|
public boolean isThresholdReached(boolean supports64Bit) {
|
|
|
|
if (supports64Bit) {
|
|
|
|
return globalHitCount.getAcquire() > totalHitsThreshold;
|
|
|
|
} else {
|
|
|
|
return Math.min(globalHitCount.getAcquire(), Integer.MAX_VALUE) > Math.min(totalHitsThreshold, Integer.MAX_VALUE);
|
|
|
|
}
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ScoreMode scoreMode() {
|
2021-10-15 22:03:53 +02:00
|
|
|
if (totalHitsThreshold == Long.MAX_VALUE) {
|
|
|
|
return ScoreMode.COMPLETE;
|
|
|
|
}
|
|
|
|
return ScoreMode.TOP_SCORES;
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-10-15 22:03:53 +02:00
|
|
|
public long getHitsThreshold(boolean supports64Bit) {
|
|
|
|
if (supports64Bit) {
|
|
|
|
return totalHitsThreshold;
|
|
|
|
} else {
|
|
|
|
return Math.min(totalHitsThreshold, Integer.MAX_VALUE);
|
|
|
|
}
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-11 13:32:50 +01:00
|
|
|
/** Default implementation of CustomHitsThresholdChecker to be used for single threaded execution */
|
|
|
|
private static class LocalHitsThresholdChecker extends CustomHitsThresholdChecker {
|
2021-10-15 22:03:53 +02:00
|
|
|
private final long totalHitsThreshold;
|
|
|
|
private long hitCount;
|
2021-10-13 00:23:56 +02:00
|
|
|
|
2021-10-15 22:03:53 +02:00
|
|
|
public LocalHitsThresholdChecker(long totalHitsThreshold) {
|
2021-10-13 00:23:56 +02:00
|
|
|
|
|
|
|
if (totalHitsThreshold < 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"totalHitsThreshold must be >= 0, got " + totalHitsThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.totalHitsThreshold = totalHitsThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void incrementHitCount() {
|
|
|
|
++hitCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-10-15 22:03:53 +02:00
|
|
|
public boolean isThresholdReached(boolean supports64Bit) {
|
|
|
|
if (supports64Bit) {
|
|
|
|
return hitCount > totalHitsThreshold;
|
|
|
|
} else {
|
|
|
|
return Math.min(hitCount, Integer.MAX_VALUE) > Math.min(totalHitsThreshold, Integer.MAX_VALUE);
|
|
|
|
}
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ScoreMode scoreMode() {
|
2021-10-15 22:03:53 +02:00
|
|
|
if (totalHitsThreshold == Long.MAX_VALUE) {
|
|
|
|
return ScoreMode.COMPLETE;
|
|
|
|
}
|
|
|
|
return ScoreMode.TOP_SCORES;
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-10-15 22:03:53 +02:00
|
|
|
public long getHitsThreshold(boolean supports64Bit) {
|
|
|
|
if (supports64Bit) {
|
|
|
|
return totalHitsThreshold;
|
|
|
|
} else {
|
|
|
|
return Math.min(totalHitsThreshold, Integer.MAX_VALUE);
|
|
|
|
}
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns a threshold checker that is useful for single threaded searches
|
|
|
|
*/
|
2022-02-11 13:32:50 +01:00
|
|
|
public static CustomHitsThresholdChecker create(final long totalHitsThreshold) {
|
2021-10-13 00:23:56 +02:00
|
|
|
return new LocalHitsThresholdChecker(totalHitsThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns a threshold checker that is based on a shared counter
|
|
|
|
*/
|
2022-02-11 13:32:50 +01:00
|
|
|
public static CustomHitsThresholdChecker createShared(final long totalHitsThreshold) {
|
2021-10-13 00:23:56 +02:00
|
|
|
return new GlobalHitsThresholdChecker(totalHitsThreshold);
|
|
|
|
}
|
|
|
|
|
|
|
|
public abstract void incrementHitCount();
|
|
|
|
|
|
|
|
public abstract ScoreMode scoreMode();
|
|
|
|
|
2021-10-15 22:03:53 +02:00
|
|
|
public abstract long getHitsThreshold(boolean supports64Bit);
|
2021-10-13 00:23:56 +02:00
|
|
|
|
2021-10-15 22:03:53 +02:00
|
|
|
public abstract boolean isThresholdReached(boolean supports64Bit);
|
2021-10-13 00:23:56 +02:00
|
|
|
}
|