diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 255ee918f94..3992b2c96fa 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -233,6 +233,9 @@ API Changes resourceDescription so its toString is sane (Robert Muir, Mike McCandless) +* LUCENE-6087: Allow passing custom DirectoryReader to SearcherManager + (Mike McCandless) + Bug Fixes * LUCENE-5650: Enforce read-only access to any path outside the temporary 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 7305e512cea..fa46e6852f1 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java +++ b/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java @@ -106,6 +106,25 @@ public final class SearcherManager extends ReferenceManager { current = getSearcher(searcherFactory, DirectoryReader.open(dir)); } + /** + * Creates and returns a new SearcherManager from an existing {@link DirectoryReader}. Note that + * this steals the incoming reference. + * + * @param reader the DirectoryReader. + * @param searcherFactory An optional {@link SearcherFactory}. Pass + * null if you don't require the searcher to be warmed + * before going live or other custom behavior. + * + * @throws IOException if there is a low-level I/O error + */ + public SearcherManager(DirectoryReader reader, SearcherFactory searcherFactory) throws IOException { + if (searcherFactory == null) { + searcherFactory = new SearcherFactory(); + } + this.searcherFactory = searcherFactory; + this.current = getSearcher(searcherFactory, reader); + } + @Override protected void decRef(IndexSearcher reference) throws IOException { reference.getIndexReader().decRef(); 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 58d49d206f5..642f73a7f7b 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java @@ -31,16 +31,20 @@ import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.ConcurrentMergeScheduler; import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.FilterDirectoryReader; +import org.apache.lucene.index.FilterLeafReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.LeafReader; +import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.RandomIndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase; import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.store.Directory; -import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase.SuppressCodecs; +import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.NamedThreadFactory; import org.apache.lucene.util.TestUtil; @@ -445,5 +449,51 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase { sm.close(); dir.close(); } - + + private static class MyFilterLeafReader extends FilterLeafReader { + public MyFilterLeafReader(LeafReader in) { + super(in); + } + } + + private static class MyFilterDirectoryReader extends FilterDirectoryReader { + public MyFilterDirectoryReader(DirectoryReader in) { + super(in, + new FilterDirectoryReader.SubReaderWrapper() { + @Override + public LeafReader wrap(LeafReader reader) { + return new MyFilterLeafReader(reader); + } + }); + } + + @Override + protected DirectoryReader doWrapDirectoryReader(DirectoryReader in) { + return new MyFilterDirectoryReader(in); + } + } + + // LUCENE-6087 + public void testCustomDirectoryReader() throws Exception { + Directory dir = newDirectory(); + RandomIndexWriter w = new RandomIndexWriter(random(), dir); + DirectoryReader reader = new MyFilterDirectoryReader(w.getReader()); + SearcherManager mgr = new SearcherManager(reader, null); + for(int i=0;i<10;i++) { + w.addDocument(new Document()); + mgr.maybeRefresh(); + IndexSearcher s = mgr.acquire(); + try { + assertTrue(s.getIndexReader() instanceof MyFilterDirectoryReader); + for (LeafReaderContext ctx : s.getIndexReader().leaves()) { + assertTrue(ctx.reader() instanceof MyFilterLeafReader); + } + } finally { + mgr.release(s); + } + } + mgr.close(); + w.close(); + dir.close(); + } }