Index: lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java (revision 1499437) +++ lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java (working copy) @@ -33,6 +33,7 @@ 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 @@ 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 requests = new ArrayList(); + 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(); + } } Index: lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java (revision 1499437) +++ lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java (working copy) @@ -35,9 +35,11 @@ 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 @@ 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,18 @@ @Override public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException { - SortedSetDocValues segValues = matchingDocs.context.reader().getSortedSetDocValues(field); + AtomicReader reader = matchingDocs.context.reader(); + 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) { Index: lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesReaderState.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesReaderState.java (revision 1499437) +++ lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesReaderState.java (working copy) @@ -51,6 +51,7 @@ 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 @@ 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: