You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2012/06/19 09:39:37 UTC

svn commit: r1351591 [1/3] - in /lucene/dev/branches/branch_4x: ./ lucene/ lucene/core/ lucene/core/src/java/org/apache/lucene/index/ lucene/core/src/java/org/apache/lucene/search/ lucene/core/src/java/org/apache/lucene/search/payloads/ lucene/core/src...

Author: uschindler
Date: Tue Jun 19 07:39:34 2012
New Revision: 1351591

URL: http://svn.apache.org/viewvc?rev=1351591&view=rev
Log:
Merged revision(s) 1351590 from lucene/dev/trunk:
LUCENE-3866: CompositeReader.getSequentialSubReaders() now returns unmodifiable List<? extends IndexReader>. ReaderUtil.Gather was removed, as IndexReaderContext.leaves() is now the preferred way to access sub-readers

Added:
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderSlice.java
      - copied unchanged from r1351590, lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/ReaderSlice.java
Modified:
    lucene/dev/branches/branch_4x/   (props changed)
    lucene/dev/branches/branch_4x/lucene/   (props changed)
    lucene/dev/branches/branch_4x/lucene/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_4x/lucene/core/   (props changed)
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/AtomicReaderContext.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReaderContext.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocValues.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsAndPositionsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFields.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTerms.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTermsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentMerger.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/BitsSlice.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/MultiBits.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderUtil.java
    lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/TermContext.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/codecs/lucene40/TestReuseDocsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDeletionPolicy.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDocValuesIndexing.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDocsAndPositions.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterCommit.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterForceMerge.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestThreadedForceMerge.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTypePromotion.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestShardSearching.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/spans/MultiSpansWrapper.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
    lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
    lucene/dev/branches/branch_4x/lucene/grouping/   (props changed)
    lucene/dev/branches/branch_4x/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
    lucene/dev/branches/branch_4x/lucene/join/   (props changed)
    lucene/dev/branches/branch_4x/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
    lucene/dev/branches/branch_4x/lucene/misc/   (props changed)
    lucene/dev/branches/branch_4x/lucene/misc/src/java/org/apache/lucene/index/MultiPassIndexSplitter.java
    lucene/dev/branches/branch_4x/lucene/misc/src/java/org/apache/lucene/index/PKIndexSplitter.java
    lucene/dev/branches/branch_4x/lucene/misc/src/java/org/apache/lucene/misc/HighFreqTerms.java
    lucene/dev/branches/branch_4x/lucene/misc/src/test/org/apache/lucene/index/TestBalancedSegmentMergePolicy.java
    lucene/dev/branches/branch_4x/lucene/misc/src/test/org/apache/lucene/index/TestIndexSplitter.java
    lucene/dev/branches/branch_4x/lucene/queries/   (props changed)
    lucene/dev/branches/branch_4x/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java
    lucene/dev/branches/branch_4x/lucene/queryparser/   (props changed)
    lucene/dev/branches/branch_4x/lucene/queryparser/src/test/org/apache/lucene/queryparser/xml/TestParser.java
    lucene/dev/branches/branch_4x/lucene/suggest/   (props changed)
    lucene/dev/branches/branch_4x/lucene/suggest/src/java/org/apache/lucene/search/spell/SpellChecker.java
    lucene/dev/branches/branch_4x/lucene/test-framework/   (props changed)
    lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/search/QueryUtils.java
    lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
    lucene/dev/branches/branch_4x/solr/   (props changed)
    lucene/dev/branches/branch_4x/solr/core/   (props changed)
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/SpellCheckComponent.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/PerSegmentSingleValuedFaceting.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
    lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/update/VersionInfo.java
    lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/search/TestDocSet.java
    lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/search/TestIndexSearcher.java
    lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/search/TestSort.java

Modified: lucene/dev/branches/branch_4x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/CHANGES.txt?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/lucene/CHANGES.txt Tue Jun 19 07:39:34 2012
@@ -273,6 +273,11 @@ Changes in backwards compatibility polic
 
 * LUCENE-4055: You can't put foreign files into the index dir anymore.
 
+* LUCENE-3866: CompositeReader.getSequentialSubReaders() now returns
+  unmodifiable List<? extends IndexReader>. ReaderUtil.Gather was
+  removed, as IndexReaderContext.leaves() is now the preferred way
+  to access sub-readers.  (Uwe Schindler)
+
 Changes in Runtime Behavior
 
 * LUCENE-2846: omitNorms now behaves like omitTermFrequencyAndPositions, if you
@@ -531,6 +536,10 @@ API Changes
   which can be used to change the IndexWriter's live settings. IndexWriterConfig 
   is used only for initializing the IndexWriter. (Shai Erera)
 
+* LUCENE-3866: IndexReaderContext.leaves() is now the preferred way to access
+  atomic sub-readers of any kind of IndexReader (for AtomicReaders it returns
+  itsself as only leaf with docBase=0).  (Uwe Schindler)
+
 New features
 
 * LUCENE-2604: Added RegexpQuery support to QueryParser. Regular expressions

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/AtomicReaderContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/AtomicReaderContext.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/AtomicReaderContext.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/AtomicReaderContext.java Tue Jun 19 07:39:34 2012
@@ -1,5 +1,8 @@
 package org.apache.lucene.index;
 
+import java.util.Collections;
+import java.util.List;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -28,7 +31,7 @@ public final class AtomicReaderContext e
   public final int docBase;
   
   private final AtomicReader reader;
