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