LUCENE-7564: Force single-threaded access to the AnalyzingInfixSuggester's SearcherManager when performing an acquire() or reassigning. This fixes failures in AnalyzingInfixSuggester.testRandomNRT().

This commit is contained in:
Steve Rowe 2016-12-29 15:51:37 -05:00
parent a4335c0e9f
commit 93fdc20736
1 changed files with 82 additions and 56 deletions

View File

@ -136,6 +136,8 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
/** {@link IndexSearcher} used for lookups. */ /** {@link IndexSearcher} used for lookups. */
protected SearcherManager searcherMgr; protected SearcherManager searcherMgr;
protected final Object searcherMgrLock = new Object();
/** Default minimum number of leading characters before /** Default minimum number of leading characters before
* PrefixQuery is used (4). */ * PrefixQuery is used (4). */
@ -275,53 +277,55 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
@Override @Override
public void build(InputIterator iter) throws IOException { public void build(InputIterator iter) throws IOException {
if (searcherMgr != null) { synchronized (searcherMgrLock) {
searcherMgr.close(); if (searcherMgr != null) {
searcherMgr = null; searcherMgr.close();
} searcherMgr = null;
if (writer != null) {
writer.close();
writer = null;
}
boolean success = false;
try {
// First pass: build a temporary normal Lucene index,
// just indexing the suggestions as they iterate:
writer = new IndexWriter(dir,
getIndexWriterConfig(getGramAnalyzer(), IndexWriterConfig.OpenMode.CREATE));
//long t0 = System.nanoTime();
// TODO: use threads?
BytesRef text;
while ((text = iter.next()) != null) {
BytesRef payload;
if (iter.hasPayloads()) {
payload = iter.payload();
} else {
payload = null;
}
add(text, iter.contexts(), iter.weight(), payload);
} }
//System.out.println("initial indexing time: " + ((System.nanoTime()-t0)/1000000) + " msec"); if (writer != null) {
if (commitOnBuild || closeIndexWriterOnBuild) { writer.close();
commit(); writer = null;
} }
searcherMgr = new SearcherManager(writer, null);
success = true; boolean success = false;
} finally { try {
if (success) { // First pass: build a temporary normal Lucene index,
if (closeIndexWriterOnBuild) { // just indexing the suggestions as they iterate:
writer.close(); writer = new IndexWriter(dir,
writer = null; getIndexWriterConfig(getGramAnalyzer(), IndexWriterConfig.OpenMode.CREATE));
//long t0 = System.nanoTime();
// TODO: use threads?
BytesRef text;
while ((text = iter.next()) != null) {
BytesRef payload;
if (iter.hasPayloads()) {
payload = iter.payload();
} else {
payload = null;
}
add(text, iter.contexts(), iter.weight(), payload);
} }
} else { // failure
if (writer != null) { //System.out.println("initial indexing time: " + ((System.nanoTime()-t0)/1000000) + " msec");
writer.rollback(); if (commitOnBuild || closeIndexWriterOnBuild) {
writer = null; commit();
}
searcherMgr = new SearcherManager(writer, null);
success = true;
} finally {
if (success) {
if (closeIndexWriterOnBuild) {
writer.close();
writer = null;
}
} else { // failure
if (writer != null) {
writer.rollback();
writer = null;
}
} }
} }
} }
@ -369,10 +373,12 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
} else { } else {
writer = new IndexWriter(dir, getIndexWriterConfig(getGramAnalyzer(), IndexWriterConfig.OpenMode.CREATE)); writer = new IndexWriter(dir, getIndexWriterConfig(getGramAnalyzer(), IndexWriterConfig.OpenMode.CREATE));
} }
SearcherManager oldSearcherMgr = searcherMgr; synchronized (searcherMgrLock) {
searcherMgr = new SearcherManager(writer, null); SearcherManager oldSearcherMgr = searcherMgr;
if (oldSearcherMgr != null) { searcherMgr = new SearcherManager(writer, null);
oldSearcherMgr.close(); if (oldSearcherMgr != null) {
oldSearcherMgr.close();
}
} }
} }
} }
@ -642,7 +648,12 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
// only retrieve the first num hits now: // only retrieve the first num hits now:
Collector c2 = new EarlyTerminatingSortingCollector(c, SORT, num); Collector c2 = new EarlyTerminatingSortingCollector(c, SORT, num);
List<LookupResult> results = null; List<LookupResult> results = null;
IndexSearcher searcher = searcherMgr.acquire(); SearcherManager mgr;
IndexSearcher searcher;
synchronized (searcherMgrLock) {
mgr = searcherMgr; // acquire & release on same SearcherManager, via local reference
searcher = mgr.acquire();
}
try { try {
//System.out.println("got searcher=" + searcher); //System.out.println("got searcher=" + searcher);
searcher.search(finalQuery, c2); searcher.search(finalQuery, c2);
@ -653,7 +664,7 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
// hits = searcher.search(query, null, num, SORT); // hits = searcher.search(query, null, num, SORT);
results = createResults(searcher, hits, num, key, doHighlight, matchedTokens, prefixToken); results = createResults(searcher, hits, num, key, doHighlight, matchedTokens, prefixToken);
} finally { } finally {
searcherMgr.release(searcher); mgr.release(searcher);
} }
//System.out.println((System.currentTimeMillis() - t0) + " msec for infix suggest"); //System.out.println((System.currentTimeMillis() - t0) + " msec for infix suggest");
@ -853,7 +864,12 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
long mem = RamUsageEstimator.shallowSizeOf(this); long mem = RamUsageEstimator.shallowSizeOf(this);
try { try {
if (searcherMgr != null) { if (searcherMgr != null) {
IndexSearcher searcher = searcherMgr.acquire(); SearcherManager mgr;
IndexSearcher searcher;
synchronized (searcherMgrLock) {
mgr = searcherMgr; // acquire & release on same SearcherManager, via local reference
searcher = mgr.acquire();
}
try { try {
for (LeafReaderContext context : searcher.getIndexReader().leaves()) { for (LeafReaderContext context : searcher.getIndexReader().leaves()) {
LeafReader reader = FilterLeafReader.unwrap(context.reader()); LeafReader reader = FilterLeafReader.unwrap(context.reader());
@ -862,7 +878,7 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
} }
} }
} finally { } finally {
searcherMgr.release(searcher); mgr.release(searcher);
} }
} }
return mem; return mem;
@ -876,7 +892,12 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
List<Accountable> resources = new ArrayList<>(); List<Accountable> resources = new ArrayList<>();
try { try {
if (searcherMgr != null) { if (searcherMgr != null) {
IndexSearcher searcher = searcherMgr.acquire(); SearcherManager mgr;
IndexSearcher searcher;
synchronized (searcherMgrLock) {
mgr = searcherMgr; // acquire & release on same SearcherManager, via local reference
searcher = mgr.acquire();
}
try { try {
for (LeafReaderContext context : searcher.getIndexReader().leaves()) { for (LeafReaderContext context : searcher.getIndexReader().leaves()) {
LeafReader reader = FilterLeafReader.unwrap(context.reader()); LeafReader reader = FilterLeafReader.unwrap(context.reader());
@ -885,7 +906,7 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
} }
} }
} finally { } finally {
searcherMgr.release(searcher); mgr.release(searcher);
} }
} }
return Collections.unmodifiableList(resources); return Collections.unmodifiableList(resources);
@ -899,11 +920,16 @@ public class AnalyzingInfixSuggester extends Lookup implements Closeable {
if (searcherMgr == null) { if (searcherMgr == null) {
return 0; return 0;
} }
IndexSearcher searcher = searcherMgr.acquire(); SearcherManager mgr;
IndexSearcher searcher;
synchronized (searcherMgrLock) {
mgr = searcherMgr; // acquire & release on same SearcherManager, via local reference
searcher = mgr.acquire();
}
try { try {
return searcher.getIndexReader().numDocs(); return searcher.getIndexReader().numDocs();
} finally { } finally {
searcherMgr.release(searcher); mgr.release(searcher);
} }
} }
}; }