-  private final AtomicReaderContext[] leaves;
+  private final List<AtomicReaderContext> leaves;
   
   /**
    * Creates a new {@link AtomicReaderContext} 
@@ -39,7 +42,7 @@ public final class AtomicReaderContext e
     this.ord = leafOrd;
     this.docBase = leafDocBase;
     this.reader = reader;
-    this.leaves = isTopLevel ? new AtomicReaderContext[] { this } : null;
+    this.leaves = isTopLevel ? Collections.singletonList(this) : null;
   }
   
   AtomicReaderContext(AtomicReader atomicReader) {
@@ -47,12 +50,15 @@ public final class AtomicReaderContext e
   }
   
   @Override
-  public AtomicReaderContext[] leaves() {
+  public List<AtomicReaderContext> leaves() {
+    if (!isTopLevel)
+      throw new UnsupportedOperationException("This is not a top-level context.");
+    assert leaves != null;
     return leaves;
   }
   
   @Override
-  public IndexReaderContext[] children() {
+  public List<IndexReaderContext> children() {
     return null;
   }
   

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/BaseCompositeReader.java Tue Jun 19 07:39:34 2012
@@ -18,6 +18,9 @@ package org.apache.lucene.index;
  */
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.ReaderUtil;
@@ -47,12 +50,16 @@ import org.apache.lucene.util.ReaderUtil
  * @lucene.internal
  */
 public abstract class BaseCompositeReader<R extends IndexReader> extends CompositeReader {
-  protected final R[] subReaders;
-  protected final int[] starts;       // 1st docno for each reader
+  private final R[] subReaders;
+  private final int[] starts;       // 1st docno for each reader
   private final int maxDoc;
   private final int numDocs;
   private final boolean hasDeletions;
-  
+
+  /** List view solely for {@link #getSequentialSubReaders()},
+   * for effectiveness the array is used internally. */
+  private final List<R> subReadersList;
+
   /**
    * Constructs a {@code BaseCompositeReader} on the given subReaders.
    * @param subReaders the wrapped sub-readers. This array is returned by
@@ -63,6 +70,7 @@ public abstract class BaseCompositeReade
    */
   protected BaseCompositeReader(R[] subReaders) throws IOException {
     this.subReaders = subReaders;
+    this.subReadersList = Collections.unmodifiableList(Arrays.asList(subReaders));
     starts = new int[subReaders.length + 1];    // build starts array
     int maxDoc = 0, numDocs = 0;
     boolean hasDeletions = false;
@@ -135,8 +143,16 @@ public abstract class BaseCompositeReade
     return ReaderUtil.subIndex(docID, this.starts);
   }
   
+  /** Helper method for subclasses to get the docBase of the given sub-reader index. */
+  protected final int readerBase(int readerIndex) {
+    if (readerIndex < 0 || readerIndex >= subReaders.length) {
+      throw new IllegalArgumentException("readerIndex must be >= 0 and < getSequentialSubReaders().size()");
+    }
+    return this.starts[readerIndex];
+  }
+  
   @Override
-  public final R[] getSequentialSubReaders() {
-    return subReaders;
+  public final List<? extends R> getSequentialSubReaders() {
+    return subReadersList;
   }
 }

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReader.java Tue Jun 19 07:39:34 2012
@@ -17,6 +17,8 @@ package org.apache.lucene.index;
  * limitations under the License.
  */
 
+import java.util.List;
+
 import org.apache.lucene.search.SearcherManager; // javadocs
 import org.apache.lucene.store.*;
 
@@ -63,12 +65,12 @@ public abstract class CompositeReader ex
     final StringBuilder buffer = new StringBuilder();
     buffer.append(getClass().getSimpleName());
     buffer.append('(');
-    final IndexReader[] subReaders = getSequentialSubReaders();
+    final List<? extends IndexReader> subReaders = getSequentialSubReaders();
     assert subReaders != null;
-    if (subReaders.length > 0) {
-      buffer.append(subReaders[0]);
-      for (int i = 1; i < subReaders.length; ++i) {
-        buffer.append(" ").append(subReaders[i]);
+    if (!subReaders.isEmpty()) {
+      buffer.append(subReaders.get(0));
+      for (int i = 1, c = subReaders.size(); i < c; ++i) {
+        buffer.append(" ").append(subReaders.get(i));
       }
     }
     buffer.append(')');
@@ -81,11 +83,8 @@ public abstract class CompositeReader ex
    *  If this method returns an empty array, that means this
    *  reader is a null reader (for example a MultiReader
    *  that has no sub readers).
-   *  <p><b>Warning:</b> Don't modify the returned array!
-   *  Doing so will corrupt the internal structure of this
-   *  {@code CompositeReader}.
    */
-  public abstract IndexReader[] getSequentialSubReaders();
+  public abstract List<? extends IndexReader> getSequentialSubReaders();
 
   @Override
   public final CompositeReaderContext getTopReaderContext() {

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReaderContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReaderContext.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReaderContext.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/CompositeReaderContext.java Tue Jun 19 07:39:34 2012
@@ -17,16 +17,18 @@ package org.apache.lucene.index;
  * limitations under the License.
  */
 
-import java.io.IOException;
-import org.apache.lucene.util.ReaderUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * {@link IndexReaderContext} for {@link CompositeReader} instance.
  * @lucene.experimental
  */
 public final class CompositeReaderContext extends IndexReaderContext {
-  private final IndexReaderContext[] children;
-  private final AtomicReaderContext[] leaves;
+  private final List<IndexReaderContext> children;
+  private final List<AtomicReaderContext> leaves;
   private final CompositeReader reader;
   
   static CompositeReaderContext create(CompositeReader reader) {
@@ -38,34 +40,37 @@ public final class CompositeReaderContex
    * not top-level readers in the current context
    */
   CompositeReaderContext(CompositeReaderContext parent, CompositeReader reader,
-      int ordInParent, int docbaseInParent, IndexReaderContext[] children) {
+      int ordInParent, int docbaseInParent, List<IndexReaderContext> children) {
     this(parent, reader, ordInParent, docbaseInParent, children, null);
   }
   
   /**
    * Creates a {@link CompositeReaderContext} for top-level readers with parent set to <code>null</code>
    */
-  CompositeReaderContext(CompositeReader reader, IndexReaderContext[] children, AtomicReaderContext[] leaves) {
+  CompositeReaderContext(CompositeReader reader, List<IndexReaderContext> children, List<AtomicReaderContext> leaves) {
     this(null, reader, 0, 0, children, leaves);
   }
   
   private CompositeReaderContext(CompositeReaderContext parent, CompositeReader reader,
-      int ordInParent, int docbaseInParent, IndexReaderContext[] children,
-      AtomicReaderContext[] leaves) {
+      int ordInParent, int docbaseInParent, List<IndexReaderContext> children,
+      List<AtomicReaderContext> leaves) {
     super(parent, ordInParent, docbaseInParent);
-    this.children = children;
-    this.leaves = leaves;
+    this.children = Collections.unmodifiableList(children);
+    this.leaves = leaves == null ? null : Collections.unmodifiableList(leaves);
     this.reader = reader;
   }
 
   @Override
-  public AtomicReaderContext[] leaves() {
+  public List<AtomicReaderContext> leaves() {
+    if (!isTopLevel)
+      throw new UnsupportedOperationException("This is not a top-level context.");
+    assert leaves != null;
     return leaves;
   }
   
   
   @Override
-  public IndexReaderContext[] children() {
+  public List<IndexReaderContext> children() {
     return children;
   }
   
@@ -76,13 +81,11 @@ public final class CompositeReaderContex
   
   private static final class Builder {
     private final CompositeReader reader;
-    private final AtomicReaderContext[] leaves;
-    private int leafOrd = 0;
+    private final List<AtomicReaderContext> leaves = new ArrayList<AtomicReaderContext>();
     private int leafDocBase = 0;
     
     public Builder(CompositeReader reader) {
       this.reader = reader;
-      leaves = new AtomicReaderContext[numLeaves(reader)];
     }
     
     public CompositeReaderContext build() {
@@ -92,14 +95,14 @@ public final class CompositeReaderContex
     private IndexReaderContext build(CompositeReaderContext parent, IndexReader reader, int ord, int docBase) {
       if (reader instanceof AtomicReader) {
         final AtomicReader ar = (AtomicReader) reader;
-        final AtomicReaderContext atomic = new AtomicReaderContext(parent, ar, ord, docBase, leafOrd, leafDocBase);
-        leaves[leafOrd++] = atomic;
+        final AtomicReaderContext atomic = new AtomicReaderContext(parent, ar, ord, docBase, leaves.size(), leafDocBase);
+        leaves.add(atomic);
         leafDocBase += reader.maxDoc();
         return atomic;
       } else {
         final CompositeReader cr = (CompositeReader) reader;
-        final IndexReader[] sequentialSubReaders = cr.getSequentialSubReaders();
-        final IndexReaderContext[] children = new IndexReaderContext[sequentialSubReaders.length];
+        final List<? extends IndexReader> sequentialSubReaders = cr.getSequentialSubReaders();
+        final List<IndexReaderContext> children = Arrays.asList(new IndexReaderContext[sequentialSubReaders.size()]);
         final CompositeReaderContext newParent;
         if (parent == null) {
           newParent = new CompositeReaderContext(cr, children, leaves);
@@ -107,31 +110,15 @@ public final class CompositeReaderContex
           newParent = new CompositeReaderContext(parent, cr, ord, docBase, children);
         }
         int newDocBase = 0;
-        for (int i = 0; i < sequentialSubReaders.length; i++) {
-          children[i] = build(newParent, sequentialSubReaders[i], i, newDocBase);
-          newDocBase += sequentialSubReaders[i].maxDoc();
+        for (int i = 0, c = sequentialSubReaders.size(); i < c; i++) {
+          final IndexReader r = sequentialSubReaders.get(i);
+          children.set(i, build(newParent, r, i, newDocBase));
+          newDocBase += r.maxDoc();
         }
         assert newDocBase == cr.maxDoc();
         return newParent;
       }
     }
-    
-    private int numLeaves(IndexReader reader) {
-      final int[] numLeaves = new int[1];
-      try {
-        new ReaderUtil.Gather(reader) {
-          @Override
-          protected void add(int base, AtomicReader r) {
-            numLeaves[0]++;
-          }
-        }.run();
-      } catch (IOException ioe) {
-        // won't happen
-        throw new RuntimeException(ioe);
-      }
-      return numLeaves[0];
-    }
-    
   }
 
 }
\ No newline at end of file

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java Tue Jun 19 07:39:34 2012
@@ -22,7 +22,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.lucene.search.SearcherManager; // javadocs
 import org.apache.lucene.store.Directory;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java Tue Jun 19 07:39:34 2012
@@ -1,5 +1,7 @@
 package org.apache.lucene.index;
 
+import java.util.List;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -45,23 +47,19 @@ public abstract class IndexReaderContext
   public abstract IndexReader reader();
   
   /**
-   * Returns the context's leaves if this context is a top-level context
-   * otherwise <code>null</code>. For convenience, if this is an
-   * {@link AtomicReaderContext} this returns itsself as the only leaf.
+   * Returns the context's leaves if this context is a top-level context.
+   * For convenience, if this is an {@link AtomicReaderContext} this
+   * returns itself as the only leaf.
    * <p>Note: this is convenience method since leaves can always be obtained by
-   * walking the context tree.
-   * <p><b>Warning:</b> Don't modify the returned array!
-   * Doing so will corrupt the internal structure of this
-   * {@code IndexReaderContext}.
+   * walking the context tree using {@link #children()}.
+   * @throws UnsupportedOperationExceception if this is not a top-level context.
+   * @see #children()
    */
-  public abstract AtomicReaderContext[] leaves();
+  public abstract List<AtomicReaderContext> leaves();
   
   /**
    * Returns the context's children iff this context is a composite context
    * otherwise <code>null</code>.
-   * <p><b>Warning:</b> Don't modify the returned array!
-   * Doing so will corrupt the internal structure of this
-   * {@code IndexReaderContext}.
    */
-  public abstract IndexReaderContext[] children();
+  public abstract List<IndexReaderContext> children();
 }
\ No newline at end of file

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocValues.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocValues.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocValues.java Tue Jun 19 07:39:34 2012
@@ -29,13 +29,18 @@ import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.PagedBytes;
 import org.apache.lucene.util.ReaderUtil;
-import org.apache.lucene.util.ReaderUtil.Gather;
 import org.apache.lucene.util.packed.PackedInts.Reader;
 
 /**
  * A wrapper for CompositeIndexReader providing access to per segment
  * {@link DocValues}
  * 
+ * <p><b>NOTE</b>: for multi readers, you'll get better
+ * performance by gathering the sub readers using
+ * {@link IndexReader#getTopReaderContext()} to get the
+ * atomic leaves and then operate per-AtomicReader,
+ * instead of using this class.
+ *
  * @lucene.experimental
  * @lucene.internal
  */
@@ -69,6 +74,8 @@ public class MultiDocValues extends DocV
   }
   
   private static class DocValuesPuller {
+    public DocValuesPuller() {}
+
     public DocValues pull(AtomicReader reader, String field) throws IOException {
       return reader.docValues(field);
     }
@@ -94,8 +101,9 @@ public class MultiDocValues extends DocV
    * their values on the fly.
    * 
    * <p>
-   * <b>NOTE</b>: this is a slow way to access DocValues. It's better to get the
-   * sub-readers (using {@link Gather}) and iterate through them yourself.
+   * <b>NOTE</b>: this is a slow way to access DocValues.
+   * It's better to get the sub-readers and iterate through them
+   * yourself.
    */
   public static DocValues getDocValues(IndexReader r, final String field) throws IOException {
     return getDocValues(r, field, DEFAULT_PULLER);
@@ -106,80 +114,74 @@ public class MultiDocValues extends DocV
    * their values on the fly.
    * 
    * <p>
-   * <b>NOTE</b>: this is a slow way to access DocValues. It's better to get the
-   * sub-readers (using {@link Gather}) and iterate through them yourself.
+   * <b>NOTE</b>: this is a slow way to access DocValues.
+   * It's better to get the sub-readers and iterate through them
+   * yourself.
    */
   public static DocValues getNormDocValues(IndexReader r, final String field) throws IOException {
     return getDocValues(r, field, NORMS_PULLER);
   }
   
  
-  private static DocValues getDocValues(IndexReader r, final String field, final DocValuesPuller puller) throws IOException {
-    if (r instanceof AtomicReader) {
+  private static DocValues getDocValues(IndexReader reader, final String field, final DocValuesPuller puller) throws IOException {
+    if (reader instanceof AtomicReader) {
       // already an atomic reader
-      return puller.pull((AtomicReader) r, field);
+      return puller.pull((AtomicReader) reader, field);
     }
-    assert r instanceof CompositeReader;
-    final IndexReader[] subs = ((CompositeReader) r).getSequentialSubReaders();
-    if (subs.length == 0) {
-      // no fields
-      return null;
-    } else if (subs.length == 1) {
-      return getDocValues(subs[0], field, puller);
-    } else {      
-      final List<DocValuesSlice> slices = new ArrayList<DocValuesSlice>();
-      
-      final TypePromoter promotedType[] = new TypePromoter[1];
-      promotedType[0] = TypePromoter.getIdentityPromoter();
-      
-      // gather all docvalues fields, accumulating a promoted type across 
-      // potentially incompatible types
-      
-      new ReaderUtil.Gather(r) {
-        boolean stop = false;
-        @Override
-        protected void add(int base, AtomicReader r) throws IOException {
-          if (stop) {
-            return;
-          }
+    assert reader instanceof CompositeReader;
+    final List<AtomicReaderContext> leaves = reader.getTopReaderContext().leaves();
+    switch (leaves.size()) {
+      case 0:
+        // no fields
+        return null;
+      case 1:
+        // already an atomic reader / reader with one leave
+        return getDocValues(leaves.get(0).reader(), field, puller);
+      default:
+        final List<DocValuesSlice> slices = new ArrayList<DocValuesSlice>();
+        
+        TypePromoter promotedType =  TypePromoter.getIdentityPromoter();
+        
+        // gather all docvalues fields, accumulating a promoted type across 
+        // potentially incompatible types
+        for (final AtomicReaderContext ctx : leaves) {
+          final AtomicReader r = ctx.reader();
           final DocValues d = puller.pull(r, field);
           if (d != null) {
             TypePromoter incoming = TypePromoter.create(d.getType(), d.getValueSize());
-            promotedType[0] = promotedType[0].promote(incoming);
+            promotedType = promotedType.promote(incoming);
           } else if (puller.stopLoadingOnNull(r, field)){
-            promotedType[0] = TypePromoter.getIdentityPromoter(); // set to identity to return null
-            stop = true;
+            return null;
           }
-          slices.add(new DocValuesSlice(d, base, r.maxDoc()));
+          slices.add(new DocValuesSlice(d, ctx.docBase, r.maxDoc()));
         }
-      }.run();
-      
-      // return null if no docvalues encountered anywhere
-      if (promotedType[0] == TypePromoter.getIdentityPromoter()) {
-        return null;
-      }
-           
-      // populate starts and fill gaps with empty docvalues 
-      int starts[] = new int[slices.size()];
-      for (int i = 0; i < slices.size(); i++) {
-        DocValuesSlice slice = slices.get(i);
-        starts[i] = slice.start;
-        if (slice.docValues == null) {
-          Type promoted = promotedType[0].type();
-          switch(promoted) {
-            case BYTES_FIXED_DEREF:
-            case BYTES_FIXED_STRAIGHT:
-            case BYTES_FIXED_SORTED:
-              assert promotedType[0].getValueSize() >= 0;
-              slice.docValues = new EmptyFixedDocValues(slice.length, promoted, promotedType[0].getValueSize());
-              break;
-            default:
-              slice.docValues = new EmptyDocValues(slice.length, promoted);
+        
+        // return null if no docvalues encountered anywhere
+        if (promotedType == TypePromoter.getIdentityPromoter()) {
+          return null;
+        }
+             
+        // populate starts and fill gaps with empty docvalues 
+        int starts[] = new int[slices.size()];
+        for (int i = 0; i < slices.size(); i++) {
+          DocValuesSlice slice = slices.get(i);
+          starts[i] = slice.start;
+          if (slice.docValues == null) {
+            Type promoted = promotedType.type();
+            switch(promoted) {
+              case BYTES_FIXED_DEREF:
+              case BYTES_FIXED_STRAIGHT:
+              case BYTES_FIXED_SORTED:
+                assert promotedType.getValueSize() >= 0;
+                slice.docValues = new EmptyFixedDocValues(slice.length, promoted, promotedType.getValueSize());
+                break;
+              default:
+                slice.docValues = new EmptyDocValues(slice.length, promoted);
+            }
           }
         }
-      }
-      
-      return new MultiDocValues(slices.toArray(new DocValuesSlice[slices.size()]), starts, promotedType[0]);
+        
+        return new MultiDocValues(slices.toArray(new DocValuesSlice[slices.size()]), starts, promotedType);
     }
   }
 

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsAndPositionsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsAndPositionsEnum.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsAndPositionsEnum.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsAndPositionsEnum.java Tue Jun 19 07:39:34 2012
@@ -17,8 +17,8 @@ package org.apache.lucene.index;
  * limitations under the License.
  */
 
-import org.apache.lucene.util.ReaderUtil;
 import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.ReaderSlice;
 
 import java.io.IOException;
 
@@ -148,7 +148,7 @@ public final class MultiDocsAndPositions
   // TODO: implement bulk read more efficiently than super
   public final static class EnumWithSlice {
     public DocsAndPositionsEnum docsAndPositionsEnum;
-    public ReaderUtil.Slice slice;
+    public ReaderSlice slice;
   }
 }
 

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsEnum.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsEnum.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiDocsEnum.java Tue Jun 19 07:39:34 2012
@@ -17,7 +17,8 @@ package org.apache.lucene.index;
  * limitations under the License.
  */
 
-import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
+
 import java.io.IOException;
 import java.util.Arrays;
 
@@ -123,7 +124,7 @@ public final class MultiDocsEnum extends
   // TODO: implement bulk read more efficiently than super
   public final static class EnumWithSlice {
     public DocsEnum docsEnum;
-    public ReaderUtil.Slice slice;
+    public ReaderSlice slice;
     
     @Override
     public String toString() {

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFields.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFields.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFields.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFields.java Tue Jun 19 07:39:34 2012
@@ -28,8 +28,7 @@ import java.util.concurrent.ConcurrentHa
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.MultiBits;
-import org.apache.lucene.util.ReaderUtil.Gather;  // for javadocs
-import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
 
 /**
  * Exposes flex API, merged from flex API of sub-segments.
@@ -38,9 +37,10 @@ import org.apache.lucene.util.ReaderUtil
  * sub-readers (eg {@link DirectoryReader} or {@link
  * MultiReader}).
  *
- * <p><b>NOTE</b>: for multi readers, you'll get better
- * performance by gathering the sub readers using {@link
- * ReaderUtil#gatherSubReaders} and then operate per-reader,
+ * <p><b>NOTE</b>: for composite readers, you'll get better
+ * performance by gathering the sub readers using
+ * {@link IndexReader#getTopReaderContext()} to get the
+ * atomic leaves and then operate per-AtomicReader,
  * instead of using this class.
  *
  * @lucene.experimental
@@ -48,7 +48,7 @@ import org.apache.lucene.util.ReaderUtil
 
 public final class MultiFields extends Fields {
   private final Fields[] subs;
-  private final ReaderUtil.Slice[] subSlices;
+  private final ReaderSlice[] subSlices;
   private final Map<String,Terms> terms = new ConcurrentHashMap<String,Terms>();
 
   /** Returns a single {@link Fields} instance for this
@@ -57,72 +57,57 @@ public final class MultiFields extends F
    *  has no postings.
    *
    *  <p><b>NOTE</b>: this is a slow way to access postings.
-   *  It's better to get the sub-readers (using {@link
-   *  Gather}) and iterate through them
+   *  It's better to get the sub-readers and iterate through them
    *  yourself. */
-  public static Fields getFields(IndexReader r) throws IOException {
-    if (r instanceof AtomicReader) {
-      // already an atomic reader
-      return ((AtomicReader) r).fields();
-    }
-    assert r instanceof CompositeReader;
-    final IndexReader[] subs = ((CompositeReader) r).getSequentialSubReaders();
-    if (subs.length == 0) {
-      // no fields
-      return null;
-    } else {
-      final List<Fields> fields = new ArrayList<Fields>();
-      final List<ReaderUtil.Slice> slices = new ArrayList<ReaderUtil.Slice>();
-
-      new ReaderUtil.Gather(r) {
-        @Override
-        protected void add(int base, AtomicReader r) throws IOException {
+  public static Fields getFields(IndexReader reader) throws IOException {
+    final List<AtomicReaderContext> leaves = reader.getTopReaderContext().leaves();
+    switch (leaves.size()) {
+      case 0:
+        // no fields
+        return null;
+      case 1:
+        // already an atomic reader / reader with one leave
+        return leaves.get(0).reader().fields();
+      default:
+        final List<Fields> fields = new ArrayList<Fields>();
+        final List<ReaderSlice> slices = new ArrayList<ReaderSlice>();
+        for (final AtomicReaderContext ctx : leaves) {
+          final AtomicReader r = ctx.reader();
           final Fields f = r.fields();
           if (f != null) {
             fields.add(f);
-            slices.add(new ReaderUtil.Slice(base, r.maxDoc(), fields.size()-1));
+            slices.add(new ReaderSlice(ctx.docBase, r.maxDoc(), fields.size()-1));
           }
         }
-      }.run();
-
-      if (fields.isEmpty()) {
-        return null;
-      } else if (fields.size() == 1) {
-        return fields.get(0);
-      } else {
-        return new MultiFields(fields.toArray(Fields.EMPTY_ARRAY),
-                                       slices.toArray(ReaderUtil.Slice.EMPTY_ARRAY));
-      }
+        if (fields.isEmpty()) {
+          return null;
+        } else if (fields.size() == 1) {
+          return fields.get(0);
+        } else {
+          return new MultiFields(fields.toArray(Fields.EMPTY_ARRAY),
+                                         slices.toArray(ReaderSlice.EMPTY_ARRAY));
+        }
     }
   }
 
-  public static Bits getLiveDocs(IndexReader r) {
-    if (r.hasDeletions()) {
-      final List<Bits> liveDocs = new ArrayList<Bits>();
-      final List<Integer> starts = new ArrayList<Integer>();
-
-      try {
-        final int maxDoc = new ReaderUtil.Gather(r) {
-            @Override
-            protected void add(int base, AtomicReader r) throws IOException {
-              // record all liveDocs, even if they are null
-              liveDocs.add(r.getLiveDocs());
-              starts.add(base);
-            }
-          }.run();
-        starts.add(maxDoc);
-      } catch (IOException ioe) {
-        // should not happen
-        throw new RuntimeException(ioe);
-      }
-
-      assert liveDocs.size() > 0;
-      if (liveDocs.size() == 1) {
-        // Only one actual sub reader -- optimize this case
-        return liveDocs.get(0);
-      } else {
-        return new MultiBits(liveDocs, starts, true);
+  public static Bits getLiveDocs(IndexReader reader) {
+    if (reader.hasDeletions()) {
+      final List<AtomicReaderContext> leaves = reader.getTopReaderContext().leaves();
+      final int size = leaves.size();
+      assert size > 0 : "A reader with deletions must have at least one leave";
+      if (size == 1) {
+        return leaves.get(0).reader().getLiveDocs();
+      }
+      final Bits[] liveDocs = new Bits[size];
+      final int[] starts = new int[size + 1];
+      for (int i = 0; i < size; i++) {
+        // record all liveDocs, even if they are null
+        final AtomicReaderContext ctx = leaves.get(i);
+        liveDocs[i] = ctx.reader().getLiveDocs();
+        starts[i] = ctx.docBase;
       }
+      starts[size] = reader.maxDoc();
+      return new MultiBits(liveDocs, starts, true);
     } else {
       return null;
     }
@@ -170,7 +155,7 @@ public final class MultiFields extends F
     return null;
   }
 
-  public MultiFields(Fields[] subs, ReaderUtil.Slice[] subSlices) {
+  public MultiFields(Fields[] subs, ReaderSlice[] subSlices) {
     this.subs = subs;
     this.subSlices = subSlices;
   }
@@ -179,7 +164,7 @@ public final class MultiFields extends F
   public FieldsEnum iterator() throws IOException {
 
     final List<FieldsEnum> fieldsEnums = new ArrayList<FieldsEnum>();
-    final List<ReaderUtil.Slice> fieldsSlices = new ArrayList<ReaderUtil.Slice>();
+    final List<ReaderSlice> fieldsSlices = new ArrayList<ReaderSlice>();
     for(int i=0;i<subs.length;i++) {
       fieldsEnums.add(subs[i].iterator());
       fieldsSlices.add(subSlices[i]);
@@ -189,13 +174,12 @@ public final class MultiFields extends F
     } else {
       return new MultiFieldsEnum(this,
                                  fieldsEnums.toArray(FieldsEnum.EMPTY_ARRAY),
-                                 fieldsSlices.toArray(ReaderUtil.Slice.EMPTY_ARRAY));
+                                 fieldsSlices.toArray(ReaderSlice.EMPTY_ARRAY));
     }
   }
 
   @Override
   public Terms terms(String field) throws IOException {
-
     Terms result = terms.get(field);
     if (result != null)
       return result;
@@ -204,7 +188,7 @@ public final class MultiFields extends F
     // Lazy init: first time this field is requested, we
     // create & add to terms:
     final List<Terms> subs2 = new ArrayList<Terms>();
-    final List<ReaderUtil.Slice> slices2 = new ArrayList<ReaderUtil.Slice>();
+    final List<ReaderSlice> slices2 = new ArrayList<ReaderSlice>();
 
     // Gather all sub-readers that share this field
     for(int i=0;i<subs.length;i++) {
@@ -220,7 +204,7 @@ public final class MultiFields extends F
       // is unbounded.
     } else {
       result = new MultiTerms(subs2.toArray(Terms.EMPTY_ARRAY),
-          slices2.toArray(ReaderUtil.Slice.EMPTY_ARRAY));
+          slices2.toArray(ReaderSlice.EMPTY_ARRAY));
       terms.put(field, result);
     }
 
@@ -252,18 +236,16 @@ public final class MultiFields extends F
    *  will be unavailable.
    */
   public static FieldInfos getMergedFieldInfos(IndexReader reader) {
-    final List<AtomicReader> subReaders = new ArrayList<AtomicReader>();
-    ReaderUtil.gatherSubReaders(subReaders, reader);
     final FieldInfos.Builder builder = new FieldInfos.Builder();
-    for(AtomicReader subReader : subReaders) {
-      builder.add(subReader.getFieldInfos());
+    for(final AtomicReaderContext ctx : reader.getTopReaderContext().leaves()) {
+      builder.add(ctx.reader().getFieldInfos());
     }
     return builder.finish();
   }
 
   public static Collection<String> getIndexedFields(IndexReader reader) {
     final Collection<String> fields = new HashSet<String>();
-    for(FieldInfo fieldInfo : getMergedFieldInfos(reader)) {
+    for(final FieldInfo fieldInfo : getMergedFieldInfos(reader)) {
       if (fieldInfo.isIndexed()) {
         fields.add(fieldInfo.name);
       }

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java Tue Jun 19 07:39:34 2012
@@ -18,7 +18,7 @@ package org.apache.lucene.index;
  */
 
 import org.apache.lucene.util.PriorityQueue;
-import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
 
 import java.io.IOException;
 import java.util.List;
@@ -47,7 +47,7 @@ public final  class MultiFieldsEnum exte
 
   /** The subs array must be newly initialized FieldsEnum
    *  (ie, {@link FieldsEnum#next} has not been called. */
-  public MultiFieldsEnum(MultiFields fields, FieldsEnum[] subs, ReaderUtil.Slice[] subSlices) throws IOException {
+  public MultiFieldsEnum(MultiFields fields, FieldsEnum[] subs, ReaderSlice[] subSlices) throws IOException {
     this.fields = fields;
     queue = new FieldMergeQueue(subs.length);
     top = new FieldsEnumWithSlice[subs.length];
@@ -107,11 +107,11 @@ public final  class MultiFieldsEnum exte
   public final static class FieldsEnumWithSlice {
     public static final FieldsEnumWithSlice[] EMPTY_ARRAY = new FieldsEnumWithSlice[0];
     final FieldsEnum fields;
-    final ReaderUtil.Slice slice;
+    final ReaderSlice slice;
     final int index;
     String current;
 
-    public FieldsEnumWithSlice(FieldsEnum fields, ReaderUtil.Slice slice, int index) throws IOException {
+    public FieldsEnumWithSlice(FieldsEnum fields, ReaderSlice slice, int index) throws IOException {
       this.slice = slice;
       this.index = index;
       assert slice.length >= 0: "length=" + slice.length;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiReader.java Tue Jun 19 07:39:34 2012
@@ -68,12 +68,12 @@ public class MultiReader extends BaseCom
   @Override
   protected synchronized void doClose() throws IOException {
     IOException ioe = null;
-    for (int i = 0; i < subReaders.length; i++) {
+    for (final IndexReader r : getSequentialSubReaders()) {
       try {
         if (closeSubReaders) {
-          subReaders[i].close();
+          r.close();
         } else {
-          subReaders[i].decRef();
+          r.decRef();
         }
       } catch (IOException e) {
         if (ioe == null) ioe = e;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTerms.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTerms.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTerms.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTerms.java Tue Jun 19 07:39:34 2012
@@ -23,7 +23,7 @@ import java.util.Comparator;
 import java.util.List;
 
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
 
 import org.apache.lucene.util.automaton.CompiledAutomaton;
 
@@ -36,10 +36,10 @@ import org.apache.lucene.util.automaton.
 
 public final class MultiTerms extends Terms {
   private final Terms[] subs;
-  private final ReaderUtil.Slice[] subSlices;
+  private final ReaderSlice[] subSlices;
   private final Comparator<BytesRef> termComp;
 
-  public MultiTerms(Terms[] subs, ReaderUtil.Slice[] subSlices) throws IOException {
+  public MultiTerms(Terms[] subs, ReaderSlice[] subSlices) throws IOException {
     this.subs = subs;
     this.subSlices = subSlices;
     

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTermsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTermsEnum.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTermsEnum.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/MultiTermsEnum.java Tue Jun 19 07:39:34 2012
@@ -22,7 +22,7 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BitsSlice;
 import org.apache.lucene.util.MultiBits;
-import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -71,7 +71,7 @@ public final class MultiTermsEnum extend
     return top;
   }
 
-  public MultiTermsEnum(ReaderUtil.Slice[] slices) {
+  public MultiTermsEnum(ReaderSlice[] slices) {
     queue = new TermMergeQueue(slices.length);
     top = new TermsEnumWithSlice[slices.length];
     subs = new TermsEnumWithSlice[slices.length];
@@ -494,12 +494,12 @@ public final class MultiTermsEnum extend
   }
 
   private final static class TermsEnumWithSlice {
-    private final ReaderUtil.Slice subSlice;
+    private final ReaderSlice subSlice;
     private TermsEnum terms;
     public BytesRef current;
     final int index;
 
-    public TermsEnumWithSlice(int index, ReaderUtil.Slice subSlice) {
+    public TermsEnumWithSlice(int index, ReaderSlice subSlice) {
       this.subSlice = subSlice;
       this.index = index;
       assert subSlice.length >= 0: "length=" + subSlice.length;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/ParallelCompositeReader.java Tue Jun 19 07:39:34 2012
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.util.Collections;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 /** An {@link CompositeReader} which reads multiple, parallel indexes.  Each index added
@@ -85,44 +86,45 @@ public final class ParallelCompositeRead
         throw new IllegalArgumentException("There must be at least one main reader if storedFieldsReaders are used.");
       return new IndexReader[0];
     } else {
-      final IndexReader[] firstSubReaders = readers[0].getSequentialSubReaders();
+      final List<? extends IndexReader> firstSubReaders = readers[0].getSequentialSubReaders();
 
       // check compatibility:
-      final int maxDoc = readers[0].maxDoc();
-      final int[] childMaxDoc = new int[firstSubReaders.length];
-      final boolean[] childAtomic = new boolean[firstSubReaders.length];
-      for (int i = 0; i < firstSubReaders.length; i++) {
-        childMaxDoc[i] = firstSubReaders[i].maxDoc();
-        childAtomic[i] = firstSubReaders[i] instanceof AtomicReader;
+      final int maxDoc = readers[0].maxDoc(), noSubs = firstSubReaders.size();
+      final int[] childMaxDoc = new int[noSubs];
+      final boolean[] childAtomic = new boolean[noSubs];
+      for (int i = 0; i < noSubs; i++) {
+        final IndexReader r = firstSubReaders.get(i);
+        childMaxDoc[i] = r.maxDoc();
+        childAtomic[i] = r instanceof AtomicReader;
       }
       validate(readers, maxDoc, childMaxDoc, childAtomic);
       validate(storedFieldsReaders, maxDoc, childMaxDoc, childAtomic);
 
       // hierarchically build the same subreader structure as the first CompositeReader with Parallel*Readers:
-      final IndexReader[] subReaders = new IndexReader[firstSubReaders.length];
+      final IndexReader[] subReaders = new IndexReader[noSubs];
       for (int i = 0; i < subReaders.length; i++) {
-        if (firstSubReaders[i] instanceof AtomicReader) {
+        if (firstSubReaders.get(i) instanceof AtomicReader) {
           final AtomicReader[] atomicSubs = new AtomicReader[readers.length];
           for (int j = 0; j < readers.length; j++) {
-            atomicSubs[j] = (AtomicReader) readers[j].getSequentialSubReaders()[i];
+            atomicSubs[j] = (AtomicReader) readers[j].getSequentialSubReaders().get(i);
           }
           final AtomicReader[] storedSubs = new AtomicReader[storedFieldsReaders.length];
           for (int j = 0; j < storedFieldsReaders.length; j++) {
-            storedSubs[j] = (AtomicReader) storedFieldsReaders[j].getSequentialSubReaders()[i];
+            storedSubs[j] = (AtomicReader) storedFieldsReaders[j].getSequentialSubReaders().get(i);
           }
           // 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);
         } else {
-          assert firstSubReaders[i] instanceof CompositeReader;
+          assert firstSubReaders.get(i) instanceof CompositeReader;
           final CompositeReader[] compositeSubs = new CompositeReader[readers.length];
           for (int j = 0; j < readers.length; j++) {
-            compositeSubs[j] = (CompositeReader) readers[j].getSequentialSubReaders()[i];
+            compositeSubs[j] = (CompositeReader) readers[j].getSequentialSubReaders().get(i);
           }
           final CompositeReader[] storedSubs = new CompositeReader[storedFieldsReaders.length];
           for (int j = 0; j < storedFieldsReaders.length; j++) {
-            storedSubs[j] = (CompositeReader) storedFieldsReaders[j].getSequentialSubReaders()[i];
+            storedSubs[j] = (CompositeReader) storedFieldsReaders[j].getSequentialSubReaders().get(i);
           }
           // we simply enable closing of subReaders, to prevent incRefs on subReaders
           // -> for synthetic subReaders, close() is never called by our doClose()
@@ -136,18 +138,20 @@ public final class ParallelCompositeRead
   private static void validate(CompositeReader[] readers, int maxDoc, int[] childMaxDoc, boolean[] childAtomic) {
     for (int i = 0; i < readers.length; i++) {
       final CompositeReader reader = readers[i];
-      final IndexReader[] subs = reader.getSequentialSubReaders();
+      final List<? extends IndexReader> subs = reader.getSequentialSubReaders();
       if (reader.maxDoc() != maxDoc) {
         throw new IllegalArgumentException("All readers must have same maxDoc: "+maxDoc+"!="+reader.maxDoc());
       }
-      if (subs.length != childMaxDoc.length) {
+      final int noSubs = subs.size();
+      if (noSubs != childMaxDoc.length) {
         throw new IllegalArgumentException("All readers must have same number of subReaders");
       }
-      for (int subIDX = 0; subIDX < subs.length; subIDX++) {
-        if (subs[subIDX].maxDoc() != childMaxDoc[subIDX]) {
+      for (int subIDX = 0; subIDX < noSubs; subIDX++) {
+        final IndexReader r = subs.get(subIDX);
+        if (r.maxDoc() != childMaxDoc[subIDX]) {
           throw new IllegalArgumentException("All readers must have same corresponding subReader maxDoc");
         }
-        if (!(childAtomic[subIDX] ? (subs[subIDX] instanceof AtomicReader) : (subs[subIDX] instanceof CompositeReader))) {
+        if (!(childAtomic[subIDX] ? (r instanceof AtomicReader) : (r instanceof CompositeReader))) {
           throw new IllegalArgumentException("All readers must have same corresponding subReader types (atomic or composite)");
         }
       }

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentMerger.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentMerger.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentMerger.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SegmentMerger.java Tue Jun 19 07:39:34 2012
@@ -35,6 +35,7 @@ import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.InfoStream;
 import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderSlice;
 
 /**
  * The SegmentMerger class combines two or more Segments, represented by an IndexReader ({@link #add},
@@ -76,16 +77,9 @@ final class SegmentMerger {
    * @param reader
    */
   final void add(IndexReader reader) {
-    try {
-      new ReaderUtil.Gather(reader) {
-        @Override
-        protected void add(int base, AtomicReader r) {
-          mergeState.readers.add(new MergeState.IndexReaderAndLiveDocs(r, r.getLiveDocs(), r.numDeletedDocs()));
-        }
-      }.run();
-    } catch (IOException ioe) {
-      // won't happen
-      throw new RuntimeException(ioe);
+    for (final AtomicReaderContext ctx : reader.getTopReaderContext().leaves()) {
+      final AtomicReader r = ctx.reader();
+      mergeState.readers.add(new MergeState.IndexReaderAndLiveDocs(r, r.getLiveDocs(), r.numDeletedDocs()));
     }
   }
 
@@ -311,7 +305,7 @@ final class SegmentMerger {
   private final void mergeTerms(SegmentWriteState segmentWriteState) throws CorruptIndexException, IOException {
     
     final List<Fields> fields = new ArrayList<Fields>();
-    final List<ReaderUtil.Slice> slices = new ArrayList<ReaderUtil.Slice>();
+    final List<ReaderSlice> slices = new ArrayList<ReaderSlice>();
 
     int docBase = 0;
 
@@ -320,7 +314,7 @@ final class SegmentMerger {
       final Fields f = r.reader.fields();
       final int maxDoc = r.reader.maxDoc();
       if (f != null) {
-        slices.add(new ReaderUtil.Slice(docBase, maxDoc, readerIndex));
+        slices.add(new ReaderSlice(docBase, maxDoc, readerIndex));
         fields.add(f);
       }
       docBase += maxDoc;
@@ -331,7 +325,7 @@ final class SegmentMerger {
     try {
       consumer.merge(mergeState,
                      new MultiFields(fields.toArray(Fields.EMPTY_ARRAY),
-                                     slices.toArray(ReaderUtil.Slice.EMPTY_ARRAY)));
+                                     slices.toArray(ReaderSlice.EMPTY_ARRAY)));
       success = true;
     } finally {
       if (success) {

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/SlowCompositeReaderWrapper.java Tue Jun 19 07:39:34 2012
@@ -22,7 +22,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.ReaderUtil; // javadoc
 
 import org.apache.lucene.index.DirectoryReader; // javadoc
 import org.apache.lucene.index.MultiReader; // javadoc
@@ -32,17 +31,16 @@ import org.apache.lucene.index.MultiRead
  * MultiReader} or {@link DirectoryReader}) to emulate an
  * atomic reader.  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.
+ * 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,
- * it's better to get the sequential sub readers (see {@link
- * ReaderUtil#gatherSubReaders}, instead, and iterate through them
- * yourself.</p>
+ * you'll get better performance by gathering the sub readers using
+ * {@link IndexReader#getTopReaderContext()} to get the
+ * atomic leaves and then operate per-AtomicReader,
+ * instead of using this class.
  */
-
 public final class SlowCompositeReaderWrapper extends AtomicReader {
 
   private final CompositeReader in;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java Tue Jun 19 07:39:34 2012
@@ -118,8 +118,8 @@ final class StandardDirectoryReader exte
       writer, segmentInfos, writer.getConfig().getReaderTermsIndexDivisor(), applyAllDeletes);
   }
 
-  /** This constructor is only used for {@link #doOpenIfChanged()} */
-  private static DirectoryReader open(Directory directory, IndexWriter writer, SegmentInfos infos, AtomicReader[] oldReaders,
+  /** This constructor is only used for {@link #doOpenIfChanged(SegmentInfos, IndexWriter)} */
+  private static DirectoryReader open(Directory directory, IndexWriter writer, SegmentInfos infos, List<? extends AtomicReader> oldReaders,
     int termInfosIndexDivisor) throws IOException {
     // we put the old SegmentReaders in a map, that allows us
     // to lookup a reader using its segment name
@@ -127,8 +127,9 @@ final class StandardDirectoryReader exte
 
     if (oldReaders != null) {
       // create a Map SegmentName->SegmentReader
-      for (int i = 0; i < oldReaders.length; i++) {
-        segmentReaders.put(((SegmentReader) oldReaders[i]).getSegmentName(), Integer.valueOf(i));
+      for (int i = 0, c = oldReaders.size(); i < c; i++) {
+        final SegmentReader sr = (SegmentReader) oldReaders.get(i);
+        segmentReaders.put(sr.getSegmentName(), Integer.valueOf(i));
       }
     }
     
@@ -146,7 +147,7 @@ final class StandardDirectoryReader exte
         newReaders[i] = null;
       } else {
         // there is an old reader for this segment - we'll try to reopen it
-        newReaders[i] = (SegmentReader) oldReaders[oldReaderIndex.intValue()];
+        newReaders[i] = (SegmentReader) oldReaders.get(oldReaderIndex.intValue());
       }
 
       boolean success = false;
@@ -216,9 +217,9 @@ final class StandardDirectoryReader exte
     if (writer != null) {
       buffer.append(":nrt");
     }
-    for(int i=0;i<subReaders.length;i++) {
+    for (final AtomicReader r : getSequentialSubReaders()) {
       buffer.append(' ');
-      buffer.append(subReaders[i]);
+      buffer.append(r);
     }
     buffer.append(')');
     return buffer.toString();
@@ -298,7 +299,7 @@ final class StandardDirectoryReader exte
   }
 
   synchronized DirectoryReader doOpenIfChanged(SegmentInfos infos, IndexWriter writer) throws CorruptIndexException, IOException {
-    return StandardDirectoryReader.open(directory, writer, infos, subReaders, termInfosIndexDivisor);
+    return StandardDirectoryReader.open(directory, writer, infos, getSequentialSubReaders(), termInfosIndexDivisor);
   }
 
   @Override
@@ -329,10 +330,10 @@ final class StandardDirectoryReader exte
   @Override
   protected synchronized void doClose() throws IOException {
     IOException ioe = null;
-    for (int i = 0; i < subReaders.length; i++) {
+    for (final AtomicReader r : getSequentialSubReaders()) {
       // try to close each reader, even if an exception is thrown
       try {
-        subReaders[i].decRef();
+        r.decRef();
       } catch (IOException e) {
         if (ioe == null) ioe = e;
       }

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java Tue Jun 19 07:39:34 2012
@@ -18,7 +18,9 @@ package org.apache.lucene.search;
  */
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -80,7 +82,7 @@ public class IndexSearcher {
   // NOTE: these members might change in incompatible ways
   // in the next release
   protected final IndexReaderContext readerContext;
-  protected final AtomicReaderContext[] leafContexts;
+  protected final List<AtomicReaderContext> leafContexts;
   // used with executor - each slice holds a set of leafs executed within one thread
   protected final LeafSlice[] leafSlices;
 
@@ -165,10 +167,10 @@ public class IndexSearcher {
    * Each {@link LeafSlice} is executed in a single thread. By default there
    * will be one {@link LeafSlice} per leaf ({@link AtomicReaderContext}).
    */
-  protected LeafSlice[] slices(AtomicReaderContext...leaves) {
-    LeafSlice[] slices = new LeafSlice[leaves.length];
+  protected LeafSlice[] slices(List<AtomicReaderContext> leaves) {
+    LeafSlice[] slices = new LeafSlice[leaves.size()];
     for (int i = 0; i < slices.length; i++) {
-      slices[i] = new LeafSlice(leaves[i]);
+      slices[i] = new LeafSlice(leaves.get(i));
     }
     return slices;
   }
@@ -440,7 +442,7 @@ public class IndexSearcher {
    * {@link IndexSearcher#search(Query,Filter,int)} instead.
    * @throws BooleanQuery.TooManyClauses
    */
-  protected TopDocs search(AtomicReaderContext[] leaves, Weight weight, ScoreDoc after, int nDocs) throws IOException {
+  protected TopDocs search(List<AtomicReaderContext> leaves, Weight weight, ScoreDoc after, int nDocs) throws IOException {
     // single thread
     int limit = reader.maxDoc();
     if (limit == 0) {
@@ -477,7 +479,7 @@ public class IndexSearcher {
    * <p>NOTE: this does not compute scores by default.  If you
    * need scores, create a {@link TopFieldCollector}
    * instance by calling {@link TopFieldCollector#create} and
-   * then pass that to {@link #search(AtomicReaderContext[], Weight,
+   * then pass that to {@link #search(List, Weight,
    * Collector)}.</p>
    */
   protected TopFieldDocs search(Weight weight, FieldDoc after, int nDocs,
@@ -525,7 +527,7 @@ public class IndexSearcher {
    * whether or not the fields in the returned {@link FieldDoc} instances should
    * be set by specifying fillFields.
    */
-  protected TopFieldDocs search(AtomicReaderContext[] leaves, Weight weight, FieldDoc after, int nDocs,
+  protected TopFieldDocs search(List<AtomicReaderContext> leaves, Weight weight, FieldDoc after, int nDocs,
                                 Sort sort, boolean fillFields, boolean doDocScores, boolean doMaxScore) throws IOException {
     // single thread
     int limit = reader.maxDoc();
@@ -559,15 +561,15 @@ public class IndexSearcher {
    *          to receive hits
    * @throws BooleanQuery.TooManyClauses
    */
-  protected void search(AtomicReaderContext[] leaves, Weight weight, Collector collector)
+  protected void search(List<AtomicReaderContext> leaves, Weight weight, Collector collector)
       throws IOException {
 
     // TODO: should we make this
     // threaded...?  the Collector could be sync'd?
     // always use single thread:
-    for (int i = 0; i < leaves.length; i++) { // search each subreader
-      collector.setNextReader(leaves[i]);
-      Scorer scorer = weight.scorer(leaves[i], !collector.acceptsDocsOutOfOrder(), true, leaves[i].reader().getLiveDocs());
+    for (AtomicReaderContext ctx : leaves) { // search each subreader
+      collector.setNextReader(ctx);
+      Scorer scorer = weight.scorer(ctx, !collector.acceptsDocsOutOfOrder(), true, ctx.reader().getLiveDocs());
       if (scorer != null) {
         scorer.score(collector);
       }
@@ -611,9 +613,10 @@ public class IndexSearcher {
    */
   protected Explanation explain(Weight weight, int doc) throws IOException {
     int n = ReaderUtil.subIndex(doc, leafContexts);
-    int deBasedDoc = doc - leafContexts[n].docBase;
+    final AtomicReaderContext ctx = leafContexts.get(n);
+    int deBasedDoc = doc - ctx.docBase;
     
-    return weight.explain(leafContexts[n], deBasedDoc);
+    return weight.explain(ctx, deBasedDoc);
   }
 
   /**
@@ -669,7 +672,7 @@ public class IndexSearcher {
     }
 
     public TopDocs call() throws IOException {
-      final TopDocs docs = searcher.search(slice.leaves, weight, after, nDocs);
+      final TopDocs docs = searcher.search(Arrays.asList(slice.leaves), weight, after, nDocs);
       final ScoreDoc[] scoreDocs = docs.scoreDocs;
       //it would be so nice if we had a thread-safe insert 
       lock.lock();
@@ -757,11 +760,13 @@ public class IndexSearcher {
 
     public TopFieldDocs call() throws IOException {
       assert slice.leaves.length == 1;
-      final TopFieldDocs docs = searcher.search(slice.leaves, weight, after, nDocs, sort, true, doDocScores, doMaxScore);
+      final TopFieldDocs docs = searcher.search(Arrays.asList(slice.leaves),
+          weight, after, nDocs, sort, true, doDocScores, doMaxScore);
       lock.lock();
       try {
-        final int base = slice.leaves[0].docBase;
-        hq.setNextReader(slice.leaves[0]);
+        final AtomicReaderContext ctx = slice.leaves[0];
+        final int base = ctx.docBase;
+        hq.setNextReader(ctx);
         hq.setScorer(fakeScorer);
         for(ScoreDoc scoreDoc : docs.scoreDocs) {
           fakeScorer.doc = scoreDoc.doc - base;
@@ -837,7 +842,7 @@ public class IndexSearcher {
   public static class LeafSlice {
     final AtomicReaderContext[] leaves;
     
-    public LeafSlice(AtomicReaderContext...leaves) {
+    public LeafSlice(AtomicReaderContext... leaves) {
       this.leaves = leaves;
     }
   }

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/TermCollectingRewrite.java Tue Jun 19 07:39:34 2012
@@ -48,8 +48,7 @@ abstract class TermCollectingRewrite<Q e
   final void collectTerms(IndexReader reader, MultiTermQuery query, TermCollector collector) throws IOException {
     IndexReaderContext topReaderContext = reader.getTopReaderContext();
     Comparator<BytesRef> lastTermComp = null;
-    final AtomicReaderContext[] leaves = topReaderContext.leaves();
-    for (AtomicReaderContext context : leaves) {
+    for (AtomicReaderContext context : topReaderContext.leaves()) {
       final Fields fields = context.reader().fields();
       if (fields == null) {
         // reader has no fields

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java Tue Jun 19 07:39:34 2012
@@ -184,8 +184,7 @@ public class PayloadSpanUtil {
     for (Term term : terms) {
       termContexts.put(term, TermContext.build(context, term, true));
     }
-    final AtomicReaderContext[] leaves = context.leaves();
-    for (AtomicReaderContext atomicReaderContext : leaves) {
+    for (AtomicReaderContext atomicReaderContext : context.leaves()) {
       final Spans spans = query.getSpans(atomicReaderContext, atomicReaderContext.reader().getLiveDocs(), termContexts);
       while (spans.next() == true) {
         if (spans.isPayloadAvailable()) {

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/BitsSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/BitsSlice.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/BitsSlice.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/BitsSlice.java Tue Jun 19 07:39:34 2012
@@ -25,7 +25,7 @@ public final class BitsSlice implements 
   private final int length;
 
   // start is inclusive; end is exclusive (length = end-start)
-  public BitsSlice(Bits parent, ReaderUtil.Slice slice) {
+  public BitsSlice(Bits parent, ReaderSlice slice) {
     this.parent = parent;
     this.start = slice.start;
     this.length = slice.length;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java Tue Jun 19 07:39:34 2012
@@ -280,9 +280,9 @@ public final class FieldCacheSanityCheck
     for (int i = 0; i < all.size(); i++) {
       Object obj = all.get(i);
       if (obj instanceof CompositeReader) {
-        IndexReader[] subs = ((CompositeReader)obj).getSequentialSubReaders();
-        for (int j = 0; (null != subs) && (j < subs.length); j++) {
-          all.add(subs[j].getCoreCacheKey());
+        List<? extends IndexReader> subs = ((CompositeReader)obj).getSequentialSubReaders();
+        for (int j = 0; (null != subs) && (j < subs.size()); j++) {
+          all.add(subs.get(j).getCoreCacheKey());
         }
       }
       

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/MultiBits.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/MultiBits.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/MultiBits.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/MultiBits.java Tue Jun 19 07:39:34 2012
@@ -17,8 +17,6 @@ package org.apache.lucene.util;
  * limitations under the License.
  */
 
-import java.util.List;
-
 /**
  * Concatenates multiple Bits together, on every lookup.
  *
@@ -36,13 +34,10 @@ public final class MultiBits implements 
 
   private final boolean defaultValue;
 
-  public MultiBits(List<Bits> bits, List<Integer> starts, boolean defaultValue) {
-    assert starts.size() == 1+bits.size();
-    this.subs = bits.toArray(Bits.EMPTY_ARRAY);
-    this.starts = new int[starts.size()];
-    for(int i=0;i<this.starts.length;i++) {
-      this.starts[i] = starts.get(i);
-    }
+  public MultiBits(Bits[] subs, int[] starts, boolean defaultValue) {
+    assert starts.length == 1+subs.length;
+    this.subs = subs;
+    this.starts = starts;
     this.defaultValue = defaultValue;
   }
 
@@ -84,7 +79,7 @@ public final class MultiBits implements 
 
   /**
    * Represents a sub-Bits from 
-   * {@link MultiBits#getMatchingSub(org.apache.lucene.util.ReaderUtil.Slice) getMatchingSub()}.
+   * {@link MultiBits#getMatchingSub(org.apache.lucene.util.ReaderSlice) getMatchingSub()}.
    */
   public final static class SubResult {
     public boolean matches;
@@ -99,7 +94,7 @@ public final class MultiBits implements 
    * {@link SubResult#matches} instead to ensure the sub was 
    * actually found.
    */
-  public SubResult getMatchingSub(ReaderUtil.Slice slice) {
+  public SubResult getMatchingSub(ReaderSlice slice) {
     int reader = ReaderUtil.subIndex(slice.start, starts);
     assert reader != -1;
     assert reader < subs.length: "slice=" + slice + " starts[-1]=" + starts[starts.length-1];

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderUtil.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderUtil.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/ReaderUtil.java Tue Jun 19 07:39:34 2012
@@ -18,11 +18,8 @@ package org.apache.lucene.util;
  */
 
 import java.util.List;
-import java.io.IOException;
 
 import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.CompositeReader;
-import org.apache.lucene.index.AtomicReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReaderContext;
 
@@ -36,92 +33,6 @@ public final class ReaderUtil {
   private ReaderUtil() {} // no instance
 
   /**
-   * Subreader slice from a parent composite reader.
-   */
-  public static class Slice {
-    public static final Slice[] EMPTY_ARRAY = new Slice[0];
-    public final int start;
-    public final int length;
-    public final int readerIndex;
-
-    public Slice(int start, int length, int readerIndex) {
-      this.start = start;
-      this.length = length;
-      this.readerIndex = readerIndex;
-    }
-
-    @Override
-    public String toString() {
-      return "slice start=" + start + " length=" + length + " readerIndex=" + readerIndex;
-    }
-  }
-
-  /**
-   * Gathers sub-readers from reader into a List.  See
-   * {@link Gather} for are more general way to gather
-   * whatever you need to, per reader.
-   *
-   * @lucene.experimental
-   * 
-   * @param allSubReaders
-   * @param reader
-   */
-
-  public static void gatherSubReaders(final List<AtomicReader> allSubReaders, IndexReader reader) {
-    try {
-      new Gather(reader) {
-        @Override
-        protected void add(int base, AtomicReader r) {
-          allSubReaders.add(r);
-        }
-      }.run();
-    } catch (IOException ioe) {
-      // won't happen
-      throw new RuntimeException(ioe);
-    }
-  }
-
-  /** Recursively visits all sub-readers of a reader.  You
-   *  should subclass this and override the add method to
-   *  gather what you need.
-   *
-   * @lucene.experimental */
-  public static abstract class Gather {
-    private final IndexReader topReader;
-
-    public Gather(IndexReader r) {
-      topReader = r;
-    }
-
-    public int run() throws IOException {
-      return run(0, topReader);
-    }
-
-    public int run(int docBase) throws IOException {
-      return run(docBase, topReader);
-    }
-
-    private int run(final int base, final IndexReader reader) throws IOException {
-      if (reader instanceof AtomicReader) {
-        // atomic reader
-        add(base, (AtomicReader) reader);
-        return base + reader.maxDoc();
-      } else {
-        assert reader instanceof CompositeReader : "must be a composite reader";
-        int newBase = base;
-        IndexReader[] subReaders = ((CompositeReader) reader).getSequentialSubReaders();
-        for (int i = 0; i < subReaders.length; i++) {
-          newBase = run(newBase, subReaders[i]);
-        }
-        assert newBase == base + reader.maxDoc();
-        return newBase;
-      }
-    }
-
-    protected abstract void add(int base, AtomicReader r) throws IOException;
-  }
-  
-  /**
    * Walks up the reader tree and return the given context's top level reader
    * context, or in other words the reader tree's root context.
    */
@@ -162,20 +73,20 @@ public final class ReaderUtil {
    * Returns index of the searcher/reader for document <code>n</code> in the
    * array used to construct this searcher/reader.
    */
-  public static int subIndex(int n, AtomicReaderContext[] leaves) { // find
+  public static int subIndex(int n, List<AtomicReaderContext> leaves) { // find
     // searcher/reader for doc n:
-    int size = leaves.length;
+    int size = leaves.size();
     int lo = 0; // search starts array
     int hi = size - 1; // for first element less than n, return its index
     while (hi >= lo) {
       int mid = (lo + hi) >>> 1;
-      int midValue = leaves[mid].docBase;
+      int midValue = leaves.get(mid).docBase;
       if (n < midValue)
         hi = mid - 1;
       else if (n > midValue)
         lo = mid + 1;
       else { // found a match
-        while (mid + 1 < size && leaves[mid + 1].docBase == midValue) {
+        while (mid + 1 < size && leaves.get(mid + 1).docBase == midValue) {
           mid++; // scan to last match
         }
         return mid;

Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/TermContext.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/TermContext.java?rev=1351591&r1=1351590&r2=1351591&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/TermContext.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/TermContext.java Tue Jun 19 07:39:34 2012
@@ -57,7 +57,7 @@ public final class TermContext {
     if (context.leaves() == null) {
       len = 1;
     } else {
-      len = context.leaves().length;
+      len = context.leaves().size();
     }
     states = new TermState[len];
   }
@@ -85,11 +85,10 @@ public final class TermContext {
     final String field = term.field();
     final BytesRef bytes = term.bytes();
     final TermContext perReaderTermState = new TermContext(context);
-    final AtomicReaderContext[] leaves = context.leaves();
     //if (DEBUG) System.out.println("prts.build term=" + term);
-    for (int i = 0; i < leaves.length; i++) {
+    for (final AtomicReaderContext ctx : context.leaves()) {
       //if (DEBUG) System.out.println("  r=" + leaves[i].reader);
-      final Fields fields = leaves[i].reader().fields();
+      final Fields fields = ctx.reader().fields();
       if (fields != null) {
         final Terms terms = fields.terms(field);
         if (terms != null) {
@@ -97,7 +96,7 @@ public final class TermContext {
           if (termsEnum.seekExact(bytes, cache)) { 
             final TermState termState = termsEnum.termState();
             //if (DEBUG) System.out.println("    found");
-            perReaderTermState.register(termState, leaves[i].ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
+            perReaderTermState.register(termState, ctx.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
           }
         }
       }