diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index f4896bda4fa..4ad54d6c228 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -53,6 +53,11 @@ Bug Fixes * LUCENE-6378: Fix all RuntimeExceptions to throw the underlying root cause. (Varun Thacker, Adrien Grand, Mike McCandless) +API Changes + +* LUCENE-6377: SearcherFactory#newSearcher now accepts the previous reader + to simplify warming logic during opening new searchers. (Simon Willnauer) + ======================= Lucene 5.1.0 ======================= New Features diff --git a/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java b/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java index 3c7c8cb6173..dbdade9b30d 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java +++ b/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java @@ -49,9 +49,15 @@ import org.apache.lucene.search.similarities.Similarity; // javadocs */ public class SearcherFactory { /** - * Returns a new IndexSearcher over the given reader. + * Returns a new IndexSearcher over the given reader. + * @param reader the reader to create a new searcher for + * @param previousReader the reader previously used to create a new searcher. + * This can be null if unknown or if the given reader is the initially opened reader. + * If this reader is non-null it can be used to find newly opened segments compared to the new reader to warm + * the searcher up before returning. */ - public IndexSearcher newSearcher(IndexReader reader) throws IOException { + public IndexSearcher newSearcher(IndexReader reader, IndexReader previousReader) throws IOException { return new IndexSearcher(reader); } + } diff --git a/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java b/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java index f71134c1ad4..c35826cb72a 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java +++ b/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java @@ -86,7 +86,7 @@ public final class SearcherManager extends ReferenceManager { searcherFactory = new SearcherFactory(); } this.searcherFactory = searcherFactory; - current = getSearcher(searcherFactory, DirectoryReader.open(writer, applyAllDeletes)); + current = getSearcher(searcherFactory, DirectoryReader.open(writer, applyAllDeletes), null); } /** @@ -103,7 +103,7 @@ public final class SearcherManager extends ReferenceManager { searcherFactory = new SearcherFactory(); } this.searcherFactory = searcherFactory; - current = getSearcher(searcherFactory, DirectoryReader.open(dir)); + current = getSearcher(searcherFactory, DirectoryReader.open(dir), null); } /** @@ -122,7 +122,7 @@ public final class SearcherManager extends ReferenceManager { searcherFactory = new SearcherFactory(); } this.searcherFactory = searcherFactory; - this.current = getSearcher(searcherFactory, reader); + this.current = getSearcher(searcherFactory, reader, null); } @Override @@ -138,7 +138,7 @@ public final class SearcherManager extends ReferenceManager { if (newReader == null) { return null; } else { - return getSearcher(searcherFactory, newReader); + return getSearcher(searcherFactory, newReader, r); } } @@ -172,11 +172,11 @@ public final class SearcherManager extends ReferenceManager { * IndexReader} using the provided {@link * SearcherFactory}. NOTE: this decRefs incoming reader * on throwing an exception. */ - public static IndexSearcher getSearcher(SearcherFactory searcherFactory, IndexReader reader) throws IOException { + public static IndexSearcher getSearcher(SearcherFactory searcherFactory, IndexReader reader, IndexReader previousReader) throws IOException { boolean success = false; final IndexSearcher searcher; try { - searcher = searcherFactory.newSearcher(reader); + searcher = searcherFactory.newSearcher(reader, previousReader); if (searcher.getIndexReader() != reader) { throw new IllegalStateException("SearcherFactory must wrap exactly the provided reader (got " + searcher.getIndexReader() + " but expected " + reader + ")"); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestControlledRealTimeReopenThread.java b/lucene/core/src/test/org/apache/lucene/search/TestControlledRealTimeReopenThread.java index 37bc44b3590..e59ebc7416a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestControlledRealTimeReopenThread.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestControlledRealTimeReopenThread.java @@ -219,7 +219,7 @@ public class TestControlledRealTimeReopenThread extends ThreadedIndexingAndSearc final SearcherFactory sf = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader r) throws IOException { + public IndexSearcher newSearcher(IndexReader r, IndexReader previous) throws IOException { TestControlledRealTimeReopenThread.this.warmCalled = true; IndexSearcher s = new IndexSearcher(r, es); s.search(new TermQuery(new Term("body", "united")), 10); @@ -413,7 +413,7 @@ public class TestControlledRealTimeReopenThread extends ThreadedIndexingAndSearc final SearcherFactory theEvilOne = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader ignored) { + public IndexSearcher newSearcher(IndexReader ignored, IndexReader previous) { return LuceneTestCase.newSearcher(other); } }; 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 aff689306fc..52d56993013 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java @@ -83,7 +83,7 @@ public class TestLRUQueryCache extends LuceneTestCase { final RandomIndexWriter w = new RandomIndexWriter(random(), dir); final SearcherFactory searcherFactory = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader reader) throws IOException { + public IndexSearcher newSearcher(IndexReader reader, IndexReader previous) throws IOException { IndexSearcher searcher = new IndexSearcher(reader); searcher.setQueryCachingPolicy(MAYBE_CACHE_POLICY); searcher.setQueryCache(queryCache); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLiveFieldValues.java b/lucene/core/src/test/org/apache/lucene/search/TestLiveFieldValues.java index ee8aefc9904..982d0a0b5f9 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestLiveFieldValues.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestLiveFieldValues.java @@ -51,7 +51,7 @@ public class TestLiveFieldValues extends LuceneTestCase { final SearcherManager mgr = new SearcherManager(w, true, new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader r) { + public IndexSearcher newSearcher(IndexReader r, IndexReader previous) { return new IndexSearcher(r); } }); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java b/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java index 4f857e31128..05b25a4560d 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java @@ -78,7 +78,7 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase { protected void doAfterWriter(final ExecutorService es) throws Exception { final SearcherFactory factory = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader r) throws IOException { + public IndexSearcher newSearcher(IndexReader r, IndexReader previous) throws IOException { IndexSearcher s = new IndexSearcher(r, es); TestSearcherManager.this.warmCalled = true; s.search(new TermQuery(new Term("body", "united")), 10); @@ -217,7 +217,7 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase { final ExecutorService es = random().nextBoolean() ? null : Executors.newCachedThreadPool(new NamedThreadFactory("testIntermediateClose")); final SearcherFactory factory = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader r) { + public IndexSearcher newSearcher(IndexReader r, IndexReader previous) { try { if (triedReopen.get()) { awaitEnterWarm.countDown(); @@ -400,7 +400,7 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase { final SearcherFactory theEvilOne = new SearcherFactory() { @Override - public IndexSearcher newSearcher(IndexReader ignored) { + public IndexSearcher newSearcher(IndexReader ignored, IndexReader previous) { return LuceneTestCase.newSearcher(other); } }; @@ -503,4 +503,47 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase { w.close(); dir.close(); } + + public void testPreviousReaderIsPassed() throws IOException { + final Directory dir = newDirectory(); + final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig()); + w.addDocument(new Document()); + class MySearcherFactory extends SearcherFactory { + IndexReader lastReader = null; + IndexReader lastPreviousReader = null; + int called = 0; + @Override + public IndexSearcher newSearcher(IndexReader reader, IndexReader previousReader) throws IOException { + called++; + lastReader = reader; + lastPreviousReader = previousReader; + return super.newSearcher(reader, previousReader); + } + } + + MySearcherFactory factory = new MySearcherFactory(); + final SearcherManager sm = new SearcherManager(w, random().nextBoolean(), factory); + assertEquals(1, factory.called); + assertNull(factory.lastPreviousReader); + assertNotNull(factory.lastReader); + IndexSearcher acquire = sm.acquire(); + assertSame(factory.lastReader, acquire.getIndexReader()); + sm.release(acquire); + + final IndexReader lastReader = factory.lastReader; + // refresh + w.addDocument(new Document()); + assertTrue(sm.maybeRefresh()); + + acquire = sm.acquire(); + assertSame(factory.lastReader, acquire.getIndexReader()); + sm.release(acquire); + assertNotNull(factory.lastPreviousReader); + assertSame(lastReader, factory.lastPreviousReader); + assertNotSame(factory.lastReader, lastReader); + assertEquals(2, factory.called); + w.close(); + sm.close(); + dir.close(); + } } diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/SearcherTaxonomyManager.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/SearcherTaxonomyManager.java index 561c2b19a5b..a9fc7480b27 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/SearcherTaxonomyManager.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/SearcherTaxonomyManager.java @@ -70,7 +70,7 @@ public class SearcherTaxonomyManager extends ReferenceManager