You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2016/03/12 01:27:13 UTC

[32/50] [abbrv] lucene-solr git commit: LUCENE-7086: move SlowCompositeReaderWrapper to misc module, and throw clear exc if you try to use in with points

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestPayloads.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPayloads.java b/lucene/core/src/test/org/apache/lucene/index/TestPayloads.java
index 3fa2131..eca293e 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPayloads.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPayloads.java
@@ -85,7 +85,7 @@ public class TestPayloads extends LuceneTestCase {
     // flush
     writer.close();
 
-    SegmentReader reader = getOnlySegmentReader(DirectoryReader.open(ram));
+    LeafReader reader = getOnlyLeafReader(DirectoryReader.open(ram));
     FieldInfos fi = reader.getFieldInfos();
     assertFalse("Payload field bit should not be set.", fi.fieldInfo("f1").hasPayloads());
     assertTrue("Payload field bit should be set.", fi.fieldInfo("f2").hasPayloads());
@@ -112,7 +112,7 @@ public class TestPayloads extends LuceneTestCase {
     // flush
     writer.close();
 
-    reader = getOnlySegmentReader(DirectoryReader.open(ram));
+    reader = getOnlyLeafReader(DirectoryReader.open(ram));
     fi = reader.getFieldInfos();
     assertFalse("Payload field bit should not be set.", fi.fieldInfo("f1").hasPayloads());
     assertTrue("Payload field bit should be set.", fi.fieldInfo("f2").hasPayloads());
@@ -603,8 +603,9 @@ public class TestPayloads extends LuceneTestCase {
     field.setTokenStream(ts);
     writer.addDocument(doc);
     DirectoryReader reader = writer.getReader();
-    LeafReader sr = SlowCompositeReaderWrapper.wrap(reader);
-    PostingsEnum de = sr.postings(new Term("field", "withPayload"), PostingsEnum.PAYLOADS);
+    TermsEnum te = MultiFields.getFields(reader).terms("field").iterator();
+    assertTrue(te.seekExact(new BytesRef("withPayload")));
+    PostingsEnum de = te.postings(null, PostingsEnum.PAYLOADS);
     de.nextDoc();
     de.nextPosition();
     assertEquals(new BytesRef("test"), de.getPayload());
@@ -637,7 +638,7 @@ public class TestPayloads extends LuceneTestCase {
     doc.add(field3);
     writer.addDocument(doc);
     DirectoryReader reader = writer.getReader();
-    SegmentReader sr = getOnlySegmentReader(reader);
+    LeafReader sr = getOnlyLeafReader(reader);
     PostingsEnum de = sr.postings(new Term("field", "withPayload"), PostingsEnum.PAYLOADS);
     de.nextDoc();
     de.nextPosition();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
index 9b18f02..0946234 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
@@ -182,7 +182,7 @@ public class TestPointValues extends LuceneTestCase {
     w2.addDocument(doc);
     DirectoryReader r = DirectoryReader.open(dir);
     IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
-      w2.addIndexes(new CodecReader[] {getOnlySegmentReader(r)});
+        w2.addIndexes(new CodecReader[] {(CodecReader) getOnlyLeafReader(r)});
     });
     assertEquals("cannot change point dimension count from 2 to 1 for field=\"dim\"", expected.getMessage());
 
@@ -331,7 +331,7 @@ public class TestPointValues extends LuceneTestCase {
     w2.addDocument(doc);
     DirectoryReader r = DirectoryReader.open(dir);
     IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
-      w2.addIndexes(new CodecReader[] {getOnlySegmentReader(r)});
+        w2.addIndexes(new CodecReader[] {(CodecReader) getOnlyLeafReader(r)});
     });
     assertEquals("cannot change point numBytes from 6 to 4 for field=\"dim\"", expected.getMessage());
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java b/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
index aff0bd9..b21cb23 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
@@ -375,10 +375,9 @@ public class TestPostingsOffsets extends LuceneTestCase {
       riw.addDocument(doc);
     }
     CompositeReader ir = riw.getReader();
-    LeafReader slow = SlowCompositeReaderWrapper.wrap(ir);
-    FieldInfos fis = slow.getFieldInfos();
+    FieldInfos fis = MultiFields.getMergedFieldInfos(ir);
     assertEquals(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, fis.fieldInfo("foo").getIndexOptions());
-    slow.close();
+    ir.close();
     ir.close();
     riw.close();
     dir.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestReaderClosed.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestReaderClosed.java b/lucene/core/src/test/org/apache/lucene/index/TestReaderClosed.java
index 6a1ab3a..401254b 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestReaderClosed.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestReaderClosed.java
@@ -32,7 +32,7 @@ import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
 public class TestReaderClosed extends LuceneTestCase {
-  private IndexReader reader;
+  private DirectoryReader reader;
   private Directory dir;
 
   @Override
@@ -54,6 +54,7 @@ public class TestReaderClosed extends LuceneTestCase {
       field.setStringValue(TestUtil.randomUnicodeString(random(), 10));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = writer.getReader();
     writer.close();
   }
@@ -77,8 +78,7 @@ public class TestReaderClosed extends LuceneTestCase {
   // LUCENE-3800
   public void testReaderChaining() throws Exception {
     assertTrue(reader.getRefCount() > 0);
-    IndexReader wrappedReader = SlowCompositeReaderWrapper.wrap(reader);
-    wrappedReader = new ParallelLeafReader((LeafReader) wrappedReader);
+    LeafReader wrappedReader = new ParallelLeafReader(getOnlyLeafReader(reader));
 
     IndexSearcher searcher = newSearcher(wrappedReader);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestReaderWrapperDVTypeCheck.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestReaderWrapperDVTypeCheck.java b/lucene/core/src/test/org/apache/lucene/index/TestReaderWrapperDVTypeCheck.java
index 308c48e..88b177d 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestReaderWrapperDVTypeCheck.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestReaderWrapperDVTypeCheck.java
@@ -45,7 +45,7 @@ public class TestReaderWrapperDVTypeCheck extends LuceneTestCase {
     {
       final Random indexRandom = new Random(seed);
       final int docs;
-      docs = indexRandom.nextInt(4);
+      docs = TestUtil.nextInt(indexRandom, 1, 4);
      // System.out.println("docs:"+docs);
       
       for(int i=0; i< docs; i++){
@@ -68,12 +68,13 @@ public class TestReaderWrapperDVTypeCheck extends LuceneTestCase {
         iw.commit();
       }
     }
+    iw.forceMerge(1);
     final DirectoryReader reader = iw.getReader();
     
    // System.out.println("sdv:"+ sdvExist+ " ssdv:"+ssdvExist+", segs: "+reader.leaves().size() +", "+reader.leaves());
     
     iw.close();
-    final LeafReader wrapper = SlowCompositeReaderWrapper.wrap(reader);
+    final LeafReader wrapper = getOnlyLeafReader(reader);
     
     {
       //final Random indexRandom = new Random(seed);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestSegmentTermEnum.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestSegmentTermEnum.java b/lucene/core/src/test/org/apache/lucene/index/TestSegmentTermEnum.java
index fc708c2..1e85e14 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestSegmentTermEnum.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestSegmentTermEnum.java
@@ -79,7 +79,7 @@ public class TestSegmentTermEnum extends LuceneTestCase {
                                 .setCodec(TestUtil.alwaysPostingsFormat(TestUtil.getDefaultPostingsFormat())));
     addDoc(writer, "aaa bbb");
     writer.close();
-    SegmentReader reader = getOnlySegmentReader(DirectoryReader.open(dir));
+    LeafReader reader = getOnlyLeafReader(DirectoryReader.open(dir));
     TermsEnum terms = reader.fields().terms("content").iterator();
     assertNotNull(terms.next());
     assertEquals("aaa", terms.term().utf8ToString());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestStressAdvance.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestStressAdvance.java b/lucene/core/src/test/org/apache/lucene/index/TestStressAdvance.java
index d423616..606a11a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestStressAdvance.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestStressAdvance.java
@@ -74,7 +74,7 @@ public class TestStressAdvance extends LuceneTestCase {
           bDocIDs.add(docID);
         }
       }
-      final TermsEnum te = getOnlySegmentReader(r).fields().terms("field").iterator();
+      final TermsEnum te = getOnlyLeafReader(r).fields().terms("field").iterator();
       
       PostingsEnum de = null;
       for(int iter2=0;iter2<10;iter2++) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
index aa2ca24..b074f81 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
@@ -732,7 +732,7 @@ public class TestTermsEnum extends LuceneTestCase {
     w.forceMerge(1);
     DirectoryReader r = w.getReader();
     w.close();
-    LeafReader sub = getOnlySegmentReader(r);
+    LeafReader sub = getOnlyLeafReader(r);
     Terms terms = sub.fields().terms("field");
     Automaton automaton = new RegExp(".*", RegExp.NONE).toAutomaton();
     CompiledAutomaton ca = new CompiledAutomaton(automaton, false, false);    
@@ -786,7 +786,7 @@ public class TestTermsEnum extends LuceneTestCase {
     w.forceMerge(1);
     DirectoryReader r = w.getReader();
     w.close();
-    LeafReader sub = getOnlySegmentReader(r);
+    LeafReader sub = getOnlyLeafReader(r);
     Terms terms = sub.fields().terms("field");
 
     Automaton automaton = new RegExp(".*d", RegExp.NONE).toAutomaton();
@@ -840,7 +840,7 @@ public class TestTermsEnum extends LuceneTestCase {
     w.forceMerge(1);
     DirectoryReader r = w.getReader();
     w.close();
-    LeafReader sub = getOnlySegmentReader(r);
+    LeafReader sub = getOnlyLeafReader(r);
     Terms terms = sub.fields().terms("field");
 
     Automaton automaton = new RegExp(".*", RegExp.NONE).toAutomaton();  // accept ALL

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
index 7a9bb4e..79c32d3 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
@@ -36,7 +36,6 @@ import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.ClassicSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
@@ -157,9 +156,10 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
       writer.addDocument(d4);
     }
     
-    r = SlowCompositeReaderWrapper.wrap(writer.getReader());
+    writer.forceMerge(1);
+    r = getOnlyLeafReader(writer.getReader());
     writer.close();
-    s = newSearcher(r);
+    s = new IndexSearcher(r);
     s.setSimilarity(sim);
   }
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
index f289975..cc6606f 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
@@ -87,7 +87,7 @@ public class TestMinShouldMatch2 extends LuceneTestCase {
     iw.forceMerge(1);
     iw.close();
     r = DirectoryReader.open(dir);
-    reader = getOnlySegmentReader(r);
+    reader = getOnlyLeafReader(r);
     searcher = new IndexSearcher(reader);
     searcher.setSimilarity(new ClassicSimilarity() {
       @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseEnum.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseEnum.java b/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseEnum.java
index aa0c86d..5d0096d 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseEnum.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseEnum.java
@@ -48,8 +48,8 @@ public class TestMultiPhraseEnum extends LuceneTestCase {
     DirectoryReader ir = DirectoryReader.open(writer);
     writer.close();
 
-    PostingsEnum p1 = getOnlySegmentReader(ir).postings(new Term("field", "foo"), PostingsEnum.POSITIONS);
-    PostingsEnum p2 = getOnlySegmentReader(ir).postings(new Term("field", "bar"), PostingsEnum.POSITIONS);
+    PostingsEnum p1 = getOnlyLeafReader(ir).postings(new Term("field", "foo"), PostingsEnum.POSITIONS);
+    PostingsEnum p2 = getOnlyLeafReader(ir).postings(new Term("field", "bar"), PostingsEnum.POSITIONS);
     PostingsEnum union = new MultiPhraseQuery.UnionPostingsEnum(Arrays.asList(p1, p2));
     
     assertEquals(-1, union.docID());
@@ -90,8 +90,8 @@ public class TestMultiPhraseEnum extends LuceneTestCase {
     DirectoryReader ir = DirectoryReader.open(writer);
     writer.close();
 
-    PostingsEnum p1 = getOnlySegmentReader(ir).postings(new Term("field", "foo"), PostingsEnum.POSITIONS);
-    PostingsEnum p2 = getOnlySegmentReader(ir).postings(new Term("field", "bar"), PostingsEnum.POSITIONS);
+    PostingsEnum p1 = getOnlyLeafReader(ir).postings(new Term("field", "foo"), PostingsEnum.POSITIONS);
+    PostingsEnum p2 = getOnlyLeafReader(ir).postings(new Term("field", "bar"), PostingsEnum.POSITIONS);
     PostingsEnum union = new MultiPhraseQuery.UnionPostingsEnum(Arrays.asList(p1, p2));
     
     assertEquals(-1, union.docID());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
index cf77903..0d6cb36 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
@@ -95,7 +95,7 @@ public class TestPhraseQuery extends LuceneTestCase {
     reader = writer.getReader();
     writer.close();
 
-    searcher = newSearcher(reader);
+    searcher = new IndexSearcher(reader);
   }
   
   @Override
@@ -123,7 +123,7 @@ public class TestPhraseQuery extends LuceneTestCase {
     query = new PhraseQuery(3, "field", "one", "five");
     ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
     assertEquals(1, hits.length);
-    QueryUtils.check(random(), query,searcher);
+    QueryUtils.check(random(), query, searcher);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java b/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
index b7ae42a..227b15d 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
@@ -36,9 +36,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.spans.MultiSpansWrapper;
 import org.apache.lucene.search.spans.SpanCollector;
 import org.apache.lucene.search.spans.SpanNearQuery;
 import org.apache.lucene.search.spans.SpanQuery;
@@ -225,7 +223,7 @@ public class TestPositionIncrement extends LuceneTestCase {
     writer.addDocument(doc);
 
     final IndexReader readerFromWriter = writer.getReader();
-    LeafReader r = SlowCompositeReaderWrapper.wrap(readerFromWriter);
+    LeafReader r = getOnlyLeafReader(readerFromWriter);
 
     PostingsEnum tp = r.postings(new Term("content", "a"), PostingsEnum.ALL);
     
@@ -241,7 +239,7 @@ public class TestPositionIncrement extends LuceneTestCase {
     // only one doc has "a"
     assertEquals(DocIdSetIterator.NO_MORE_DOCS, tp.nextDoc());
 
-    IndexSearcher is = newSearcher(readerFromWriter);
+    IndexSearcher is = newSearcher(getOnlyLeafReader(readerFromWriter));
   
     SpanTermQuery stq1 = new SpanTermQuery(new Term("content", "a"));
     SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
@@ -254,7 +252,7 @@ public class TestPositionIncrement extends LuceneTestCase {
       System.out.println("\ngetPayloadSpans test");
     }
     PayloadSpanCollector collector = new PayloadSpanCollector();
-    Spans pspans = MultiSpansWrapper.wrap(is.getIndexReader(), snq, SpanWeight.Postings.PAYLOADS);
+    Spans pspans = snq.createWeight(is, false).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.PAYLOADS);
     while (pspans.nextDoc() != Spans.NO_MORE_DOCS) {
       while (pspans.nextStartPosition() != Spans.NO_MORE_POSITIONS) {
         if (VERBOSE) {
@@ -276,7 +274,7 @@ public class TestPositionIncrement extends LuceneTestCase {
     assertEquals(8, count);
 
     // System.out.println("\ngetSpans test");
-    Spans spans = MultiSpansWrapper.wrap(is.getIndexReader(), snq);
+    Spans spans = snq.createWeight(is, false).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     count = 0;
     sawZero = false;
     while (spans.nextDoc() != Spans.NO_MORE_DOCS) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java b/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
index 9278934..c332c10 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
@@ -20,13 +20,13 @@ package org.apache.lucene.search;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.PerFieldSimilarityWrapper;
 import org.apache.lucene.search.similarities.Similarity;
@@ -75,10 +75,9 @@ public class TestSimilarityProvider extends LuceneTestCase {
   public void testBasics() throws Exception {
     // sanity check of norms writer
     // TODO: generalize
-    LeafReader slow = SlowCompositeReaderWrapper.wrap(reader);
-    NumericDocValues fooNorms = slow.getNormValues("foo");
-    NumericDocValues barNorms = slow.getNormValues("bar");
-    for (int i = 0; i < slow.maxDoc(); i++) {
+    NumericDocValues fooNorms = MultiDocValues.getNormValues(reader, "foo");
+    NumericDocValues barNorms = MultiDocValues.getNormValues(reader, "bar");
+    for (int i = 0; i < reader.maxDoc(); i++) {
       assertFalse(fooNorms.get(i) == barNorms.get(i));
     }
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
index 30061b5..2cdcba4 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
@@ -29,7 +29,6 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.ClassicSimilarity;
 import org.apache.lucene.store.Directory;
@@ -55,11 +54,11 @@ public class TestTermScorer extends LuceneTestCase {
         .setSimilarity(new ClassicSimilarity()));
     for (int i = 0; i < values.length; i++) {
       Document doc = new Document();
-      doc
-          .add(newTextField(FIELD, values[i], Field.Store.YES));
+      doc.add(newTextField(FIELD, values[i], Field.Store.YES));
       writer.addDocument(doc);
     }
-    indexReader = SlowCompositeReaderWrapper.wrap(writer.getReader());
+    writer.forceMerge(1);
+    indexReader = getOnlyLeafReader(writer.getReader());
     writer.close();
     indexSearcher = newSearcher(indexReader);
     indexSearcher.setSimilarity(new ClassicSimilarity());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
index 9c7ada8..c656b85 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
@@ -16,10 +16,15 @@
  */
 package org.apache.lucene.search;
 
+import org.apache.lucene.document.Document;
 import org.apache.lucene.document.IntPoint;
+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.MultiReader;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
 public class TestUsageTrackingFilterCachingPolicy extends LuceneTestCase {
@@ -36,7 +41,15 @@ public class TestUsageTrackingFilterCachingPolicy extends LuceneTestCase {
     for (int i = 0; i < 1000; ++i) {
       policy.onUse(q);
     }
-    assertFalse(policy.shouldCache(q, SlowCompositeReaderWrapper.wrap(new MultiReader()).getContext()));
+    Directory dir = newDirectory();
+    IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(null));
+    w.addDocument(new Document());
+    IndexReader r = DirectoryReader.open(w);
+    assertFalse(policy.shouldCache(q, getOnlyLeafReader(r).getContext()));
+    
+    r.close();
+    w.close();
+    dir.close();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
index 052457b..b4435e7 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
@@ -116,8 +116,9 @@ public class TestFieldMaskingSpanQuery extends LuceneTestCase {
                                          field("first",  "bubba"),
                                          field("last",   "jones")     }));
     reader = writer.getReader();
+    writer.forceMerge(1);
     writer.close();
-    searcher = newSearcher(reader);
+    searcher = new IndexSearcher(getOnlyLeafReader(reader));
   }
 
   @AfterClass
@@ -251,7 +252,7 @@ public class TestFieldMaskingSpanQuery extends LuceneTestCase {
     SpanQuery q  = new SpanOrQuery(q1, new FieldMaskingSpanQuery(q2, "gender"));
     check(q, new int[] { 0, 1, 2, 3, 4 });
 
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(span, 0,0,1);
     assertNext(span, 1,0,1);
     assertNext(span, 1,1,2);
@@ -273,8 +274,8 @@ public class TestFieldMaskingSpanQuery extends LuceneTestCase {
     check(qA, new int[] { 0, 1, 2, 4 });
     check(qB, new int[] { 0, 1, 2, 4 });
   
-    Spans spanA = MultiSpansWrapper.wrap(searcher.getIndexReader(), qA);
-    Spans spanB = MultiSpansWrapper.wrap(searcher.getIndexReader(), qB);
+    Spans spanA = qA.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
+    Spans spanB = qB.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     
     while (spanA.nextDoc() != Spans.NO_MORE_DOCS) {
       assertNotSame("spanB not still going", Spans.NO_MORE_DOCS, spanB.nextDoc());
@@ -299,7 +300,7 @@ public class TestFieldMaskingSpanQuery extends LuceneTestCase {
         new FieldMaskingSpanQuery(qB, "id") }, -1, false );
     check(q, new int[] { 0, 1, 2, 3 });
 
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(span, 0,0,1);
     assertNext(span, 1,1,2);
     assertNext(span, 2,0,1);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
index b101c61..f297f33 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
@@ -60,9 +60,10 @@ public class TestNearSpansOrdered extends LuceneTestCase {
       doc.add(newTextField(FIELD, docFields[i], Field.Store.NO));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = writer.getReader();
     writer.close();
-    searcher = newSearcher(reader);
+    searcher = newSearcher(getOnlyLeafReader(reader));
   }
 
   protected String[] docFields = {
@@ -118,7 +119,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
   
   public void testNearSpansNext() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(span,0,0,3);
     assertNext(span,1,0,4);
     assertFinished(span);
@@ -131,7 +132,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
    */
   public void testNearSpansAdvanceLikeNext() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertEquals(0, span.advance(0));
     assertEquals(0, span.nextStartPosition());
     assertEquals(s(0,0,3), s(span));
@@ -143,7 +144,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
   
   public void testNearSpansNextThenAdvance() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNotSame(Spans.NO_MORE_DOCS, span.nextDoc());
     assertEquals(0, span.nextStartPosition());
     assertEquals(s(0,0,3), s(span));
@@ -155,7 +156,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
   
   public void testNearSpansNextThenAdvancePast() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNotSame(Spans.NO_MORE_DOCS, span.nextDoc());
     assertEquals(0, span.nextStartPosition());
     assertEquals(s(0,0,3), s(span));
@@ -164,13 +165,13 @@ public class TestNearSpansOrdered extends LuceneTestCase {
   
   public void testNearSpansAdvancePast() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertEquals(Spans.NO_MORE_DOCS, span.advance(2));
   }
   
   public void testNearSpansAdvanceTo0() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertEquals(0, span.advance(0));
     assertEquals(0, span.nextStartPosition());
     assertEquals(s(0,0,3), s(span));
@@ -178,7 +179,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
 
   public void testNearSpansAdvanceTo1() throws Exception {
     SpanNearQuery q = makeQuery();
-    Spans span = MultiSpansWrapper.wrap(searcher.getIndexReader(), q);
+    Spans span = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertEquals(1, span.advance(1));
     assertEquals(0, span.nextStartPosition());
     assertEquals(s(1,0,4), s(span));
@@ -217,7 +218,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
         new SpanOrQuery(new SpanTermQuery(new Term(FIELD, "w1")), new SpanTermQuery(new Term(FIELD, "w2"))),
         new SpanTermQuery(new Term(FIELD, "w4"))
     }, 10, true);
-    Spans spans = MultiSpansWrapper.wrap(reader, q);
+    Spans spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans,0,0,4);
     assertNext(spans,0,1,4);
     assertFinished(spans);
@@ -227,7 +228,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
     SpanNearQuery q = new SpanNearQuery(new SpanQuery[]{
         new SpanTermQuery(new Term(FIELD, "t1")), new SpanTermQuery(new Term(FIELD, "t2"))
     }, 1, true);
-    Spans spans = MultiSpansWrapper.wrap(reader, q);
+    Spans spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans,4,0,2);
     assertFinished(spans);
   }
@@ -236,7 +237,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
     SpanNearQuery q = new SpanNearQuery(new SpanQuery[]{
         new SpanTermQuery(new Term(FIELD, "t2")), new SpanTermQuery(new Term(FIELD, "t1"))
     }, 1, true);
-    Spans spans = MultiSpansWrapper.wrap(reader, q);
+    Spans spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans,4,1,4);
     assertNext(spans,4,2,4);
     assertFinished(spans);
@@ -260,7 +261,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
         .addGap(1)
         .addClause(new SpanTermQuery(new Term(FIELD, "w2")))
         .build();
-    Spans spans = MultiSpansWrapper.wrap(reader, q);
+    Spans spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans, 1, 0, 3);
     assertNext(spans, 2, 0, 3);
     assertFinished(spans);
@@ -273,7 +274,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
         .addClause(new SpanTermQuery(new Term(FIELD, "w3")))
         .setSlop(1)
         .build();
-    spans = MultiSpansWrapper.wrap(reader, q);
+    spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans, 2, 0, 5);
     assertNext(spans, 3, 0, 6);
     assertFinished(spans);
@@ -285,7 +286,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
         .addGap(2)
         .addClause(new SpanTermQuery(new Term(FIELD, "g")))
         .build();
-    Spans spans = MultiSpansWrapper.wrap(reader, q);
+    Spans spans = q.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans, 5, 0, 4);
     assertNext(spans, 5, 9, 13);
     assertFinished(spans);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanCollection.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanCollection.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanCollection.java
index 03fc40d..dfc0439 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanCollection.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanCollection.java
@@ -67,9 +67,10 @@ public class TestSpanCollection extends LuceneTestCase {
       doc.add(newField(FIELD, docFields[i], OFFSETS));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = writer.getReader();
     writer.close();
-    searcher = newSearcher(reader);
+    searcher = newSearcher(getOnlyLeafReader(reader));
   }
 
   private static class TermCollector implements SpanCollector {
@@ -119,7 +120,7 @@ public class TestSpanCollection extends LuceneTestCase {
     SpanNearQuery q7 = new SpanNearQuery(new SpanQuery[]{q1, q6}, 1, true);
 
     TermCollector collector = new TermCollector();
-    Spans spans = MultiSpansWrapper.wrap(reader, q7, SpanWeight.Postings.POSITIONS);
+    Spans spans = q7.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertEquals(0, spans.advance(0));
     spans.nextStartPosition();
     checkCollectedTerms(spans, collector, new Term(FIELD, "w1"), new Term(FIELD, "w2"), new Term(FIELD, "w3"));
@@ -139,7 +140,7 @@ public class TestSpanCollection extends LuceneTestCase {
     SpanOrQuery orQuery = new SpanOrQuery(q2, q3);
 
     TermCollector collector = new TermCollector();
-    Spans spans = MultiSpansWrapper.wrap(reader, orQuery, SpanWeight.Postings.POSITIONS);
+    Spans spans = orQuery.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
 
     assertEquals(1, spans.advance(1));
     spans.nextStartPosition();
@@ -169,7 +170,7 @@ public class TestSpanCollection extends LuceneTestCase {
     SpanNotQuery notq = new SpanNotQuery(nq, q3);
 
     TermCollector collector = new TermCollector();
-    Spans spans = MultiSpansWrapper.wrap(reader, notq, SpanWeight.Postings.POSITIONS);
+    Spans spans = notq.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
 
     assertEquals(2, spans.advance(2));
     spans.nextStartPosition();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanContainQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanContainQuery.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanContainQuery.java
index c260704..3e50183 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanContainQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanContainQuery.java
@@ -47,9 +47,10 @@ public class TestSpanContainQuery extends LuceneTestCase {
       doc.add(newTextField(field, docFields[i], Field.Store.YES));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = writer.getReader();
     writer.close();
-    searcher = newSearcher(reader);
+    searcher = newSearcher(getOnlyLeafReader(reader));
   }
 
   @Override
@@ -71,7 +72,7 @@ public class TestSpanContainQuery extends LuceneTestCase {
   }
 
   Spans makeSpans(SpanQuery sq) throws Exception {
-    return MultiSpansWrapper.wrap(searcher.getIndexReader(), sq);
+    return sq.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
   }
 
   void tstEqualSpans(String mes, SpanQuery expectedQ, SpanQuery actualQ) throws Exception {
@@ -144,4 +145,4 @@ public class TestSpanContainQuery extends LuceneTestCase {
     assertFinished(spans);
   }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
index 9352f60..2983301 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
@@ -70,9 +70,10 @@ public class TestSpans extends LuceneTestCase {
       doc.add(newTextField(field, docFields[i], Field.Store.YES));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = writer.getReader();
     writer.close();
-    searcher = newSearcher(reader);
+    searcher = newSearcher(getOnlyLeafReader(reader));
   }
   
   @Override
@@ -201,7 +202,7 @@ public class TestSpans extends LuceneTestCase {
   public void testSpanNearOrderedOverlap() throws Exception {
     final SpanQuery query = spanNearOrderedQuery(field, 1, "t1", "t2", "t3");
     
-    Spans spans = MultiSpansWrapper.wrap(searcher.getIndexReader(), query);
+    Spans spans = query.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
 
     assertEquals("first doc", 11, spans.nextDoc());
     assertEquals("first start", 0, spans.nextStartPosition());
@@ -216,7 +217,7 @@ public class TestSpans extends LuceneTestCase {
   public void testSpanNearUnOrdered() throws Exception {
     //See http://www.gossamer-threads.com/lists/lucene/java-dev/52270 for discussion about this test
     SpanQuery senq = spanNearUnorderedQuery(field, 0, "u1", "u2");
-    Spans spans = MultiSpansWrapper.wrap(reader, senq);
+    Spans spans = senq.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans, 4, 1, 3);
     assertNext(spans, 5, 2, 4);
     assertNext(spans, 8, 2, 4);
@@ -225,7 +226,7 @@ public class TestSpans extends LuceneTestCase {
     assertFinished(spans);
 
     senq = spanNearUnorderedQuery(1, senq, spanTermQuery(field, "u2")); 
-    spans = MultiSpansWrapper.wrap(reader, senq);
+    spans = senq.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     assertNext(spans, 4, 0, 3);
     assertNext(spans, 4, 1, 3); // unordered spans can be subsets
     assertNext(spans, 5, 0, 4);
@@ -239,7 +240,7 @@ public class TestSpans extends LuceneTestCase {
   }
 
   private Spans orSpans(String[] terms) throws Exception {
-    return MultiSpansWrapper.wrap(searcher.getIndexReader(), spanOrQuery(field, terms));
+    return spanOrQuery(field, terms).createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
   }
 
   public void testSpanOrEmpty() throws Exception {
@@ -443,7 +444,7 @@ public class TestSpans extends LuceneTestCase {
      SpanQuery iq = spanTermQuery(field, include);
      SpanQuery eq = spanTermQuery(field, exclude);
      SpanQuery snq = spanNotQuery(iq, eq, pre, post);
-     Spans spans = MultiSpansWrapper.wrap(searcher.getIndexReader(), snq);
+     Spans spans = snq.createWeight(searcher, false).getSpans(searcher.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
 
      int i = 0;
      if (spans != null) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/facet/src/java/org/apache/lucene/facet/sortedset/DefaultSortedSetDocValuesReaderState.java
----------------------------------------------------------------------
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/DefaultSortedSetDocValuesReaderState.java b/lucene/facet/src/java/org/apache/lucene/facet/sortedset/DefaultSortedSetDocValuesReaderState.java
index 5d374f7..e052541 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/DefaultSortedSetDocValuesReaderState.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/sortedset/DefaultSortedSetDocValuesReaderState.java
@@ -23,9 +23,16 @@ import java.util.Map;
 
 import org.apache.lucene.facet.FacetsConfig;
 import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState.OrdRange;
-import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.DocValuesType;
+import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.MultiDocValues.MultiSortedDocValues;
+import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
+import org.apache.lucene.index.MultiDocValues.OrdinalMap;
+import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.util.BytesRef;
 
@@ -35,12 +42,13 @@ import org.apache.lucene.util.BytesRef;
 public class DefaultSortedSetDocValuesReaderState extends SortedSetDocValuesReaderState {
 
   private final String field;
-  private final LeafReader topReader;
   private final int valueCount;
 
   /** {@link IndexReader} passed to the constructor. */
   public final IndexReader origReader;
 
+  private final Map<String,OrdinalMap> cachedOrdMaps = new HashMap<>();
+
   private final Map<String,OrdRange> prefixToOrdRange = new HashMap<>();
 
   /** Creates this, pulling doc values from the default {@link
@@ -57,8 +65,7 @@ public class DefaultSortedSetDocValuesReaderState extends SortedSetDocValuesRead
 
     // We need this to create thread-safe MultiSortedSetDV
     // per collector:
-    topReader = SlowCompositeReaderWrapper.wrap(reader);
-    SortedSetDocValues dv = topReader.getSortedSetDocValues(field);
+    SortedSetDocValues dv = getDocValues();
     if (dv == null) {
       throw new IllegalArgumentException("field \"" + field + "\" was not indexed with SortedSetDocValues");
     }
@@ -100,7 +107,43 @@ public class DefaultSortedSetDocValuesReaderState extends SortedSetDocValuesRead
   /** Return top-level doc values. */
   @Override
   public SortedSetDocValues getDocValues() throws IOException {
-    return topReader.getSortedSetDocValues(field);
+    // TODO: this is dup'd from slow composite reader wrapper ... can we factor it out to share?
+    OrdinalMap map = null;
+    synchronized (cachedOrdMaps) {
+      map = cachedOrdMaps.get(field);
+      if (map == null) {
+        // uncached, or not a multi dv
+        SortedSetDocValues dv = MultiDocValues.getSortedSetValues(origReader, field);
+        if (dv instanceof MultiSortedSetDocValues) {
+          map = ((MultiSortedSetDocValues)dv).mapping;
+          if (map.owner == origReader.getCoreCacheKey()) {
+            cachedOrdMaps.put(field, map);
+          }
+        }
+        return dv;
+      }
+    }
+   
+    assert map != null;
+    int size = origReader.leaves().size();
+    final SortedSetDocValues[] values = new SortedSetDocValues[size];
+    final int[] starts = new int[size+1];
+    for (int i = 0; i < size; i++) {
+      LeafReaderContext context = origReader.leaves().get(i);
+      final LeafReader reader = context.reader();
+      final FieldInfo fieldInfo = reader.getFieldInfos().fieldInfo(field);
+      if (fieldInfo != null && fieldInfo.getDocValuesType() != DocValuesType.SORTED_SET) {
+        return null;
+      }
+      SortedSetDocValues v = reader.getSortedSetDocValues(field);
+      if (v == null) {
+        v = DocValues.emptySortedSet();
+      }
+      values[i] = v;
+      starts[i] = context.docBase;
+    }
+    starts[size] = origReader.maxDoc();
+    return new MultiSortedSetDocValues(values, starts, map);
   }
 
   /** Returns mapping from prefix to {@link OrdRange}. */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java
----------------------------------------------------------------------
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java b/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java
index 7659be8..60beddd 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java
@@ -32,7 +32,6 @@ import org.apache.lucene.facet.FacetsConfig;
 import org.apache.lucene.facet.LabelAndValue;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MatchAllDocsQuery;
@@ -227,41 +226,6 @@ public class TestSortedSetDocValuesFacets extends FacetTestCase {
     dir.close();
   }
 
-  public void testSlowCompositeReaderWrapper() throws Exception {
-    Directory dir = newDirectory();
-
-    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
-
-    FacetsConfig config = new FacetsConfig();
-
-    Document doc = new Document();
-    doc.add(new SortedSetDocValuesFacetField("a", "foo1"));
-    writer.addDocument(config.build(doc));
-
-    writer.commit();
-
-    doc = new Document();
-    doc.add(new SortedSetDocValuesFacetField("a", "foo2"));
-    writer.addDocument(config.build(doc));
-
-    // NRT open
-    IndexSearcher searcher = new IndexSearcher(SlowCompositeReaderWrapper.wrap(writer.getReader()));
-
-    // Per-top-reader state:
-    SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.getIndexReader());
-
-    FacetsCollector c = new FacetsCollector();
-    searcher.search(new MatchAllDocsQuery(), c);    
-    Facets facets = new SortedSetDocValuesFacetCounts(state, c);
-
-    // Ask for top 10 labels for any dims that have counts:
-    assertEquals("dim=a path=[] value=2 childCount=2\n  foo1 (1)\n  foo2 (1)\n", facets.getTopChildren(10, "a").toString());
-
-    writer.close();
-    IOUtils.close(searcher.getIndexReader(), dir);
-  }
-
-
   public void testRandom() throws Exception {
     String[] tokens = getRandomTokens(10);
     Directory indexDir = newDirectory();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
----------------------------------------------------------------------
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
index a3bda0b..2f51c94 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
@@ -44,7 +44,6 @@ import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.ReaderUtil;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
@@ -1164,16 +1163,7 @@ public class TestGrouping extends LuceneTestCase {
     final List<Collection<SearchGroup<BytesRef>>> shardGroups = new ArrayList<>();
     List<AbstractFirstPassGroupingCollector<?>> firstPassGroupingCollectors = new ArrayList<>();
     AbstractFirstPassGroupingCollector<?> firstPassCollector = null;
-    boolean shardsCanUseIDV;
-    if (canUseIDV) {
-      if (SlowCompositeReaderWrapper.class.isAssignableFrom(subSearchers[0].getIndexReader().getClass())) {
-        shardsCanUseIDV = false;
-      } else {
-        shardsCanUseIDV = !preFlex;
-      }
-    } else {
-      shardsCanUseIDV = false;
-    }
+    boolean shardsCanUseIDV = canUseIDV;
 
     String groupField = "group";
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/join/src/test/org/apache/lucene/search/join/TestJoinUtil.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/test/org/apache/lucene/search/join/TestJoinUtil.java b/lucene/join/src/test/org/apache/lucene/search/join/TestJoinUtil.java
index af507cd..2796e01 100644
--- a/lucene/join/src/test/org/apache/lucene/search/join/TestJoinUtil.java
+++ b/lucene/join/src/test/org/apache/lucene/search/join/TestJoinUtil.java
@@ -58,7 +58,6 @@ import org.apache.lucene.index.NoMergePolicy;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.index.Term;
@@ -558,7 +557,7 @@ public class TestJoinUtil extends LuceneTestCase {
     assertEquals(numParents, topDocs.totalHits);
     for (int i = 0; i < topDocs.scoreDocs.length; i++) {
       ScoreDoc scoreDoc = topDocs.scoreDocs[i];
-      String id = SlowCompositeReaderWrapper.wrap(searcher.getIndexReader()).document(scoreDoc.doc).get("id");
+      String id = searcher.doc(scoreDoc.doc).get("id");
       assertEquals(lowestScoresPerParent.get(id), scoreDoc.score, 0f);
     }
 
@@ -567,7 +566,7 @@ public class TestJoinUtil extends LuceneTestCase {
     assertEquals(numParents, topDocs.totalHits);
     for (int i = 0; i < topDocs.scoreDocs.length; i++) {
       ScoreDoc scoreDoc = topDocs.scoreDocs[i];
-      String id = SlowCompositeReaderWrapper.wrap(searcher.getIndexReader()).document(scoreDoc.doc).get("id");
+      String id = searcher.doc(scoreDoc.doc).get("id");
       assertEquals(highestScoresPerParent.get(id), scoreDoc.score, 0f);
     }
 
@@ -1229,8 +1228,7 @@ public class TestJoinUtil extends LuceneTestCase {
 
       final Map<Integer, JoinScore> docToJoinScore = new HashMap<>();
       if (multipleValuesPerDocument) {
-        LeafReader slowCompositeReader = SlowCompositeReaderWrapper.wrap(topLevelReader);
-        Terms terms = slowCompositeReader.terms(toField);
+        Terms terms = MultiFields.getTerms(topLevelReader, toField);
         if (terms != null) {
           PostingsEnum postingsEnum = null;
           SortedSet<BytesRef> joinValues = new TreeSet<>();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java
----------------------------------------------------------------------
diff --git a/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java b/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java
index e29e8c8..57e25fe 100644
--- a/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java
+++ b/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndexAgainstRAMDir.java
@@ -41,7 +41,6 @@ import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CompositeReader;
 import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexReader;
@@ -49,8 +48,10 @@ import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
+import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -66,8 +67,8 @@ import org.apache.lucene.search.spans.SpanOrQuery;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.RAMDirectory;
-import org.apache.lucene.util.ByteBlockPool;
 import org.apache.lucene.util.ByteBlockPool.Allocator;
+import org.apache.lucene.util.ByteBlockPool;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.LineFileDocs;
@@ -170,15 +171,14 @@ public class TestMemoryIndexAgainstRAMDir extends BaseTokenStreamTestCase {
 
   private void duellReaders(CompositeReader other, LeafReader memIndexReader)
       throws IOException {
-    LeafReader competitor = SlowCompositeReaderWrapper.wrap(other);
     Fields memFields = memIndexReader.fields();
-    for (String field : competitor.fields()) {
+    for (String field : MultiFields.getFields(other)) {
       Terms memTerms = memFields.terms(field);
       Terms iwTerms = memIndexReader.terms(field);
       if (iwTerms == null) {
         assertNull(memTerms);
       } else {
-        NumericDocValues normValues = competitor.getNormValues(field);
+        NumericDocValues normValues = MultiDocValues.getNormValues(other, field);
         NumericDocValues memNormValues = memIndexReader.getNormValues(field);
         if (normValues != null) {
           // mem idx always computes norms on the fly

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java b/lucene/misc/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java
new file mode 100644
index 0000000..de79ab0
--- /dev/null
+++ b/lucene/misc/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.index;
+
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.index.MultiDocValues.MultiSortedDocValues;
+import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
+import org.apache.lucene.index.MultiDocValues.OrdinalMap;
+import org.apache.lucene.util.Bits;
+
+/**
+ * This class forces a composite reader (eg a {@link
+ * MultiReader} or {@link DirectoryReader}) to emulate a
+ * {@link LeafReader}.  This requires implementing the postings
+ * APIs on-the-fly, using the static methods in {@link
+ * MultiFields}, {@link MultiDocValues}, by stepping through
+ * the sub-readers to merge fields/terms, appending docs, etc.
+ *
+ * <p><b>NOTE</b>: this class almost always results in a
+ * performance hit.  If this is important to your use case,
+ * you'll get better performance by gathering the sub readers using
+ * {@link IndexReader#getContext()} to get the
+ * leaves and then operate per-LeafReader,
+ * instead of using this class.
+ */
+
+public final class SlowCompositeReaderWrapper extends LeafReader {
+
+  private final CompositeReader in;
+  private final Fields fields;
+  private final boolean merging;
+  
+  /** This method is sugar for getting an {@link LeafReader} from
+   * an {@link IndexReader} of any kind. If the reader is already atomic,
+   * it is returned unchanged, otherwise wrapped by this class.
+   */
+  public static LeafReader wrap(IndexReader reader) throws IOException {
+    if (reader instanceof CompositeReader) {
+      return new SlowCompositeReaderWrapper((CompositeReader) reader, false);
+    } else {
+      assert reader instanceof LeafReader;
+      return (LeafReader) reader;
+    }
+  }
+
+  SlowCompositeReaderWrapper(CompositeReader reader, boolean merging) throws IOException {
+    super();
+    in = reader;
+    if (getFieldInfos().hasPointValues()) {
+      throw new IllegalArgumentException("cannot wrap points");
+    }
+    fields = MultiFields.getFields(in);
+    in.registerParentReader(this);
+    this.merging = merging;
+  }
+
+  @Override
+  public String toString() {
+    return "SlowCompositeReaderWrapper(" + in + ")";
+  }
+
+  @Override
+  public void addCoreClosedListener(CoreClosedListener listener) {
+    addCoreClosedListenerAsReaderClosedListener(in, listener);
+  }
+
+  @Override
+  public void removeCoreClosedListener(CoreClosedListener listener) {
+    removeCoreClosedListenerAsReaderClosedListener(in, listener);
+  }
+
+  @Override
+  public Fields fields() {
+    ensureOpen();
+    return fields;
+  }
+
+  @Override
+  public NumericDocValues getNumericDocValues(String field) throws IOException {
+    ensureOpen();
+    return MultiDocValues.getNumericValues(in, field);
+  }
+
+  @Override
+  public Bits getDocsWithField(String field) throws IOException {
+    ensureOpen();
+    return MultiDocValues.getDocsWithField(in, field);
+  }
+
+  @Override
+  public BinaryDocValues getBinaryDocValues(String field) throws IOException {
+    ensureOpen();
+    return MultiDocValues.getBinaryValues(in, field);
+  }
+  
+  @Override
+  public SortedNumericDocValues getSortedNumericDocValues(String field) throws IOException {
+    ensureOpen();
+    return MultiDocValues.getSortedNumericValues(in, field);
+  }
+
+  @Override
+  public SortedDocValues getSortedDocValues(String field) throws IOException {
+    ensureOpen();
+    OrdinalMap map = null;
+    synchronized (cachedOrdMaps) {
+      map = cachedOrdMaps.get(field);
+      if (map == null) {
+        // uncached, or not a multi dv
+        SortedDocValues dv = MultiDocValues.getSortedValues(in, field);
+        if (dv instanceof MultiSortedDocValues) {
+          map = ((MultiSortedDocValues)dv).mapping;
+          if (map.owner == getCoreCacheKey() && merging == false) {
+            cachedOrdMaps.put(field, map);
+          }
+        }
+        return dv;
+      }
+    }
+    int size = in.leaves().size();
+    final SortedDocValues[] values = new SortedDocValues[size];
+    final int[] starts = new int[size+1];
+    for (int i = 0; i < size; i++) {
+      LeafReaderContext context = in.leaves().get(i);
+      final LeafReader reader = context.reader();
+      final FieldInfo fieldInfo = reader.getFieldInfos().fieldInfo(field);
+      if (fieldInfo != null && fieldInfo.getDocValuesType() != DocValuesType.SORTED) {
+        return null;
+      }
+      SortedDocValues v = reader.getSortedDocValues(field);
+      if (v == null) {
+        v = DocValues.emptySorted();
+      }
+      values[i] = v;
+      starts[i] = context.docBase;
+    }
+    starts[size] = maxDoc();
+    return new MultiSortedDocValues(values, starts, map);
+  }
+  
+  @Override
+  public SortedSetDocValues getSortedSetDocValues(String field) throws IOException {
+    ensureOpen();
+    OrdinalMap map = null;
+    synchronized (cachedOrdMaps) {
+      map = cachedOrdMaps.get(field);
+      if (map == null) {
+        // uncached, or not a multi dv
+        SortedSetDocValues dv = MultiDocValues.getSortedSetValues(in, field);
+        if (dv instanceof MultiSortedSetDocValues) {
+          map = ((MultiSortedSetDocValues)dv).mapping;
+          if (map.owner == getCoreCacheKey() && merging == false) {
+            cachedOrdMaps.put(field, map);
+          }
+        }
+        return dv;
+      }
+    }
+   
+    assert map != null;
+    int size = in.leaves().size();
+    final SortedSetDocValues[] values = new SortedSetDocValues[size];
+    final int[] starts = new int[size+1];
+    for (int i = 0; i < size; i++) {
+      LeafReaderContext context = in.leaves().get(i);
+      final LeafReader reader = context.reader();
+      final FieldInfo fieldInfo = reader.getFieldInfos().fieldInfo(field);
+      if(fieldInfo != null && fieldInfo.getDocValuesType() != DocValuesType.SORTED_SET){
+        return null;
+      }
+      SortedSetDocValues v = reader.getSortedSetDocValues(field);
+      if (v == null) {
+        v = DocValues.emptySortedSet();
+      }
+      values[i] = v;
+      starts[i] = context.docBase;
+    }
+    starts[size] = maxDoc();
+    return new MultiSortedSetDocValues(values, starts, map);
+  }
+  
+  // TODO: this could really be a weak map somewhere else on the coreCacheKey,
+  // but do we really need to optimize slow-wrapper any more?
+  private final Map<String,OrdinalMap> cachedOrdMaps = new HashMap<>();
+
+  @Override
+  public NumericDocValues getNormValues(String field) throws IOException {
+    ensureOpen();
+    return MultiDocValues.getNormValues(in, field);
+  }
+  
+  @Override
+  public Fields getTermVectors(int docID) throws IOException {
+    ensureOpen();
+    return in.getTermVectors(docID);
+  }
+
+  @Override
+  public int numDocs() {
+    // Don't call ensureOpen() here (it could affect performance)
+    return in.numDocs();
+  }
+
+  @Override
+  public int maxDoc() {
+    // Don't call ensureOpen() here (it could affect performance)
+    return in.maxDoc();
+  }
+
+  @Override
+  public void document(int docID, StoredFieldVisitor visitor) throws IOException {
+    ensureOpen();
+    in.document(docID, visitor);
+  }
+
+  @Override
+  public Bits getLiveDocs() {
+    ensureOpen();
+    return MultiFields.getLiveDocs(in);
+  }
+
+  @Override
+  public PointValues getPointValues() {
+    ensureOpen();
+    return null;
+  }
+
+  @Override
+  public FieldInfos getFieldInfos() {
+    ensureOpen();
+    return MultiFields.getMergedFieldInfos(in);
+  }
+
+  @Override
+  public Object getCoreCacheKey() {
+    return in.getCoreCacheKey();
+  }
+
+  @Override
+  public Object getCombinedCoreAndDeletesKey() {
+    return in.getCombinedCoreAndDeletesKey();
+  }
+
+  @Override
+  protected void doClose() throws IOException {
+    // TODO: as this is a wrapper, should we really close the delegate?
+    in.close();
+  }
+
+  @Override
+  public void checkIntegrity() throws IOException {
+    ensureOpen();
+    for (LeafReaderContext ctx : in.leaves()) {
+      ctx.reader().checkIntegrity();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/index/TestSlowCompositeReaderWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/index/TestSlowCompositeReaderWrapper.java b/lucene/misc/src/test/org/apache/lucene/index/TestSlowCompositeReaderWrapper.java
new file mode 100644
index 0000000..d37e45a
--- /dev/null
+++ b/lucene/misc/src/test/org/apache/lucene/index/TestSlowCompositeReaderWrapper.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.index;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+
+public class TestSlowCompositeReaderWrapper extends LuceneTestCase {
+
+  public void testCoreListenerOnSlowCompositeReaderWrapper() throws IOException {
+    RandomIndexWriter w = new RandomIndexWriter(random(), newDirectory());
+    final int numDocs = TestUtil.nextInt(random(), 1, 5);
+    for (int i = 0; i < numDocs; ++i) {
+      w.addDocument(new Document());
+      if (random().nextBoolean()) {
+        w.commit();
+      }
+    }
+    w.commit();
+    w.close();
+
+    final IndexReader reader = DirectoryReader.open(w.w.getDirectory());
+    final LeafReader leafReader = SlowCompositeReaderWrapper.wrap(reader);
+    
+    final int numListeners = TestUtil.nextInt(random(), 1, 10);
+    final List<LeafReader.CoreClosedListener> listeners = new ArrayList<>();
+    AtomicInteger counter = new AtomicInteger(numListeners);
+    
+    for (int i = 0; i < numListeners; ++i) {
+      CountCoreListener listener = new CountCoreListener(counter, leafReader.getCoreCacheKey());
+      listeners.add(listener);
+      leafReader.addCoreClosedListener(listener);
+    }
+    for (int i = 0; i < 100; ++i) {
+      leafReader.addCoreClosedListener(listeners.get(random().nextInt(listeners.size())));
+    }
+    final int removed = random().nextInt(numListeners);
+    Collections.shuffle(listeners, random());
+    for (int i = 0; i < removed; ++i) {
+      leafReader.removeCoreClosedListener(listeners.get(i));
+    }
+    assertEquals(numListeners, counter.get());
+    // make sure listeners are registered on the wrapped reader and that closing any of them has the same effect
+    if (random().nextBoolean()) {
+      reader.close();
+    } else {
+      leafReader.close();
+    }
+    assertEquals(removed, counter.get());
+    w.w.getDirectory().close();
+  }
+
+  private static final class CountCoreListener implements LeafReader.CoreClosedListener {
+
+    private final AtomicInteger count;
+    private final Object coreCacheKey;
+
+    public CountCoreListener(AtomicInteger count, Object coreCacheKey) {
+      this.count = count;
+      this.coreCacheKey = coreCacheKey;
+    }
+
+    @Override
+    public void onClose(Object coreCacheKey) {
+      assertSame(this.coreCacheKey, coreCacheKey);
+      count.decrementAndGet();
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestDocTermOrds.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestDocTermOrds.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestDocTermOrds.java
index 4861cd3..0c5d765 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestDocTermOrds.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestDocTermOrds.java
@@ -443,9 +443,9 @@ public class TestDocTermOrds extends LuceneTestCase {
     iw.deleteDocuments(new Term("foo", "baz"));
     DirectoryReader r2 = DirectoryReader.open(iw);
     
-    FieldCache.DEFAULT.getDocTermOrds(getOnlySegmentReader(r2), "foo", null);
+    FieldCache.DEFAULT.getDocTermOrds(getOnlyLeafReader(r2), "foo", null);
     
-    SortedSetDocValues v = FieldCache.DEFAULT.getDocTermOrds(getOnlySegmentReader(r1), "foo", null);
+    SortedSetDocValues v = FieldCache.DEFAULT.getDocTermOrds(getOnlyLeafReader(r1), "foo", null);
     assertEquals(3, v.getValueCount());
     v.setDocument(1);
     assertEquals(1, v.nextOrd());
@@ -473,7 +473,7 @@ public class TestDocTermOrds extends LuceneTestCase {
     iw.close();
     
     DirectoryReader ir = DirectoryReader.open(dir);
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     SortedSetDocValues v = FieldCache.DEFAULT.getDocTermOrds(ar, "foo", FieldCache.INT32_TERM_PREFIX);
     assertEquals(2, v.getValueCount());
@@ -514,7 +514,7 @@ public class TestDocTermOrds extends LuceneTestCase {
     iw.close();
     
     DirectoryReader ir = DirectoryReader.open(dir);
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     SortedSetDocValues v = FieldCache.DEFAULT.getDocTermOrds(ar, "foo", FieldCache.INT64_TERM_PREFIX);
     assertEquals(2, v.getValueCount());
@@ -563,7 +563,7 @@ public class TestDocTermOrds extends LuceneTestCase {
     DirectoryReader ireader = iwriter.getReader();
     iwriter.close();
 
-    LeafReader ar = getOnlySegmentReader(ireader);
+    LeafReader ar = getOnlyLeafReader(ireader);
     SortedSetDocValues dv = FieldCache.DEFAULT.getDocTermOrds(ar, "field", null);
     assertEquals(3, dv.getValueCount());
     
@@ -648,7 +648,7 @@ public class TestDocTermOrds extends LuceneTestCase {
     iw.close();
     
     DirectoryReader ir = DirectoryReader.open(dir);
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     SortedSetDocValues v = FieldCache.DEFAULT.getDocTermOrds(ar, "foo", null);
     assertNotNull(DocValues.unwrapSingleton(v)); // actually a single-valued field

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCache.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCache.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCache.java
index 1b322d9..93c302c 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCache.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCache.java
@@ -419,7 +419,7 @@ public class TestFieldCache extends LuceneTestCase {
     iw.addDocument(doc);
     DirectoryReader ir = iw.getReader();
     iw.close();
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     // Binary type: can be retrieved via getTerms()
     expectThrows(IllegalStateException.class, () -> {
@@ -535,7 +535,7 @@ public class TestFieldCache extends LuceneTestCase {
     DirectoryReader ir = iw.getReader();
     iw.close();
     
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     final FieldCache cache = FieldCache.DEFAULT;
     cache.purgeAllCaches();
@@ -593,7 +593,7 @@ public class TestFieldCache extends LuceneTestCase {
     DirectoryReader ir = iw.getReader();
     iw.close();
     
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     final FieldCache cache = FieldCache.DEFAULT;
     cache.purgeAllCaches();
@@ -673,7 +673,7 @@ public class TestFieldCache extends LuceneTestCase {
     }
     iw.forceMerge(1);
     final DirectoryReader reader = iw.getReader();
-    final NumericDocValues longs = FieldCache.DEFAULT.getNumerics(getOnlySegmentReader(reader), "f", FieldCache.LONG_POINT_PARSER, false);
+    final NumericDocValues longs = FieldCache.DEFAULT.getNumerics(getOnlyLeafReader(reader), "f", FieldCache.LONG_POINT_PARSER, false);
     for (int i = 0; i < values.length; ++i) {
       assertEquals(values[i], longs.get(i));
     }
@@ -719,7 +719,7 @@ public class TestFieldCache extends LuceneTestCase {
     }
     iw.forceMerge(1);
     final DirectoryReader reader = iw.getReader();
-    final NumericDocValues ints = FieldCache.DEFAULT.getNumerics(getOnlySegmentReader(reader), "f", FieldCache.INT_POINT_PARSER, false);
+    final NumericDocValues ints = FieldCache.DEFAULT.getNumerics(getOnlyLeafReader(reader), "f", FieldCache.INT_POINT_PARSER, false);
     for (int i = 0; i < values.length; ++i) {
       assertEquals(values[i], ints.get(i));
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheReopen.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheReopen.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheReopen.java
index 0d5584e..de8eab1 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheReopen.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheReopen.java
@@ -47,7 +47,7 @@ public class TestFieldCacheReopen extends LuceneTestCase {
   
     // Open reader1
     DirectoryReader r = DirectoryReader.open(dir);
-    LeafReader r1 = getOnlySegmentReader(r);
+    LeafReader r1 = getOnlyLeafReader(r);
     final NumericDocValues ints = FieldCache.DEFAULT.getNumerics(r1, "number", FieldCache.INT_POINT_PARSER, false);
     assertEquals(17, ints.get(0));
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheVsDocValues.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheVsDocValues.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheVsDocValues.java
index 23b7d0c..9809324 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheVsDocValues.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheVsDocValues.java
@@ -399,7 +399,7 @@ public class TestFieldCacheVsDocValues extends LuceneTestCase {
     
     // now compare again after the merge
     ir = writer.getReader();
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     SortedSetDocValues expected = FieldCache.DEFAULT.getDocTermOrds(ar, "indexed", null);
     SortedSetDocValues actual = ar.getSortedSetDocValues("dv");
     assertEquals(ir.maxDoc(), expected, actual);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheWithThreads.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheWithThreads.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheWithThreads.java
index e716419..3f1f450 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheWithThreads.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestFieldCacheWithThreads.java
@@ -181,7 +181,7 @@ public class TestFieldCacheWithThreads extends LuceneTestCase {
     final DirectoryReader r = writer.getReader();
     writer.close();
     
-    final LeafReader sr = getOnlySegmentReader(r);
+    final LeafReader sr = getOnlyLeafReader(r);
 
     final long END_TIME = System.currentTimeMillis() + (TEST_NIGHTLY ? 30 : 1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/misc/src/test/org/apache/lucene/uninverting/TestLegacyFieldCache.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/uninverting/TestLegacyFieldCache.java b/lucene/misc/src/test/org/apache/lucene/uninverting/TestLegacyFieldCache.java
index c4ef1c4..4fd66ad 100644
--- a/lucene/misc/src/test/org/apache/lucene/uninverting/TestLegacyFieldCache.java
+++ b/lucene/misc/src/test/org/apache/lucene/uninverting/TestLegacyFieldCache.java
@@ -307,7 +307,7 @@ public class TestLegacyFieldCache extends LuceneTestCase {
     iw.addDocument(doc);
     DirectoryReader ir = iw.getReader();
     iw.close();
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     // Binary type: can be retrieved via getTerms()
     expectThrows(IllegalStateException.class, () -> {
@@ -340,7 +340,7 @@ public class TestLegacyFieldCache extends LuceneTestCase {
     DirectoryReader ir = iw.getReader();
     iw.close();
     
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     final FieldCache cache = FieldCache.DEFAULT;
     cache.purgeAllCaches();
@@ -379,7 +379,7 @@ public class TestLegacyFieldCache extends LuceneTestCase {
     DirectoryReader ir = iw.getReader();
     iw.close();
     
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     final FieldCache cache = FieldCache.DEFAULT;
     cache.purgeAllCaches();
@@ -440,7 +440,7 @@ public class TestLegacyFieldCache extends LuceneTestCase {
     }
     iw.forceMerge(1);
     final DirectoryReader reader = iw.getReader();
-    final NumericDocValues longs = FieldCache.DEFAULT.getNumerics(getOnlySegmentReader(reader), "f", FieldCache.LEGACY_LONG_PARSER, false);
+    final NumericDocValues longs = FieldCache.DEFAULT.getNumerics(getOnlyLeafReader(reader), "f", FieldCache.LEGACY_LONG_PARSER, false);
     for (int i = 0; i < values.length; ++i) {
       assertEquals(values[i], longs.get(i));
     }
@@ -486,7 +486,7 @@ public class TestLegacyFieldCache extends LuceneTestCase {
     }
     iw.forceMerge(1);
     final DirectoryReader reader = iw.getReader();
-    final NumericDocValues ints = FieldCache.DEFAULT.getNumerics(getOnlySegmentReader(reader), "f", FieldCache.LEGACY_INT_PARSER, false);
+    final NumericDocValues ints = FieldCache.DEFAULT.getNumerics(getOnlyLeafReader(reader), "f", FieldCache.LEGACY_INT_PARSER, false);
     for (int i = 0; i < values.length; ++i) {
       assertEquals(values[i], ints.get(i));
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/queries/src/test/org/apache/lucene/queries/CommonTermsQueryTest.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/CommonTermsQueryTest.java b/lucene/queries/src/test/org/apache/lucene/queries/CommonTermsQueryTest.java
index a7bfffd..e991b0c 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/CommonTermsQueryTest.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/CommonTermsQueryTest.java
@@ -32,7 +32,6 @@ import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
 import org.apache.lucene.index.Terms;
@@ -399,8 +398,9 @@ public class CommonTermsQueryTest extends LuceneTestCase {
     analyzer.setMaxTokenLength(TestUtil.nextInt(random(), 1, IndexWriter.MAX_TERM_LENGTH));
     RandomIndexWriter w = new RandomIndexWriter(random(), dir, analyzer);
     createRandomIndex(atLeast(50), w, random().nextLong());
+    w.forceMerge(1);
     DirectoryReader reader = w.getReader();
-    LeafReader wrapper = SlowCompositeReaderWrapper.wrap(reader);
+    LeafReader wrapper = getOnlyLeafReader(reader);
     String field = "body";
     Terms terms = wrapper.terms(field);
     PriorityQueue<TermAndFreq> lowFreqQueue = new PriorityQueue<CommonTermsQueryTest.TermAndFreq>(
@@ -489,7 +489,7 @@ public class CommonTermsQueryTest extends LuceneTestCase {
       QueryUtils.check(random(), cq, newSearcher(reader2));
       reader2.close();
     } finally {
-      IOUtils.close(reader, wrapper, w, dir, analyzer);
+      IOUtils.close(wrapper, w, dir, analyzer);
     }
     
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/queries/src/test/org/apache/lucene/queries/TermsQueryTest.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/TermsQueryTest.java b/lucene/queries/src/test/org/apache/lucene/queries/TermsQueryTest.java
index c14d543..a87e45d 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/TermsQueryTest.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/TermsQueryTest.java
@@ -342,11 +342,11 @@ public class TermsQueryTest extends LuceneTestCase {
     w.close();
     TermsQuery query = new TermsQuery(new Term("foo", "bar"), new Term("foo", "baz"));
     UsageTrackingQueryCachingPolicy policy = new UsageTrackingQueryCachingPolicy();
-    assertFalse(policy.shouldCache(query, getOnlySegmentReader(reader).getContext()));
+    assertFalse(policy.shouldCache(query, getOnlyLeafReader(reader).getContext()));
     policy.onUse(query);
     policy.onUse(query);
     // cached after two uses
-    assertTrue(policy.shouldCache(query, getOnlySegmentReader(reader).getContext()));
+    assertTrue(policy.shouldCache(query, getOnlyLeafReader(reader).getContext()));
     reader.close();
     dir.close();
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
index d028dce..b72bfeb 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
@@ -50,7 +50,7 @@ public class TestSortedSetFieldSource extends LuceneTestCase {
 
     DirectoryReader ir = DirectoryReader.open(dir);
     IndexSearcher searcher = newSearcher(ir);
-    LeafReader ar = getOnlySegmentReader(ir);
+    LeafReader ar = getOnlyLeafReader(ir);
     
     ValueSource vs = new SortedSetFieldSource("value");
     FunctionValues values = vs.getValues(Collections.emptyMap(), ar.getContext());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7523ca11/lucene/queries/src/test/org/apache/lucene/queries/payloads/PayloadHelper.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/payloads/PayloadHelper.java b/lucene/queries/src/test/org/apache/lucene/queries/payloads/PayloadHelper.java
index 484c1bd..cfd5156 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/payloads/PayloadHelper.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/payloads/PayloadHelper.java
@@ -126,10 +126,11 @@ public class PayloadHelper {
       doc.add(new TextField(NO_PAYLOAD_FIELD, English.intToEnglish(i), Field.Store.YES));
       writer.addDocument(doc);
     }
+    writer.forceMerge(1);
     reader = DirectoryReader.open(writer);
     writer.close();
 
-    IndexSearcher searcher = LuceneTestCase.newSearcher(reader);
+    IndexSearcher searcher = LuceneTestCase.newSearcher(LuceneTestCase.getOnlyLeafReader(reader));
     searcher.setSimilarity(similarity);
     return searcher;
   }