Index: lucene/src/test/org/apache/lucene/search/TestSearcherManager.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSearcherManager.java (revision 1213001)
+++ lucene/src/test/org/apache/lucene/search/TestSearcherManager.java (working copy)
@@ -29,14 +29,17 @@
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.Term;
import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
+import org.apache.lucene.search.SearcherManager.SearcherFactory;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase.UseNoMemoryExpensiveCodec;
import org.apache.lucene.util.NamedThreadFactory;
import org.apache.lucene.util._TestUtil;
+import org.junit.Ignore;
@UseNoMemoryExpensiveCodec
public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase {
@@ -65,24 +68,26 @@
private boolean isNRT;
@Override
- protected void doAfterWriter(ExecutorService es) throws Exception {
- final SearcherWarmer warmer = new SearcherWarmer() {
+ protected void doAfterWriter(final ExecutorService es) throws Exception {
+ final SearcherFactory factory = new SearcherFactory() {
@Override
- public void warm(IndexSearcher s) throws IOException {
+ public IndexSearcher newSearcher(IndexReader r) throws IOException {
+ IndexSearcher s = new IndexSearcher(r, es);
TestSearcherManager.this.warmCalled = true;
s.search(new TermQuery(new Term("body", "united")), 10);
+ return s;
}
};
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, factory);
isNRT = true;
} else {
// SearcherManager needs to see empty commit:
writer.commit();
- mgr = new SearcherManager(dir, warmer, es);
+ mgr = new SearcherManager(dir, factory);
isNRT = false;
}
@@ -191,20 +196,26 @@
writer.commit();
final CountDownLatch awaitEnterWarm = new CountDownLatch(1);
final CountDownLatch awaitClose = new CountDownLatch(1);
+ final AtomicBoolean triedReopen = new AtomicBoolean(false);
final ExecutorService es = random.nextBoolean() ? null : Executors.newCachedThreadPool(new NamedThreadFactory("testIntermediateClose"));
- final SearcherWarmer warmer = new SearcherWarmer() {
+ final SearcherFactory factory = new SearcherFactory() {
@Override
- public void warm(IndexSearcher s) throws IOException {
+ public IndexSearcher newSearcher(IndexReader r) throws IOException {
try {
- awaitEnterWarm.countDown();
- awaitClose.await();
+ if (triedReopen.get()) {
+ awaitEnterWarm.countDown();
+ awaitClose.await();
+ }
} catch (InterruptedException e) {
//
}
+ return new IndexSearcher(r, es);
}
};
- final SearcherManager searcherManager = random.nextBoolean() ? new SearcherManager(dir,
- warmer, es) : new SearcherManager(writer, random.nextBoolean(), warmer, es);
+ final SearcherManager searcherManager = random.nextBoolean()
+ ? new SearcherManager(dir, factory)
+ : new SearcherManager(writer, random.nextBoolean(), factory);
+ System.out.println("sm created");
IndexSearcher searcher = searcherManager.acquire();
try {
assertEquals(1, searcher.getIndexReader().numDocs());
@@ -214,13 +225,13 @@
writer.addDocument(new Document());
writer.commit();
final AtomicBoolean success = new AtomicBoolean(false);
- final AtomicBoolean triedReopen = new AtomicBoolean(false);
final Throwable[] exc = new Throwable[1];
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
triedReopen.set(true);
+ System.out.println("NOW call maybeReopen");
searcherManager.maybeReopen();
success.set(true);
} catch (AlreadyClosedException e) {
@@ -236,7 +247,9 @@
}
});
thread.start();
+ System.out.println("THREAD started");
awaitEnterWarm.await();
+ System.out.println("NOW call close");
searcherManager.close();
awaitClose.countDown();
thread.join();
Index: lucene/src/test/org/apache/lucene/search/TestNRTManager.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestNRTManager.java (revision 1213001)
+++ lucene/src/test/org/apache/lucene/search/TestNRTManager.java (working copy)
@@ -28,12 +28,14 @@
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;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
import org.apache.lucene.search.NRTManagerReopenThread;
+import org.apache.lucene.search.SearcherManager.SearcherFactory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.NRTCachingDirectory;
@@ -190,7 +192,7 @@
private NRTManager nrt;
private NRTManagerReopenThread nrtThread;
@Override
- protected void doAfterWriter(ExecutorService es) throws Exception {
+ protected void doAfterWriter(final ExecutorService es) throws Exception {
final double minReopenSec = 0.01 + 0.05 * random.nextDouble();
final double maxReopenSec = minReopenSec * (1.0 + 10 * random.nextDouble());
@@ -198,14 +200,16 @@
System.out.println("TEST: make NRTManager maxReopenSec=" + maxReopenSec + " minReopenSec=" + minReopenSec);
}
- nrt = new NRTManager(writer, es,
- new SearcherWarmer() {
- @Override
- public void warm(IndexSearcher s) throws IOException {
- TestNRTManager.this.warmCalled = true;
- s.search(new TermQuery(new Term("body", "united")), 10);
- }
- }, false);
+ nrt = new NRTManager(writer,
+ new SearcherFactory() {
+ @Override
+ public IndexSearcher newSearcher(IndexReader r) throws IOException {
+ TestNRTManager.this.warmCalled = true;
+ IndexSearcher s = new IndexSearcher(r, es);
+ s.search(new TermQuery(new Term("body", "united")), 10);
+ return s;
+ }
+ }, false);
nrtThread = new NRTManagerReopenThread(nrt, maxReopenSec, minReopenSec);
nrtThread.setName("NRT Reopen Thread");
@@ -267,7 +271,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, false);
Document doc = new Document();
doc.add(newField("test","test", TextField.TYPE_STORED));
long gen = manager.addDocument(doc);
Index: lucene/src/java/org/apache/lucene/search/SearcherWarmer.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/SearcherWarmer.java (revision 1213001)
+++ lucene/src/java/org/apache/lucene/search/SearcherWarmer.java (working copy)
@@ -1,34 +0,0 @@
-package org.apache.lucene.search;
-
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.IOException;
-
-import org.apache.lucene.search.NRTManager; // javadocs
-
-/** Pass an implementation of this to {@link NRTManager} or
- * {@link SearcherManager} to warm a new {@link
- * IndexSearcher} before it's put into production.
- *
- * @lucene.experimental */
-
-public interface SearcherWarmer {
- // TODO: can we somehow merge this w/ IW's
- // IndexReaderWarmer.... should IW switch to this?
- public void warm(IndexSearcher s) throws IOException;
-}
Index: lucene/src/java/org/apache/lucene/search/SearcherManager.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/SearcherManager.java (revision 1213001)
+++ lucene/src/java/org/apache/lucene/search/SearcherManager.java (working copy)
@@ -18,7 +18,6 @@
*/
import java.io.IOException;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import org.apache.lucene.index.CorruptIndexException;
@@ -67,8 +66,7 @@
public final class SearcherManager {
private volatile IndexSearcher currentSearcher;
- private final ExecutorService es;
- private final SearcherWarmer warmer;
+ private final SearcherFactory searcherFactory;
private final Semaphore reopenLock = new Semaphore(1);
/**
@@ -81,54 +79,35 @@
* 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
- * 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.
- * @param es An optional {@link ExecutorService} so different segments can
- * be searched concurrently (see {@link
- * IndexSearcher#IndexSearcher(IndexReader,ExecutorService)}. Pass null
- * to search segments sequentially.
+ * @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
*/
- public SearcherManager(IndexWriter writer, boolean applyAllDeletes,
- final SearcherWarmer warmer, final ExecutorService es) throws IOException {
- this.es = es;
- this.warmer = warmer;
- 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));
- }
- });
+ public SearcherManager(IndexWriter writer, boolean applyAllDeletes, SearcherFactory searcherFactory) throws IOException {
+ if (searcherFactory == null) {
+ searcherFactory = new SearcherFactory();
}
+ this.searcherFactory = searcherFactory;
+ currentSearcher = searcherFactory.newSearcher(IndexReader.open(writer, applyAllDeletes));
}
/**
* Creates and returns a new SearcherManager from the given {@link Directory}.
* @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.
- * @param es And optional {@link ExecutorService} so different segments can
- * be searched concurrently (see {@link
- * IndexSearcher#IndexSearcher(IndexReader,ExecutorService)}. Pass null
- * to search segments sequentially.
+ * @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
*/
- public SearcherManager(Directory dir, SearcherWarmer warmer,
- ExecutorService es) throws IOException {
- this.es = es;
- this.warmer = warmer;
- currentSearcher = new IndexSearcher(IndexReader.open(dir), es);
+ public SearcherManager(Directory dir, SearcherFactory searcherFactory) throws IOException {
+ if (searcherFactory == null) {
+ searcherFactory = new SearcherFactory();
+ }
+ this.searcherFactory = searcherFactory;
+ currentSearcher = searcherFactory.newSearcher(IndexReader.open(dir));
}
/**
@@ -167,12 +146,9 @@
release(searcherToReopen);
}
if (newReader != null) {
- final IndexSearcher newSearcher = new IndexSearcher(newReader, es);
+ final IndexSearcher newSearcher = searcherFactory.newSearcher(newReader);
boolean success = false;
try {
- if (warmer != null) {
- warmer.warm(newSearcher);
- }
swapSearcher(newSearcher);
success = true;
} finally {
@@ -260,5 +236,10 @@
currentSearcher = newSearcher;
release(oldSearcher);
}
-
+
+ public static class SearcherFactory {
+ public IndexSearcher newSearcher(IndexReader r) throws IOException {
+ return new IndexSearcher(r);
+ }
+ }
}
Index: lucene/src/java/org/apache/lucene/search/NRTManager.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/NRTManager.java (revision 1213001)
+++ lucene/src/java/org/apache/lucene/search/NRTManager.java (working copy)
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
@@ -34,6 +33,7 @@
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher; // javadocs
+import org.apache.lucene.search.SearcherManager.SearcherFactory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.ThreadInterruptedException;
@@ -65,60 +65,30 @@
/**
* Create new NRTManager.
*
- * @param writer IndexWriter to open near-real-time
- * readers
- * @param warmer 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.
+ * @param writer IndexWriter to open near-real-time
+ * readers
+ * @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.
*/
- public NRTManager(IndexWriter writer, SearcherWarmer warmer) throws IOException {
- this(writer, null, warmer, true);
+ public NRTManager(IndexWriter writer, SearcherFactory searcherFactory) throws IOException {
+ this(writer, searcherFactory, true);
}
/**
- * Create new NRTManager.
- *
- * @param writer IndexWriter to open near-real-time
- * readers
- * @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
- * 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. - */ - public NRTManager(IndexWriter writer, ExecutorService es, - SearcherWarmer warmer) throws IOException { - this(writer, es, warmer, true); - } - - /** * Expert: just like {@link - * #NRTManager(IndexWriter,ExecutorService,SearcherWarmer)}, + * #NRTManager(IndexWriter,SearcherWarmer)}, * 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 { + public NRTManager(IndexWriter writer, SearcherFactory searcherFactory, 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, searcherFactory)); } 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, searcherFactory)); + withoutDeletes = new SearcherManagerRef(false, 0, new SearcherManager(writer, false, searcherFactory)); } indexingGen = new AtomicLong(1); }