diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 833fd3c9ef3..83113a8238e 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -106,6 +106,9 @@ Bug Fixes * LUCENE-7755: Fixed join queries to not reference IndexReaders, as it could cause leaks if they are cached. (Adrien Grand) +* LUCENE-7749: Made LRUQueryCache delegate the scoreSupplier method. + (Martin Amirault via Adrien Grand) + Other * LUCENE-7763: Remove outdated comment in IndexWriterConfig.setIndexSort javadocs. diff --git a/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java b/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java index b1ba4e4ca49..451ce814ecd 100644 --- a/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java +++ b/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java @@ -717,7 +717,7 @@ public class LRUQueryCache implements QueryCache, Accountable { } @Override - public Scorer scorer(LeafReaderContext context) throws IOException { + public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOException { if (used.compareAndSet(false, true)) { policy.onUse(getQuery()); } @@ -726,18 +726,18 @@ public class LRUQueryCache implements QueryCache, Accountable { final IndexReader.CacheHelper cacheHelper = context.reader().getCoreCacheHelper(); if (cacheHelper == null) { // this segment is not suitable for caching - return in.scorer(context); + return in.scorerSupplier(context); } // Short-circuit: Check whether this segment is eligible for caching // before we take a lock because of #get if (shouldCache(context) == false) { - return in.scorer(context); + return in.scorerSupplier(context); } // If the lock is already busy, prefer using the uncached version than waiting if (lock.tryLock() == false) { - return in.scorer(context); + return in.scorerSupplier(context); } DocIdSet docIdSet; @@ -752,7 +752,7 @@ public class LRUQueryCache implements QueryCache, Accountable { docIdSet = cache(context); putIfAbsent(in.getQuery(), context, docIdSet, cacheHelper); } else { - return in.scorer(context); + return in.scorerSupplier(context); } } @@ -765,7 +765,27 @@ public class LRUQueryCache implements QueryCache, Accountable { return null; } - return new ConstantScoreScorer(this, 0f, disi); + return new ScorerSupplier() { + @Override + public Scorer get(boolean randomAccess) throws IOException { + return new ConstantScoreScorer(CachingWrapperWeight.this, 0f, disi); + } + + @Override + public long cost() { + return disi.cost(); + } + }; + + } + + @Override + public Scorer scorer(LeafReaderContext context) throws IOException { + ScorerSupplier scorerSupplier = scorerSupplier(context); + if (scorerSupplier == null) { + return null; + } + return scorerSupplier.get(false); } @Override diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java index 91c1887248b..ee3f4ad9bb2 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java @@ -1273,4 +1273,80 @@ public class TestLRUQueryCache extends LuceneTestCase { w.close(); dir.close(); } + + private static class DummyQuery2 extends Query { + + private final AtomicBoolean scorerCreated; + + DummyQuery2(AtomicBoolean scorerCreated) { + this.scorerCreated = scorerCreated; + } + + @Override + public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException { + return new ConstantScoreWeight(this, boost) { + @Override + public Scorer scorer(LeafReaderContext context) throws IOException { + return scorerSupplier(context).get(false); + } + @Override + public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOException { + final Weight weight = this; + return new ScorerSupplier() { + @Override + public Scorer get(boolean randomAccess) throws IOException { + scorerCreated.set(true); + return new ConstantScoreScorer(weight, boost, DocIdSetIterator.all(1)); + } + + @Override + public long cost() { + return 1; + } + }; + } + }; + } + + @Override + public boolean equals(Object other) { + return sameClassAs(other); + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString(String field) { + return "DummyQuery2"; + } + + } + + public void testPropagatesScorerSupplier() throws IOException { + Directory dir = newDirectory(); + IndexWriterConfig iwc = newIndexWriterConfig().setMergePolicy(NoMergePolicy.INSTANCE); + RandomIndexWriter w = new RandomIndexWriter(random(), dir, iwc); + w.addDocument(new Document()); + DirectoryReader reader = w.getReader(); + IndexSearcher searcher = newSearcher(reader); + searcher.setQueryCachingPolicy(NEVER_CACHE); + + LRUQueryCache cache = new LRUQueryCache(1, 1000); + searcher.setQueryCache(cache); + + AtomicBoolean scorerCreated = new AtomicBoolean(false); + Query query = new DummyQuery2(scorerCreated); + Weight weight = searcher.createNormalizedWeight(query, false); + ScorerSupplier supplier = weight.scorerSupplier(searcher.getIndexReader().leaves().get(0)); + assertFalse(scorerCreated.get()); + supplier.get(random().nextBoolean()); + assertTrue(scorerCreated.get()); + + reader.close(); + w.close(); + dir.close(); + } }