LUCENE-5090: catch mismatched readers in SortedSetDocValuesAccumulator/ReaderState

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1503327 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2013-07-15 16:47:12 +00:00
parent 3c43636281
commit c7e9dbdde3
4 changed files with 69 additions and 3 deletions

View File

@ -225,6 +225,10 @@ Bug Fixes
* LUCENE-5103: A join on A single-valued field with deleted docs scored too few
docs. (David Smiley)
* LUCENE-5090: Detect mismatched readers passed to
SortedSetDocValuesReaderState and SortedSetDocValuesAccumulator.
(Robert Muir, Mike McCandless)
Optimizations
* LUCENE-4936: Improve numeric doc values compression in case all values share

View File

@ -35,9 +35,11 @@ import org.apache.lucene.facet.search.FacetsAccumulator;
import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.PriorityQueue;
@ -57,7 +59,7 @@ public class SortedSetDocValuesAccumulator extends FacetsAccumulator {
final String field;
public SortedSetDocValuesAccumulator(FacetSearchParams fsp, SortedSetDocValuesReaderState state) throws IOException {
super(fsp, null, null, new FacetArrays((int) state.getDocValues().getValueCount()));
super(fsp, null, null, new FacetArrays(state.getSize()));
this.state = state;
this.field = state.getField();
dv = state.getDocValues();
@ -90,13 +92,23 @@ public class SortedSetDocValuesAccumulator extends FacetsAccumulator {
@Override
public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException {
SortedSetDocValues segValues = matchingDocs.context.reader().getSortedSetDocValues(field);
AtomicReader reader = matchingDocs.context.reader();
// LUCENE-5090: make sure the provided reader context "matches"
// the top-level reader passed to the
// SortedSetDocValuesReaderState, else cryptic
// AIOOBE can happen:
if (ReaderUtil.getTopLevelContext(matchingDocs.context).reader() != state.origReader) {
throw new IllegalStateException("the SortedSetDocValuesReaderState provided to this class does not match the reader being searched; you must create a new SortedSetDocValuesReaderState every time you open a new IndexReader");
}
SortedSetDocValues segValues = reader.getSortedSetDocValues(field);
if (segValues == null) {
return;
}
final int[] counts = facetArrays.getIntArray();
final int maxDoc = matchingDocs.context.reader().maxDoc();
final int maxDoc = reader.maxDoc();
assert maxDoc == matchingDocs.bits.length();
if (dv instanceof MultiSortedSetDocValues) {

View File

@ -51,6 +51,7 @@ public final class SortedSetDocValuesReaderState {
private final String field;
private final AtomicReader topReader;
private final int valueCount;
final IndexReader origReader;
final char separator;
final String separatorRegex;
@ -91,6 +92,7 @@ public final class SortedSetDocValuesReaderState {
this.field = fip.getCategoryListParams(null).field + FACET_FIELD_EXTENSION;
this.separator = fip.getFacetDelimChar();
this.separatorRegex = Pattern.quote(Character.toString(separator));
this.origReader = reader;
// We need this to create thread-safe MultiSortedSetDV
// per collector:

View File

@ -33,6 +33,7 @@ import org.apache.lucene.facet.search.FacetRequest;
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetsCollector;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
@ -145,4 +146,51 @@ public class TestSortedSetDocValuesFacets extends FacetTestCase {
searcher.getIndexReader().close();
dir.close();
}
// LUCENE-5090
public void testStaleState() throws Exception {
assumeTrue("Test requires SortedSetDV support", defaultCodecSupportsSortedSet());
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
SortedSetDocValuesFacetFields dvFields = new SortedSetDocValuesFacetFields();
Document doc = new Document();
dvFields.addFields(doc, Collections.singletonList(new CategoryPath("a", "foo")));
writer.addDocument(doc);
IndexReader r = writer.getReader();
SortedSetDocValuesReaderState state = new SortedSetDocValuesReaderState(r);
doc = new Document();
dvFields.addFields(doc, Collections.singletonList(new CategoryPath("a", "bar")));
writer.addDocument(doc);
doc = new Document();
dvFields.addFields(doc, Collections.singletonList(new CategoryPath("a", "baz")));
writer.addDocument(doc);
IndexSearcher searcher = newSearcher(writer.getReader());
List<FacetRequest> requests = new ArrayList<FacetRequest>();
requests.add(new CountFacetRequest(new CategoryPath("a"), 10));
FacetSearchParams fsp = new FacetSearchParams(requests);
FacetsCollector c = FacetsCollector.create(new SortedSetDocValuesAccumulator(fsp, state));
searcher.search(new MatchAllDocsQuery(), c);
try {
c.getFacetResults();
fail("did not hit expected exception");
} catch (IllegalStateException ise) {
// expected
}
r.close();
writer.close();
searcher.getIndexReader().close();
dir.close();
}
}