You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2012/02/17 20:08:51 UTC
svn commit: r1245710 - in /lucene/dev/trunk/lucene: ./
core/src/java/org/apache/lucene/search/
core/src/test/org/apache/lucene/search/
Author: mikemccand
Date: Fri Feb 17 19:08:51 2012
New Revision: 1245710
URL: http://svn.apache.org/viewvc?rev=1245710&view=rev
Log:
LUCENE-3776: now you acquire/release directly from NRTManager (fixes trap)
Modified:
lucene/dev/trunk/lucene/CHANGES.txt
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManagerReopenThread.java
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java
lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Fri Feb 17 19:08:51 2012
@@ -815,6 +815,10 @@ API Changes
create two NRTManagers (one always applying deletes and the other
never applying deletes). (MJB, Shai Erera, Mike McCandless)
+* LUCENE-3776: You now acquire/release the IndexSearcher directly from
+ NRTManager. (Mike McCandless)
+
+
New Features
* LUCENE-3593: Added a FieldValueFilter that accepts all documents that either
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManager.java Fri Feb 17 19:08:51 2012
@@ -17,7 +17,6 @@ package org.apache.lucene.search;
* limitations under the License.
*/
-import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -28,6 +27,7 @@ import java.util.concurrent.locks.Reentr
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader; // javadocs
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexableField;
@@ -71,14 +71,14 @@ import org.apache.lucene.util.ThreadInte
* @lucene.experimental
*/
-public class NRTManager implements Closeable {
+public class NRTManager extends ReferenceManager<IndexSearcher> {
private static final long MAX_SEARCHER_GEN = Long.MAX_VALUE;
private final TrackingIndexWriter writer;
private final List<WaitingListener> waitingListeners = new CopyOnWriteArrayList<WaitingListener>();
- private final ReentrantLock reopenLock = new ReentrantLock();
- private final Condition newGeneration = reopenLock.newCondition();
+ private final ReentrantLock genLock = new ReentrantLock();;
+ private final Condition newGeneration = genLock.newCondition();
+ private final SearcherFactory searcherFactory;
- private final SearcherManager mgr;
private volatile long searchingGen;
/**
@@ -101,24 +101,25 @@ public class NRTManager implements Close
* 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(TrackingIndexWriter writer, SearcherFactory searcherFactory, boolean applyDeletes) throws IOException {
+ public NRTManager(TrackingIndexWriter writer, SearcherFactory searcherFactory, boolean applyAllDeletes) throws IOException {
this.writer = writer;
- mgr = new SearcherManager(writer.getIndexWriter(), applyDeletes, searcherFactory);
+ if (searcherFactory == null) {
+ searcherFactory = new SearcherFactory();
+ }
+ this.searcherFactory = searcherFactory;
+ current = SearcherManager.getSearcher(searcherFactory, DirectoryReader.open(writer.getIndexWriter(), applyAllDeletes));
}
- /**
- * Returns the {@link SearcherManager} you should use to
- * acquire/release searchers.
- *
- * <p><b>NOTE</b>: Never call maybeReopen on the returned
- * SearcherManager; only call this NRTManager's {@link
- * #maybeReopen}. Otherwise threads waiting for a
- * generation may never return.
- */
- public SearcherManager getSearcherManager() {
- return mgr;
+ @Override
+ protected void decRef(IndexSearcher reference) throws IOException {
+ reference.getIndexReader().decRef();
}
+ @Override
+ protected boolean tryIncRef(IndexSearcher reference) {
+ return reference.getIndexReader().tryIncRef();
+ }
+
/** NRTManager invokes this interface to notify it when a
* caller is waiting for a specific generation searcher
* to be visible. */
@@ -296,7 +297,7 @@ public class NRTManager implements Close
if (targetGen > curGen) {
throw new IllegalArgumentException("targetGen=" + targetGen + " was never returned by this NRTManager instance (current gen=" + curGen + ")");
}
- reopenLock.lockInterruptibly();
+ genLock.lockInterruptibly();
try {
if (targetGen > searchingGen) {
for (WaitingListener listener : waitingListeners) {
@@ -309,7 +310,7 @@ public class NRTManager implements Close
}
}
} finally {
- reopenLock.unlock();
+ genLock.unlock();
}
} catch (InterruptedException ie) {
throw new ThreadInterruptedException(ie);
@@ -318,7 +319,7 @@ public class NRTManager implements Close
private boolean waitOnGenCondition(long time, TimeUnit unit)
throws InterruptedException {
- assert reopenLock.isHeldByCurrentThread();
+ assert genLock.isHeldByCurrentThread();
if (time < 0) {
newGeneration.await();
return true;
@@ -332,51 +333,67 @@ public class NRTManager implements Close
return searchingGen;
}
- public void maybeReopen() throws IOException {
- if (reopenLock.tryLock()) {
- try {
- // Mark gen as of when reopen started:
- final long newSearcherGen = writer.getAndIncrementGeneration();
- if (searchingGen == MAX_SEARCHER_GEN) {
- newGeneration.signalAll(); // wake up threads if we have a new generation
- return;
- }
- boolean setSearchGen;
- if (!mgr.isSearcherCurrent()) {
- setSearchGen = mgr.maybeRefresh();
- } else {
- setSearchGen = true;
- }
- if (setSearchGen) {
- searchingGen = newSearcherGen;// update searcher gen
- newGeneration.signalAll(); // wake up threads if we have a new generation
- }
- } finally {
- reopenLock.unlock();
+ private long lastRefreshGen;
+
+ @Override
+ protected IndexSearcher refreshIfNeeded(IndexSearcher referenceToRefresh) throws IOException {
+ // Record gen as of when reopen started:
+ lastRefreshGen = writer.getAndIncrementGeneration();
+ final IndexReader r = referenceToRefresh.getIndexReader();
+ assert r instanceof DirectoryReader: "searcher's IndexReader should be a DirectoryReader, but got " + r;
+ final DirectoryReader dirReader = (DirectoryReader) r;
+ IndexSearcher newSearcher = null;
+ if (!dirReader.isCurrent()) {
+ final IndexReader newReader = DirectoryReader.openIfChanged(dirReader);
+ if (newReader != null) {
+ newSearcher = SearcherManager.getSearcher(searcherFactory, newReader);
+ }
+ }
+
+ return newSearcher;
+ }
+
+ @Override
+ protected void afterRefresh() {
+ genLock.lock();
+ try {
+ if (searchingGen != MAX_SEARCHER_GEN) {
+ // update searchingGen:
+ assert lastRefreshGen >= searchingGen;
+ searchingGen = lastRefreshGen;
}
+ // wake up threads if we have a new generation:
+ newGeneration.signalAll();
+ } finally {
+ genLock.unlock();
+ }
+ }
+
+ @Override
+ protected synchronized void afterClose() throws IOException {
+ genLock.lock();
+ try {
+ // max it out to make sure nobody can wait on another gen
+ searchingGen = MAX_SEARCHER_GEN;
+ newGeneration.signalAll();
+ } finally {
+ genLock.unlock();
}
}
/**
- * Close this NRTManager to future searching. Any searches still in process in
- * other threads won't be affected, and they should still call
- * {@link SearcherManager#release} after they are done.
- *
- * <p>
- * <b>NOTE</b>: caller must separately close the writer.
+ * Returns <code>true</code> if no changes have occured since this searcher
+ * ie. reader was opened, otherwise <code>false</code>.
+ * @see DirectoryReader#isCurrent()
*/
- public void close() throws IOException {
- reopenLock.lock();
+ public boolean isSearcherCurrent() throws IOException {
+ final IndexSearcher searcher = acquire();
try {
- try {
- // max it out to make sure nobody can wait on another gen
- searchingGen = MAX_SEARCHER_GEN;
- mgr.close();
- } finally { // make sure we signal even if close throws an exception
- newGeneration.signalAll();
- }
+ final IndexReader r = searcher.getIndexReader();
+ assert r instanceof DirectoryReader: "searcher's IndexReader should be a DirectoryReader, but got " + r;
+ return ((DirectoryReader) r).isCurrent();
} finally {
- reopenLock.unlock();
+ release(searcher);
}
}
}
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManagerReopenThread.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManagerReopenThread.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManagerReopenThread.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/NRTManagerReopenThread.java Fri Feb 17 19:08:51 2012
@@ -181,7 +181,7 @@ public class NRTManagerReopenThread exte
lastReopenStartNS = System.nanoTime();
try {
//final long t0 = System.nanoTime();
- manager.maybeReopen();
+ manager.maybeRefresh();
//System.out.println("reopen took " + ((System.nanoTime()-t0)/1000000.0) + " msec");
} catch (IOException ioe) {
//System.out.println(Thread.currentThread().getName() + ": IOE");
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java Fri Feb 17 19:08:51 2012
@@ -56,7 +56,7 @@ public abstract class ReferenceManager<G
current = newReference;
release(oldReference);
}
-
+
/** Decrement reference counting on the given reference. */
protected abstract void decRef(G reference) throws IOException;
@@ -100,9 +100,14 @@ public abstract class ReferenceManager<G
// closeable javadoc says:
// if this is already closed then invoking this method has no effect.
swapReference(null);
+ afterClose();
}
}
+ /** Called after close(), so subclass can free any resources. */
+ protected void afterClose() throws IOException {
+ }
+
/**
* You must call this, periodically, if you want that {@link #acquire()} will
* return refreshed instances.
@@ -116,13 +121,16 @@ public abstract class ReferenceManager<G
* refresh to complete.
*
* <p>
- * This method returns true if the reference was in fact refreshed, or if the
- * current reference has no pending changes.
+ * If this method returns true it means the calling thread either refreshed
+ * or that there were no changes to refresh. If it returns false it means another
+ * thread is currently refreshing.
*/
public final boolean maybeRefresh() throws IOException {
ensureOpen();
+
// Ensure only 1 thread does reopen at once; other threads just return immediately:
- if (reopenLock.tryAcquire()) {
+ final boolean doTryRefresh = reopenLock.tryAcquire();
+ if (doTryRefresh) {
try {
final G reference = acquire();
try {
@@ -142,15 +150,20 @@ public abstract class ReferenceManager<G
} finally {
release(reference);
}
- return true;
+ afterRefresh();
} finally {
reopenLock.release();
}
- } else {
- return false;
}
+
+ return doTryRefresh;
}
+ /** Called after swapReference has installed a new
+ * instance. */
+ protected void afterRefresh() throws IOException {
+ }
+
/**
* Release the refernce previously obtained via {@link #acquire()}.
* <p>
@@ -160,5 +173,4 @@ public abstract class ReferenceManager<G
assert reference != null;
decRef(reference);
}
-
}
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java Fri Feb 17 19:08:51 2012
@@ -86,9 +86,26 @@ public final class SearcherManager exten
searcherFactory = new SearcherFactory();
}
this.searcherFactory = searcherFactory;
- current = searcherFactory.newSearcher(DirectoryReader.open(writer, applyAllDeletes));
+ current = getSearcher(searcherFactory, DirectoryReader.open(writer, applyAllDeletes));
}
+ /**
+ * Creates and returns a new SearcherManager from the given {@link Directory}.
+ * @param dir the directory to open the DirectoryReader on.
+ * @param searcherFactory An optional {@link SearcherFactory}. Pass
+ * <code>null</code> if you don't require the searcher to be warmed
+ * before going live or other custom behavior.
+ *
+ * @throws IOException
+ */
+ public SearcherManager(Directory dir, SearcherFactory searcherFactory) throws IOException {
+ if (searcherFactory == null) {
+ searcherFactory = new SearcherFactory();
+ }
+ this.searcherFactory = searcherFactory;
+ current = getSearcher(searcherFactory, DirectoryReader.open(dir));
+ }
+
@Override
protected void decRef(IndexSearcher reference) throws IOException {
reference.getIndexReader().decRef();
@@ -97,12 +114,12 @@ public final class SearcherManager exten
@Override
protected IndexSearcher refreshIfNeeded(IndexSearcher referenceToRefresh) throws IOException {
final IndexReader r = referenceToRefresh.getIndexReader();
- final IndexReader newReader = (r instanceof DirectoryReader) ?
- DirectoryReader.openIfChanged((DirectoryReader) r) : null;
+ assert r instanceof DirectoryReader: "searcher's IndexReader should be a DirectoryReader, but got " + r;
+ final IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader) r);
if (newReader == null) {
return null;
} else {
- return searcherFactory.newSearcher(newReader);
+ return getSearcher(searcherFactory, newReader);
}
}
@@ -112,23 +129,6 @@ public final class SearcherManager exten
}
/**
- * Creates and returns a new SearcherManager from the given {@link Directory}.
- * @param dir the directory to open the DirectoryReader on.
- * @param searcherFactory An optional {@link SearcherFactory}. Pass
- * <code>null</code> if you don't require the searcher to be warmed
- * before going live or other custom behavior.
- *
- * @throws IOException
- */
- public SearcherManager(Directory dir, SearcherFactory searcherFactory) throws IOException {
- if (searcherFactory == null) {
- searcherFactory = new SearcherFactory();
- }
- this.searcherFactory = searcherFactory;
- current = searcherFactory.newSearcher(DirectoryReader.open(dir));
- }
-
- /**
* Returns <code>true</code> if no changes have occured since this searcher
* ie. reader was opened, otherwise <code>false</code>.
* @see DirectoryReader#isCurrent()
@@ -137,12 +137,28 @@ public final class SearcherManager exten
final IndexSearcher searcher = acquire();
try {
final IndexReader r = searcher.getIndexReader();
- return r instanceof DirectoryReader ?
- ((DirectoryReader ) r).isCurrent() :
- true;
+ assert r instanceof DirectoryReader: "searcher's IndexReader should be a DirectoryReader, but got " + r;
+ return ((DirectoryReader) r).isCurrent();
} finally {
release(searcher);
}
}
-
+
+ // NOTE: decRefs incoming reader on throwing an exception
+ static IndexSearcher getSearcher(SearcherFactory searcherFactory, IndexReader reader) throws IOException {
+ boolean success = false;
+ final IndexSearcher searcher;
+ try {
+ searcher = searcherFactory.newSearcher(reader);
+ if (searcher.getIndexReader() != reader) {
+ throw new IllegalStateException("SearcherFactory must wrap exactly the provided reader (got " + searcher.getIndexReader() + " but expected " + reader + ")");
+ }
+ success = true;
+ } finally {
+ if (!success) {
+ reader.decRef();
+ }
+ }
+ return searcher;
+ }
}
Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java Fri Feb 17 19:08:51 2012
@@ -28,10 +28,12 @@ import org.apache.lucene.analysis.MockAn
import org.apache.lucene.document.Document;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.DirectoryReader;
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.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
import org.apache.lucene.store.Directory;
@@ -57,7 +59,7 @@ public class TestNRTManager extends Thre
System.out.println("TEST: finalSearcher maxGen=" + maxGen);
}
nrtDeletes.waitForGeneration(maxGen);
- return nrtDeletes.getSearcherManager().acquire();
+ return nrtDeletes.acquire();
}
@Override
@@ -84,14 +86,14 @@ public class TestNRTManager extends Thre
System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
}
nrtDeletes.waitForGeneration(gen);
- final IndexSearcher s = nrtDeletes.getSearcherManager().acquire();
+ final IndexSearcher s = nrtDeletes.acquire();
if (VERBOSE) {
System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
}
try {
assertEquals(docs.size(), s.search(new TermQuery(id), 10).totalHits);
} finally {
- nrtDeletes.getSearcherManager().release(s);
+ nrtDeletes.release(s);
}
}
@@ -107,14 +109,14 @@ public class TestNRTManager extends Thre
System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
}
nrtNoDeletes.waitForGeneration(gen);
- final IndexSearcher s = nrtNoDeletes.getSearcherManager().acquire();
+ final IndexSearcher s = nrtNoDeletes.acquire();
if (VERBOSE) {
System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
}
try {
assertEquals(docs.size(), s.search(new TermQuery(id), 10).totalHits);
} finally {
- nrtNoDeletes.getSearcherManager().release(s);
+ nrtNoDeletes.release(s);
}
}
lastGens.set(gen);
@@ -130,14 +132,14 @@ public class TestNRTManager extends Thre
System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
}
nrtNoDeletes.waitForGeneration(gen);
- final IndexSearcher s = nrtNoDeletes.getSearcherManager().acquire();
+ final IndexSearcher s = nrtNoDeletes.acquire();
if (VERBOSE) {
System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
}
try {
assertEquals(1, s.search(new TermQuery(id), 10).totalHits);
} finally {
- nrtNoDeletes.getSearcherManager().release(s);
+ nrtNoDeletes.release(s);
}
}
lastGens.set(gen);
@@ -152,14 +154,14 @@ public class TestNRTManager extends Thre
System.out.println(Thread.currentThread().getName() + ": nrt: verify " + id);
}
nrtDeletes.waitForGeneration(gen);
- final IndexSearcher s = nrtDeletes.getSearcherManager().acquire();
+ final IndexSearcher s = nrtDeletes.acquire();
if (VERBOSE) {
System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
}
try {
assertEquals(1, s.search(new TermQuery(id), 10).totalHits);
} finally {
- nrtDeletes.getSearcherManager().release(s);
+ nrtDeletes.release(s);
}
}
lastGens.set(gen);
@@ -174,14 +176,14 @@ public class TestNRTManager extends Thre
System.out.println(Thread.currentThread().getName() + ": nrt: verify del " + id);
}
nrtDeletes.waitForGeneration(gen);
- final IndexSearcher s = nrtDeletes.getSearcherManager().acquire();
+ final IndexSearcher s = nrtDeletes.acquire();
if (VERBOSE) {
System.out.println(Thread.currentThread().getName() + ": nrt: got searcher=" + s);
}
try {
assertEquals(0, s.search(new TermQuery(id), 10).totalHits);
} finally {
- nrtDeletes.getSearcherManager().release(s);
+ nrtDeletes.release(s);
}
}
lastGens.set(gen);
@@ -265,7 +267,7 @@ public class TestNRTManager extends Thre
nrt = nrtNoDeletes;
}
- return nrt.getSearcherManager().acquire();
+ return nrt.acquire();
}
@Override
@@ -274,7 +276,7 @@ public class TestNRTManager extends Thre
// against the same NRT mgr you acquired from... but
// both impls just decRef the underlying reader so we
// can get away w/ cheating:
- nrtNoDeletes.getSearcherManager().release(s);
+ nrtNoDeletes.release(s);
}
@Override
@@ -304,15 +306,15 @@ public class TestNRTManager extends Thre
Document doc = new Document();
doc.add(newField("test","test", TextField.TYPE_STORED));
long gen = writer.addDocument(doc);
- manager.maybeReopen();
+ manager.maybeRefresh();
assertFalse(gen < manager.getCurrentSearchingGen());
Thread t = new Thread() {
public void run() {
try {
signal.await();
- manager.maybeReopen();
+ manager.maybeRefresh();
writer.deleteDocuments(new TermQuery(new Term("foo", "barista")));
- manager.maybeReopen(); // kick off another reopen so we inc. the internal gen
+ manager.maybeRefresh(); // kick off another reopen so we inc. the internal gen
} catch (Exception e) {
e.printStackTrace();
} finally {
@@ -324,13 +326,13 @@ public class TestNRTManager extends Thre
_writer.waitAfterUpdate = true; // wait in addDocument to let some reopens go through
final long lastGen = writer.updateDocument(new Term("foo", "bar"), doc); // once this returns the doc is already reflected in the last reopen
- assertFalse(manager.getSearcherManager().isSearcherCurrent()); // false since there is a delete in the queue
+ assertFalse(manager.isSearcherCurrent()); // false since there is a delete in the queue
- IndexSearcher acquire = manager.getSearcherManager().acquire();
+ IndexSearcher searcher = manager.acquire();
try {
- assertEquals(2, acquire.getIndexReader().numDocs());
+ assertEquals(2, searcher.getIndexReader().numDocs());
} finally {
- manager.getSearcherManager().release(acquire);
+ manager.release(searcher);
}
NRTManagerReopenThread thread = new NRTManagerReopenThread(manager, 0.01, 0.01);
thread.start(); // start reopening
@@ -346,7 +348,7 @@ public class TestNRTManager extends Thre
}
};
waiter.start();
- manager.maybeReopen();
+ manager.maybeRefresh();
waiter.join(1000);
if (!finished.get()) {
waiter.interrupt();
@@ -386,4 +388,28 @@ public class TestNRTManager extends Thre
}
}
}
+
+ public void testEvilSearcherFactory() throws Exception {
+ final Directory dir = newDirectory();
+ final RandomIndexWriter w = new RandomIndexWriter(random, dir);
+ w.commit();
+
+ final IndexReader other = DirectoryReader.open(dir);
+
+ final SearcherFactory theEvilOne = new SearcherFactory() {
+ @Override
+ public IndexSearcher newSearcher(IndexReader ignored) throws IOException {
+ return new IndexSearcher(other);
+ }
+ };
+
+ try {
+ new NRTManager(new NRTManager.TrackingIndexWriter(w.w), theEvilOne);
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ w.close();
+ other.close();
+ dir.close();
+ }
}
Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java?rev=1245710&r1=1245709&r2=1245710&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestSearcherManager.java Fri Feb 17 19:08:51 2012
@@ -29,9 +29,11 @@ import java.util.concurrent.atomic.Atomi
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.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
import org.apache.lucene.store.AlreadyClosedException;
@@ -316,5 +318,33 @@ public class TestSearcherManager extends
}
dir.close();
}
-
+
+ public void testEvilSearcherFactory() throws Exception {
+ final Directory dir = newDirectory();
+ final RandomIndexWriter w = new RandomIndexWriter(random, dir);
+ w.commit();
+
+ final IndexReader other = DirectoryReader.open(dir);
+
+ final SearcherFactory theEvilOne = new SearcherFactory() {
+ @Override
+ public IndexSearcher newSearcher(IndexReader ignored) throws IOException {
+ return new IndexSearcher(other);
+ }
+ };
+
+ try {
+ new SearcherManager(dir, theEvilOne);
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ try {
+ new SearcherManager(w.w, random.nextBoolean(), theEvilOne);
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ w.close();
+ other.close();
+ dir.close();
+ }
}