Index: lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java (revision 1471409) +++ lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java (working copy) @@ -23,8 +23,9 @@ import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.index.IndexReader.ReaderClosedListener; +import org.apache.lucene.search.*; import org.apache.lucene.search.BooleanClause.Occur; -import org.apache.lucene.search.*; import org.apache.lucene.store.Directory; import org.apache.lucene.util.LuceneTestCase; @@ -277,6 +278,33 @@ dir2.close(); } + public void testReaderClosedListener() throws Exception { + Directory dir1 = getDir1(random()); + CompositeReader ir1 = DirectoryReader.open(dir1); + + // with overlapping + ParallelCompositeReader pr = new ParallelCompositeReader(false, + new CompositeReader[] {ir1}, + new CompositeReader[] {ir1}); + + final int[] listenerClosedCount = new int[1]; + + assertEquals(3, pr.leaves().size()); + + for(AtomicReaderContext cxt : pr.leaves()) { + cxt.reader().addReaderClosedListener(new ReaderClosedListener() { + @Override + public void onClose(IndexReader reader) { + listenerClosedCount[0]++; + } + }); + } + pr.close(); + ir1.close(); + assertEquals(3, listenerClosedCount[0]); + dir1.close(); + } + private void queryTest(Query query) throws IOException { ScoreDoc[] parallelHits = parallel.search(query, null, 1000).scoreDocs; ScoreDoc[] singleHits = single.search(query, null, 1000).scoreDocs; Index: lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java (revision 1471409) +++ lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java (working copy) @@ -115,7 +115,7 @@ // we simply enable closing of subReaders, to prevent incRefs on subReaders // -> for synthetic subReaders, close() is never // called by our doClose() - subReaders[i] = new ParallelAtomicReader(true, atomicSubs, storedSubs); + subReaders[i] = new ParallelAtomicReader(false, atomicSubs, storedSubs); } else { assert firstSubReaders.get(i) instanceof CompositeReader; final CompositeReader[] compositeSubs = new CompositeReader[readers.length]; @@ -128,7 +128,7 @@ } // we simply enable closing of subReaders, to prevent incRefs on subReaders // -> for synthetic subReaders, close() is never called by our doClose() - subReaders[i] = new ParallelCompositeReader(true, compositeSubs, storedSubs); + subReaders[i] = new ParallelCompositeReader(false, compositeSubs, storedSubs); } } return subReaders; @@ -171,6 +171,14 @@ @Override protected synchronized void doClose() throws IOException { IOException ioe = null; + // Close the readers we created in prepareReaders: + for (IndexReader reader : getSequentialSubReaders()) { + try { + reader.close(); + } catch (IOException e) { + if (ioe == null) ioe = e; + } + } for (final CompositeReader reader : completeReaderSet) { try { if (closeSubReaders) {