Index: lucene/src/test/org/apache/lucene/search/TestNRTManager.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestNRTManager.java (revision 1210719)
+++ lucene/src/test/org/apache/lucene/search/TestNRTManager.java (working copy)
@@ -28,6 +28,7 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
@@ -205,7 +206,14 @@
TestNRTManager.this.warmCalled = true;
s.search(new TermQuery(new Term("body", "united")), 10);
}
- }, false);
+ },
+ new IndexWriter.IndexReaderWarmer() {
+ @Override
+ public void warm(IndexReader r) throws IOException {
+ TestNRTManager.this.warmCalled = true;
+ }
+ },
+ false);
nrtThread = new NRTManagerReopenThread(nrt, maxReopenSec, minReopenSec);
nrtThread.setName("NRT Reopen Thread");
@@ -267,7 +275,7 @@
final CountDownLatch signal = new CountDownLatch(1);
LatchedIndexWriter writer = new LatchedIndexWriter(d, conf, latch, signal);
- final NRTManager manager = new NRTManager(writer, null, null, false);
+ final NRTManager manager = new NRTManager(writer, null, null, null, false);
Document doc = new Document();
doc.add(newField("test","test", TextField.TYPE_STORED));
long gen = manager.addDocument(doc);
Index: lucene/src/test/org/apache/lucene/search/TestSearcherManager.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSearcherManager.java (revision 1210719)
+++ lucene/src/test/org/apache/lucene/search/TestSearcherManager.java (working copy)
@@ -29,7 +29,9 @@
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.ConcurrentMergeScheduler;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriter.IndexReaderWarmer;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
import org.apache.lucene.store.AlreadyClosedException;
@@ -73,11 +75,17 @@
s.search(new TermQuery(new Term("body", "united")), 10);
}
};
+ final IndexReaderWarmer readerWarmer = new IndexReaderWarmer() {
+ @Override
+ public void warm(IndexReader r) throws IOException {
+ TestSearcherManager.this.warmCalled = true;
+ }
+ };
if (random.nextBoolean()) {
// TODO: can we randomize the applyAllDeletes? But
// somehow for final searcher we must apply
// deletes...
- mgr = new SearcherManager(writer, true, warmer, es);
+ mgr = new SearcherManager(writer, true, warmer, readerWarmer, es);
isNRT = true;
} else {
// SearcherManager needs to see empty commit:
@@ -204,7 +212,7 @@
}
};
final SearcherManager searcherManager = random.nextBoolean() ? new SearcherManager(dir,
- warmer, es) : new SearcherManager(writer, random.nextBoolean(), warmer, es);
+ warmer, es) : new SearcherManager(writer, random.nextBoolean(), warmer, null, es);
IndexSearcher searcher = searcherManager.acquire();
try {
assertEquals(1, searcher.getIndexReader().numDocs());
Index: lucene/src/java/org/apache/lucene/search/SearcherManager.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/SearcherManager.java (revision 1210719)
+++ lucene/src/java/org/apache/lucene/search/SearcherManager.java (working copy)
@@ -24,6 +24,7 @@
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriter.IndexReaderWarmer;
import org.apache.lucene.search.NRTManager; // javadocs
import org.apache.lucene.search.IndexSearcher; // javadocs
import org.apache.lucene.store.AlreadyClosedException;
@@ -81,10 +82,11 @@
* Applying deletes can be costly, so if your app can tolerate deleted documents
* being returned you might gain some performance by passing false.
* See {@link IndexReader#openIfChanged(IndexReader, IndexWriter, boolean)}.
- * @param warmer An optional {@link SearcherWarmer}. Pass
+ * @param searcherWarmer An optional {@link SearcherWarmer}. Pass
* null if you don't require the searcher to warmed
- * before going live. If this is non-null then a
- * merged segment warmer is installed on the
+ * before going live.
+ * @param mergedSegmentWarmer An optional {@link IndexReaderWarmer}. If this is
+ * non-null then a merged segment warmer is installed on the
* provided IndexWriter's config.
* @param es An optional {@link ExecutorService} so different segments can
* be searched concurrently (see {@link
@@ -94,19 +96,17 @@
* @throws IOException
*/
public SearcherManager(IndexWriter writer, boolean applyAllDeletes,
- final SearcherWarmer warmer, final ExecutorService es) throws IOException {
+ SearcherWarmer searcherWarmer, IndexReaderWarmer mergedSegmentWarmer,
+ ExecutorService es) throws IOException {
this.es = es;
- this.warmer = warmer;
+ this.warmer = searcherWarmer;
currentSearcher = new IndexSearcher(IndexReader.open(writer, applyAllDeletes));
if (warmer != null) {
- writer.getConfig().setMergedSegmentWarmer(
- new IndexWriter.IndexReaderWarmer() {
- @Override
- public void warm(IndexReader reader) throws IOException {
- warmer.warm(new IndexSearcher(reader, es));
- }
- });
+ warmer.warm(currentSearcher);
}
+ if (mergedSegmentWarmer != null) {
+ writer.getConfig().setMergedSegmentWarmer(mergedSegmentWarmer);
+ }
}
/**
@@ -114,9 +114,7 @@
* @param dir the directory to open the IndexReader on.
* @param warmer An optional {@link SearcherWarmer}. Pass
* null if you don't require the searcher to warmed
- * before going live. If this is non-null then a
- * merged segment warmer is installed on the
- * provided IndexWriter's config.
+ * before going live.
* @param es And optional {@link ExecutorService} so different segments can
* be searched concurrently (see {@link
* IndexSearcher#IndexSearcher(IndexReader,ExecutorService)}. Pass null
@@ -129,6 +127,9 @@
this.es = es;
this.warmer = warmer;
currentSearcher = new IndexSearcher(IndexReader.open(dir, true), es);
+ if (warmer != null) {
+ warmer.warm(currentSearcher);
+ }
}
/**
Index: lucene/src/java/org/apache/lucene/search/IndexSearcher.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/IndexSearcher.java (revision 1210719)
+++ lucene/src/java/org/apache/lucene/search/IndexSearcher.java (working copy)
@@ -789,33 +789,65 @@
return "IndexSearcher(" + reader + "; executor=" + executor + ")";
}
+ /**
+ * Provides all scoring statistics to queries
+ * @lucene.experimental
+ */
+ public static abstract class StatsProvider {
+ /**
+ * Returns {@link TermStatistics} for a term
+ */
+ public abstract TermStatistics termStatistics(Term term, TermContext context) throws IOException;
+ /**
+ * Returns {@link CollectionStatistics} for a field
+ */
+ public abstract CollectionStatistics collectionStatistics(String field) throws IOException;
+ }
+
+ // default "local" implementation
+ private StatsProvider statsProvider = new StatsProvider() {
+ @Override
+ public TermStatistics termStatistics(Term term, TermContext context) throws IOException {
+ return new TermStatistics(term.bytes(), context.docFreq(), context.totalTermFreq());
+ };
+
+ @Override
+ public CollectionStatistics collectionStatistics(String field) throws IOException {
+ final int docCount;
+ final long sumTotalTermFreq;
+ final long sumDocFreq;
+
+ Terms terms = MultiFields.getTerms(reader, field);
+ if (terms == null) {
+ docCount = 0;
+ sumTotalTermFreq = 0;
+ sumDocFreq = 0;
+ } else {
+ docCount = terms.getDocCount();
+ sumTotalTermFreq = terms.getSumTotalTermFreq();
+ sumDocFreq = terms.getSumDocFreq();
+ }
+ return new CollectionStatistics(field, reader.maxDoc(), docCount, sumTotalTermFreq, sumDocFreq);
+ }
+ };
+
+ public void setStatsProvider(StatsProvider statsProvider) {
+ this.statsProvider = statsProvider;
+ }
+
/**
* Returns {@link TermStatistics} for a term
* @lucene.experimental
*/
- public TermStatistics termStatistics(Term term, TermContext context) throws IOException {
- return new TermStatistics(term.bytes(), context.docFreq(), context.totalTermFreq());
- };
-
+ public final TermStatistics termStatistics(Term term, TermContext context) throws IOException {
+ return statsProvider.termStatistics(term, context);
+ }
+
/**
* Returns {@link CollectionStatistics} for a field
* @lucene.experimental
*/
- public CollectionStatistics collectionStatistics(String field) throws IOException {
- final int docCount;
- final long sumTotalTermFreq;
- final long sumDocFreq;
-
- Terms terms = MultiFields.getTerms(reader, field);
- if (terms == null) {
- docCount = 0;
- sumTotalTermFreq = 0;
- sumDocFreq = 0;
- } else {
- docCount = terms.getDocCount();
- sumTotalTermFreq = terms.getSumTotalTermFreq();
- sumDocFreq = terms.getSumDocFreq();
- }
- return new CollectionStatistics(field, reader.maxDoc(), docCount, sumTotalTermFreq, sumDocFreq);
+ public final CollectionStatistics collectionStatistics(String field) throws IOException {
+ return statsProvider.collectionStatistics(field);
}
}
Index: lucene/src/java/org/apache/lucene/search/NRTManager.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/NRTManager.java (revision 1210719)
+++ lucene/src/java/org/apache/lucene/search/NRTManager.java (working copy)
@@ -31,6 +31,7 @@
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader; // javadocs
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriter.IndexReaderWarmer;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher; // javadocs
@@ -67,18 +68,16 @@
*
* @param writer IndexWriter to open near-real-time
* readers
- * @param warmer optional {@link SearcherWarmer}. Pass
+ * @param searcherWarmer optional {@link SearcherWarmer}. Pass
* null if you don't require the searcher to warmed
- * before going live. If this is non-null then a
- * merged segment warmer is installed on the
- * provided IndexWriter's config.
- *
- *
NOTE: the provided {@link SearcherWarmer} is
- * not invoked for the initial searcher; you should
- * warm it yourself if necessary.
+ * before going live.
+ * @param mergedSegmentWarmer optional {@link IndexReaderWarmer}.
+ * If this is non-null then a merged segment warmer is
+ * installed on the provided IndexWriter's config.
*/
- public NRTManager(IndexWriter writer, SearcherWarmer warmer) throws IOException {
- this(writer, null, warmer, true);
+ public NRTManager(IndexWriter writer, SearcherWarmer searcherWarmer,
+ IndexReaderWarmer mergedSegmentWarmer) throws IOException {
+ this(writer, null, searcherWarmer, mergedSegmentWarmer, true);
}
/**
@@ -89,36 +88,37 @@
* @param es optional ExecutorService so different segments can
* be searched concurrently (see {@link IndexSearcher#IndexSearcher(IndexReader, ExecutorService)}.
* Pass null to search segments sequentially.
- * @param warmer optional {@link SearcherWarmer}. Pass
+ * @param searcherWarmer optional {@link SearcherWarmer}. Pass
* null if you don't require the searcher to warmed
- * before going live. If this is non-null then a
- * merged segment warmer is installed on the
+ * before going live.
+ * @param mergedSegmentWarmer optional {@link IndexReaderWarmer}. If this
+ * is non-null then a merged segment warmer is installed on the
* provided IndexWriter's config.
- *
- *
NOTE: the provided {@link SearcherWarmer} is - * not invoked for the initial searcher; you should - * warm it yourself if necessary. */ public NRTManager(IndexWriter writer, ExecutorService es, - SearcherWarmer warmer) throws IOException { - this(writer, es, warmer, true); + SearcherWarmer searcherWarmer, IndexReaderWarmer mergedSegmentWarmer) throws IOException { + this(writer, es, searcherWarmer, mergedSegmentWarmer, true); } /** * Expert: just like {@link - * #NRTManager(IndexWriter,ExecutorService,SearcherWarmer)}, + * #NRTManager(IndexWriter, ExecutorService, SearcherWarmer, IndexWriter.IndexReaderWarmer)}, * but you can also specify whether every searcher must * apply deletes. This is useful for cases where certain * uses can tolerate seeing some deleted docs, since * reopen time is faster if deletes need not be applied. */ public NRTManager(IndexWriter writer, ExecutorService es, - SearcherWarmer warmer, boolean alwaysApplyDeletes) throws IOException { + SearcherWarmer searcherWarmer, IndexReaderWarmer mergedSegmentWarmer, + boolean alwaysApplyDeletes) throws IOException { this.writer = writer; if (alwaysApplyDeletes) { - withoutDeletes = withDeletes = new SearcherManagerRef(true, 0, new SearcherManager(writer, true, warmer, es)); + withoutDeletes = withDeletes = new SearcherManagerRef(true, 0, + new SearcherManager(writer, true, searcherWarmer, mergedSegmentWarmer, es)); } else { - withDeletes = new SearcherManagerRef(true, 0, new SearcherManager(writer, true, warmer, es)); - withoutDeletes = new SearcherManagerRef(false, 0, new SearcherManager(writer, false, warmer, es)); + withDeletes = new SearcherManagerRef(true, 0, + new SearcherManager(writer, true, searcherWarmer, mergedSegmentWarmer, es)); + withoutDeletes = new SearcherManagerRef(false, 0, + new SearcherManager(writer, false, searcherWarmer, mergedSegmentWarmer, es)); } indexingGen = new AtomicLong(1); }