You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2013/05/07 13:21:14 UTC

svn commit: r1479862 [14/38] - in /lucene/dev/branches/lucene4258: ./ dev-tools/ dev-tools/idea/.idea/ dev-tools/idea/.idea/libraries/ dev-tools/maven/ dev-tools/maven/solr/ dev-tools/maven/solr/core/src/java/ dev-tools/maven/solr/solrj/src/java/ dev-t...

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxScorer.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxScorer.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxScorer.java Tue May  7 11:20:55 2013
@@ -28,6 +28,7 @@ class DisjunctionMaxScorer extends Disju
   /* Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. */
   private final float tieBreakerMultiplier;
   private int doc = -1;
+  private int freq = -1;
 
   /* Used when scoring currently matching doc. */
   private float scoreSum;
@@ -55,8 +56,8 @@ class DisjunctionMaxScorer extends Disju
 
   @Override
   public int nextDoc() throws IOException {
-    if (numScorers == 0) return doc = NO_MORE_DOCS;
-    while (subScorers[0].docID() == doc) {
+    assert doc != NO_MORE_DOCS;
+    while(true) {
       if (subScorers[0].nextDoc() != NO_MORE_DOCS) {
         heapAdjust(0);
       } else {
@@ -65,9 +66,11 @@ class DisjunctionMaxScorer extends Disju
           return doc = NO_MORE_DOCS;
         }
       }
+      if (subScorers[0].docID() != doc) {
+        afterNext();
+        return doc;
+      }
     }
-    
-    return doc = subScorers[0].docID();
   }
 
   @Override
@@ -80,47 +83,40 @@ class DisjunctionMaxScorer extends Disju
    */
   @Override
   public float score() throws IOException {
-    int doc = subScorers[0].docID();
-    scoreSum = scoreMax = subScorers[0].score();
-    int size = numScorers;
-    scoreAll(1, size, doc);
-    scoreAll(2, size, doc);
     return scoreMax + (scoreSum - scoreMax) * tieBreakerMultiplier;
   }
+  
+  private void afterNext() throws IOException {
+    doc = subScorers[0].docID();
+    if (doc != NO_MORE_DOCS) {
+      scoreSum = scoreMax = subScorers[0].score();
+      freq = 1;
+      scoreAll(1);
+      scoreAll(2);
+    }
+  }
 
   // Recursively iterate all subScorers that generated last doc computing sum and max
-  private void scoreAll(int root, int size, int doc) throws IOException {
-    if (root < size && subScorers[root].docID() == doc) {
+  private void scoreAll(int root) throws IOException {
+    if (root < numScorers && subScorers[root].docID() == doc) {
       float sub = subScorers[root].score();
+      freq++;
       scoreSum += sub;
       scoreMax = Math.max(scoreMax, sub);
-      scoreAll((root<<1)+1, size, doc);
-      scoreAll((root<<1)+2, size, doc);
+      scoreAll((root<<1)+1);
+      scoreAll((root<<1)+2);
     }
   }
 
   @Override
   public int freq() throws IOException {
-    int doc = subScorers[0].docID();
-    int size = numScorers;
-    return 1 + freq(1, size, doc) + freq(2, size, doc);
-  }
-  
-  // Recursively iterate all subScorers that generated last doc computing sum and max
-  private int freq(int root, int size, int doc) throws IOException {
-    int freq = 0;
-    if (root < size && subScorers[root].docID() == doc) {
-      freq++;
-      freq += freq((root<<1)+1, size, doc);
-      freq += freq((root<<1)+2, size, doc);
-    }
     return freq;
   }
 
   @Override
   public int advance(int target) throws IOException {
-    if (numScorers == 0) return doc = NO_MORE_DOCS;
-    while (subScorers[0].docID() < target) {
+    assert doc != NO_MORE_DOCS;
+    while(true) {
       if (subScorers[0].advance(target) != NO_MORE_DOCS) {
         heapAdjust(0);
       } else {
@@ -129,7 +125,10 @@ class DisjunctionMaxScorer extends Disju
           return doc = NO_MORE_DOCS;
         }
       }
+      if (subScorers[0].docID() >= target) {
+        afterNext();
+        return doc;
+      }
     }
-    return doc = subScorers[0].docID();
   }
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DisjunctionSumScorer.java Tue May  7 11:20:55 2013
@@ -17,84 +17,58 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
-import java.util.List;
 import java.io.IOException;
 
 /** A Scorer for OR like queries, counterpart of <code>ConjunctionScorer</code>.
  * This Scorer implements {@link Scorer#advance(int)} and uses advance() on the given Scorers. 
  */
 class DisjunctionSumScorer extends DisjunctionScorer { 
-  /** The minimum number of scorers that should match. */
-  private final int minimumNrMatchers;
-  
   /** The document number of the current match. */
   private int doc = -1;
 
   /** The number of subscorers that provide the current match. */
   protected int nrMatchers = -1;
 
-  private double score = Float.NaN;
+  protected double score = Float.NaN;
+  private final float[] coord;
   
   /** Construct a <code>DisjunctionScorer</code>.
    * @param weight The weight to be used.
-   * @param subScorers A collection of at least two subscorers.
-   * @param minimumNrMatchers The positive minimum number of subscorers that should
-   * match to match this query.
-   * <br>When <code>minimumNrMatchers</code> is bigger than
-   * the number of <code>subScorers</code>,
-   * no matches will be produced.
-   * <br>When minimumNrMatchers equals the number of subScorers,
-   * it more efficient to use <code>ConjunctionScorer</code>.
+   * @param subScorers Array of at least two subscorers.
+   * @param coord Table of coordination factors
    */
-  public DisjunctionSumScorer(Weight weight, List<Scorer> subScorers, int minimumNrMatchers) throws IOException {
-    super(weight, subScorers.toArray(new Scorer[subScorers.size()]), subScorers.size());
+  DisjunctionSumScorer(Weight weight, Scorer[] subScorers, float[] coord) throws IOException {
+    super(weight, subScorers, subScorers.length);
 
-    if (minimumNrMatchers <= 0) {
-      throw new IllegalArgumentException("Minimum nr of matchers must be positive");
-    }
     if (numScorers <= 1) {
       throw new IllegalArgumentException("There must be at least 2 subScorers");
     }
-
-    this.minimumNrMatchers = minimumNrMatchers;
-  }
-  
-  /** Construct a <code>DisjunctionScorer</code>, using one as the minimum number
-   * of matching subscorers.
-   */
-  public DisjunctionSumScorer(Weight weight, List<Scorer> subScorers) throws IOException {
-    this(weight, subScorers, 1);
+    this.coord = coord;
   }
 
   @Override
   public int nextDoc() throws IOException {
     assert doc != NO_MORE_DOCS;
     while(true) {
-      while (subScorers[0].docID() == doc) {
-        if (subScorers[0].nextDoc() != NO_MORE_DOCS) {
-          heapAdjust(0);
-        } else {
-          heapRemoveRoot();
-          if (numScorers < minimumNrMatchers) {
-            return doc = NO_MORE_DOCS;
-          }
+      if (subScorers[0].nextDoc() != NO_MORE_DOCS) {
+        heapAdjust(0);
+      } else {
+        heapRemoveRoot();
+        if (numScorers == 0) {
+          return doc = NO_MORE_DOCS;
         }
       }
-      afterNext();
-      if (nrMatchers >= minimumNrMatchers) {
-        break;
+      if (subScorers[0].docID() != doc) {
+        afterNext();
+        return doc;
       }
     }
-    
-    return doc;
   }
   
   private void afterNext() throws IOException {
     final Scorer sub = subScorers[0];
     doc = sub.docID();
-    if (doc == NO_MORE_DOCS) {
-      nrMatchers = Integer.MAX_VALUE; // stop looping
-    } else {
+    if (doc != NO_MORE_DOCS) {
       score = sub.score();
       nrMatchers = 1;
       countMatches(1);
@@ -104,9 +78,8 @@ class DisjunctionSumScorer extends Disju
   
   // TODO: this currently scores, but so did the previous impl
   // TODO: remove recursion.
-  // TODO: if we separate scoring, out of here, modify this
-  // and afterNext() to terminate when nrMatchers == minimumNrMatchers
-  // then also change freq() to just always compute it from scratch
+  // TODO: if we separate scoring, out of here, 
+  // then change freq() to just always compute it from scratch
   private void countMatches(int root) throws IOException {
     if (root < numScorers && subScorers[root].docID() == doc) {
       nrMatchers++;
@@ -121,7 +94,7 @@ class DisjunctionSumScorer extends Disju
    */
   @Override
   public float score() throws IOException { 
-    return (float)score; 
+    return (float)score * coord[nrMatchers]; 
   }
    
   @Override
@@ -146,8 +119,8 @@ class DisjunctionSumScorer extends Disju
    */
   @Override
   public int advance(int target) throws IOException {
-    if (numScorers == 0) return doc = NO_MORE_DOCS;
-    while (subScorers[0].docID() < target) {
+    assert doc != NO_MORE_DOCS;
+    while(true) {
       if (subScorers[0].advance(target) != NO_MORE_DOCS) {
         heapAdjust(0);
       } else {
@@ -156,14 +129,10 @@ class DisjunctionSumScorer extends Disju
           return doc = NO_MORE_DOCS;
         }
       }
-    }
-    
-    afterNext();
-
-    if (nrMatchers >= minimumNrMatchers) {
-      return doc;
-    } else {
-      return nextDoc();
+      if (subScorers[0].docID() >= target) {
+        afterNext();
+        return doc;
+      }
     }
   }
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSet.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSet.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSet.java Tue May  7 11:20:55 2013
@@ -26,40 +26,8 @@ import org.apache.lucene.util.Bits;
  */
 public abstract class DocIdSet {
 
-  /** An empty {@code DocIdSet} instance for easy use, e.g. in Filters that hit no documents. */
-  public static final DocIdSet EMPTY_DOCIDSET = new DocIdSet() {
-    
-    private final DocIdSetIterator iterator = new DocIdSetIterator() {
-      @Override
-      public int advance(int target) { return NO_MORE_DOCS; }
-      @Override
-      public int docID() { return NO_MORE_DOCS; }
-      @Override
-      public int nextDoc() { return NO_MORE_DOCS; }
-      @Override
-      public long cost() { return 0; }
-    };
-    
-    @Override
-    public DocIdSetIterator iterator() {
-      return iterator;
-    }
-    
-    @Override
-    public boolean isCacheable() {
-      return true;
-    }
-    
-    // we explicitely provide no random access, as this filter is 100% sparse and iterator exits faster
-    @Override
-    public Bits bits() {
-      return null;
-    }
-  };
-    
   /** Provides a {@link DocIdSetIterator} to access the set.
-   * This implementation can return <code>null</code> or
-   * <code>{@linkplain #EMPTY_DOCIDSET}.iterator()</code> if there
+   * This implementation can return <code>null</code> if there
    * are no docs that match. */
   public abstract DocIdSetIterator iterator() throws IOException;
 

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocIdSetIterator.java Tue May  7 11:20:55 2013
@@ -28,6 +28,37 @@ import java.io.IOException;
  */
 public abstract class DocIdSetIterator {
   
+  /** An empty {@code DocIdSetIterator} instance */
+  public static final DocIdSetIterator empty() {
+    return new DocIdSetIterator() {
+      boolean exhausted = false;
+      
+      @Override
+      public int advance(int target) {
+        assert !exhausted;
+        assert target >= 0;
+        exhausted = true;
+        return NO_MORE_DOCS;
+      }
+      
+      @Override
+      public int docID() {
+        return exhausted ? NO_MORE_DOCS : -1;
+      }
+      @Override
+      public int nextDoc() {
+        assert !exhausted;
+        exhausted = true;
+        return NO_MORE_DOCS;
+      }
+      
+      @Override
+      public long cost() {
+        return 0;
+      }
+    };
+  }
+  
   /**
    * When returned by {@link #nextDoc()}, {@link #advance(int)} and
    * {@link #docID()} it means there are no more docs in the iterator.
@@ -37,7 +68,7 @@ public abstract class DocIdSetIterator {
   /**
    * Returns the following:
    * <ul>
-   * <li>-1 or {@link #NO_MORE_DOCS} if {@link #nextDoc()} or
+   * <li><code>-1</code> if {@link #nextDoc()} or
    * {@link #advance(int)} were not called yet.
    * <li>{@link #NO_MORE_DOCS} if the iterator has exhausted.
    * <li>Otherwise it should return the doc ID it is currently on.
@@ -93,6 +124,17 @@ public abstract class DocIdSetIterator {
    */
   public abstract int advance(int target) throws IOException;
 
+  /** Slow (linear) implementation of {@link #advance} relying on
+   *  {@link #nextDoc()} to advance beyond the target position. */
+  protected final int slowAdvance(int target) throws IOException {
+    assert docID() < target;
+    int doc;
+    do {
+      doc = nextDoc();
+    } while (doc < target);
+    return doc;
+  }
+
   /**
    * Returns the estimated cost of this {@link DocIdSetIterator}.
    * <p>

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRangeFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRangeFilter.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRangeFilter.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRangeFilter.java Tue May  7 11:20:55 2013
@@ -90,7 +90,7 @@ public abstract class DocTermOrdsRangeFi
         }      
 
         if (inclusiveUpperPoint < 0 || inclusiveLowerPoint > inclusiveUpperPoint) {
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         }
         
         assert inclusiveLowerPoint >= 0 && inclusiveUpperPoint >= 0;

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRewriteMethod.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRewriteMethod.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRewriteMethod.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/DocTermOrdsRewriteMethod.java Tue May  7 11:20:55 2013
@@ -143,7 +143,7 @@ public final class DocTermOrdsRewriteMet
           termSet.set(termsEnum.ord());
         } while (termsEnum.next() != null);
       } else {
-        return DocIdSet.EMPTY_DOCIDSET;
+        return null;
       }
       
       return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java Tue May  7 11:20:55 2013
@@ -121,7 +121,7 @@ public abstract class FieldCacheRangeFil
         }      
 
         if (inclusiveUpperPoint < 0 || inclusiveLowerPoint > inclusiveUpperPoint) {
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         }
         
         assert inclusiveLowerPoint >= 0 && inclusiveUpperPoint >= 0;
@@ -178,7 +178,7 @@ public abstract class FieldCacheRangeFil
         }      
 
         if (inclusiveUpperPoint < 0 || inclusiveLowerPoint > inclusiveUpperPoint) {
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         }
         
         assert inclusiveLowerPoint >= 0 && inclusiveUpperPoint >= 0;
@@ -216,7 +216,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           final byte i = lowerVal.byteValue();
           if (!includeLower && i == Byte.MAX_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveLowerPoint = (byte) (includeLower ?  i : (i + 1));
         } else {
           inclusiveLowerPoint = Byte.MIN_VALUE;
@@ -224,14 +224,14 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           final byte i = upperVal.byteValue();
           if (!includeUpper && i == Byte.MIN_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveUpperPoint = (byte) (includeUpper ? i : (i - 1));
         } else {
           inclusiveUpperPoint = Byte.MAX_VALUE;
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Bytes values = FieldCache.DEFAULT.getBytes(context.reader(), field, (FieldCache.ByteParser) parser, false);
         return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {
@@ -267,7 +267,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           short i = lowerVal.shortValue();
           if (!includeLower && i == Short.MAX_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveLowerPoint = (short) (includeLower ? i : (i + 1));
         } else {
           inclusiveLowerPoint = Short.MIN_VALUE;
@@ -275,14 +275,14 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           short i = upperVal.shortValue();
           if (!includeUpper && i == Short.MIN_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveUpperPoint = (short) (includeUpper ? i : (i - 1));
         } else {
           inclusiveUpperPoint = Short.MAX_VALUE;
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Shorts values = FieldCache.DEFAULT.getShorts(context.reader(), field, (FieldCache.ShortParser) parser, false);
         return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {
@@ -318,7 +318,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           int i = lowerVal.intValue();
           if (!includeLower && i == Integer.MAX_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveLowerPoint = includeLower ? i : (i + 1);
         } else {
           inclusiveLowerPoint = Integer.MIN_VALUE;
@@ -326,14 +326,14 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           int i = upperVal.intValue();
           if (!includeUpper && i == Integer.MIN_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveUpperPoint = includeUpper ? i : (i - 1);
         } else {
           inclusiveUpperPoint = Integer.MAX_VALUE;
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Ints values = FieldCache.DEFAULT.getInts(context.reader(), field, (FieldCache.IntParser) parser, false);
         return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {
@@ -369,7 +369,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           long i = lowerVal.longValue();
           if (!includeLower && i == Long.MAX_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveLowerPoint = includeLower ? i : (i + 1L);
         } else {
           inclusiveLowerPoint = Long.MIN_VALUE;
@@ -377,14 +377,14 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           long i = upperVal.longValue();
           if (!includeUpper && i == Long.MIN_VALUE)
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           inclusiveUpperPoint = includeUpper ? i : (i - 1L);
         } else {
           inclusiveUpperPoint = Long.MAX_VALUE;
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Longs values = FieldCache.DEFAULT.getLongs(context.reader(), field, (FieldCache.LongParser) parser, false);
         return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {
@@ -422,7 +422,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           float f = lowerVal.floatValue();
           if (!includeUpper && f > 0.0f && Float.isInfinite(f))
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           int i = NumericUtils.floatToSortableInt(f);
           inclusiveLowerPoint = NumericUtils.sortableIntToFloat( includeLower ?  i : (i + 1) );
         } else {
@@ -431,7 +431,7 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           float f = upperVal.floatValue();
           if (!includeUpper && f < 0.0f && Float.isInfinite(f))
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           int i = NumericUtils.floatToSortableInt(f);
           inclusiveUpperPoint = NumericUtils.sortableIntToFloat( includeUpper ? i : (i - 1) );
         } else {
@@ -439,7 +439,7 @@ public abstract class FieldCacheRangeFil
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Floats values = FieldCache.DEFAULT.getFloats(context.reader(), field, (FieldCache.FloatParser) parser, false);
         return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {
@@ -477,7 +477,7 @@ public abstract class FieldCacheRangeFil
         if (lowerVal != null) {
           double f = lowerVal.doubleValue();
           if (!includeUpper && f > 0.0 && Double.isInfinite(f))
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           long i = NumericUtils.doubleToSortableLong(f);
           inclusiveLowerPoint = NumericUtils.sortableLongToDouble( includeLower ?  i : (i + 1L) );
         } else {
@@ -486,7 +486,7 @@ public abstract class FieldCacheRangeFil
         if (upperVal != null) {
           double f = upperVal.doubleValue();
           if (!includeUpper && f < 0.0 && Double.isInfinite(f))
-            return DocIdSet.EMPTY_DOCIDSET;
+            return null;
           long i = NumericUtils.doubleToSortableLong(f);
           inclusiveUpperPoint = NumericUtils.sortableLongToDouble( includeUpper ? i : (i - 1L) );
         } else {
@@ -494,7 +494,7 @@ public abstract class FieldCacheRangeFil
         }
         
         if (inclusiveLowerPoint > inclusiveUpperPoint)
-          return DocIdSet.EMPTY_DOCIDSET;
+          return null;
         
         final FieldCache.Doubles values = FieldCache.DEFAULT.getDoubles(context.reader(), field, (FieldCache.DoubleParser) parser, false);
         // ignore deleted docs if range doesn't contain 0

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRewriteMethod.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRewriteMethod.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRewriteMethod.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FieldCacheRewriteMethod.java Tue May  7 11:20:55 2013
@@ -146,7 +146,7 @@ public final class FieldCacheRewriteMeth
           }
         } while (termsEnum.next() != null);
       } else {
-        return DocIdSet.EMPTY_DOCIDSET;
+        return null;
       }
       
       return new FieldCacheDocIdSet(context.reader().maxDoc(), acceptDocs) {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Filter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Filter.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Filter.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Filter.java Tue May  7 11:20:55 2013
@@ -21,7 +21,6 @@ import java.io.IOException;
 
 import org.apache.lucene.index.AtomicReader; // javadocs
 import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.IndexReader; // javadocs
 import org.apache.lucene.util.Bits;
 
 /** 
@@ -53,8 +52,9 @@ public abstract class Filter {
    *          but possibly filtering other documents)
    *          
    * @return a DocIdSet that provides the documents which should be permitted or
-   *         prohibited in search results. <b>NOTE:</b> null can be returned if
-   *         no documents will be accepted by this Filter.
+   *         prohibited in search results. <b>NOTE:</b> <code>null</code> should be returned if
+   *         the filter doesn't accept any documents otherwise internal optimization might not apply
+   *         in the case an <i>empty</i> {@link DocIdSet} is returned.
    */
   public abstract DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws IOException;
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java Tue May  7 11:20:55 2013
@@ -102,9 +102,9 @@ public class FilteredQuery extends Query
         Explanation inner = weight.explain (ir, i);
         Filter f = FilteredQuery.this.filter;
         DocIdSet docIdSet = f.getDocIdSet(ir, ir.reader().getLiveDocs());
-        DocIdSetIterator docIdSetIterator = docIdSet == null ? DocIdSet.EMPTY_DOCIDSET.iterator() : docIdSet.iterator();
+        DocIdSetIterator docIdSetIterator = docIdSet == null ? DocIdSetIterator.empty() : docIdSet.iterator();
         if (docIdSetIterator == null) {
-          docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.iterator();
+          docIdSetIterator = DocIdSetIterator.empty();
         }
         if (docIdSetIterator.advance(i) == i) {
           return inner;
@@ -240,11 +240,11 @@ public class FilteredQuery extends Query
     // optimization: we are topScorer and collect directly using short-circuited algo
     @Override
     public final void score(Collector collector) throws IOException {
-      int primDoc = primaryNext();
-      int secDoc = secondary.advance(primDoc);
       // the normalization trick already applies the boost of this query,
       // so we can use the wrapped scorer directly:
       collector.setScorer(scorer);
+      int primDoc = primaryNext();
+      int secDoc = secondary.advance(primDoc);
       for (;;) {
         if (primDoc == secDoc) {
           // Check if scorer has exhausted, only before collecting.

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java Tue May  7 11:20:55 2013
@@ -32,7 +32,6 @@ import java.util.concurrent.ExecutorServ
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.apache.lucene.document.Document;
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.index.DirectoryReader; // javadocs
 import org.apache.lucene.index.IndexReader;
@@ -427,6 +426,12 @@ public class IndexSearcher {
    *         {@link BooleanQuery#getMaxClauseCount()} clauses.
    */
   protected TopDocs search(Weight weight, ScoreDoc after, int nDocs) throws IOException {
+    int limit = reader.maxDoc();
+    if (limit == 0) {
+      limit = 1;
+    }
+    nDocs = Math.min(nDocs, limit);
+    
     if (executor == null) {
       return search(leafContexts, weight, after, nDocs);
     } else {
@@ -512,6 +517,12 @@ public class IndexSearcher {
 
     if (sort == null) throw new NullPointerException("Sort must not be null");
     
+    int limit = reader.maxDoc();
+    if (limit == 0) {
+      limit = 1;
+    }
+    nDocs = Math.min(nDocs, limit);
+
     if (executor == null) {
       // use all leaves here!
       return search(leafContexts, weight, after, nDocs, sort, fillFields, doDocScores, doMaxScore);
@@ -592,10 +603,21 @@ public class IndexSearcher {
     // threaded...?  the Collector could be sync'd?
     // always use single thread:
     for (AtomicReaderContext ctx : leaves) { // search each subreader
-      collector.setNextReader(ctx);
+      try {
+        collector.setNextReader(ctx);
+      } catch (CollectionTerminatedException e) {
+        // there is no doc of interest in this reader context
+        // continue with the following leaf
+        continue;
+      }
       Scorer scorer = weight.scorer(ctx, !collector.acceptsDocsOutOfOrder(), true, ctx.reader().getLiveDocs());
       if (scorer != null) {
-        scorer.score(collector);
+        try {
+          scorer.score(collector);
+        } catch (CollectionTerminatedException e) {
+          // collection was terminated prematurely
+          // continue with the following leaf
+        }
       }
     }
   }
@@ -794,7 +816,7 @@ public class IndexSearcher {
     public TopFieldDocs call() throws IOException {
       assert slice.leaves.length == 1;
       final TopFieldDocs docs = searcher.search(Arrays.asList(slice.leaves),
-          weight, after, nDocs, sort, true, doDocScores, doMaxScore);
+          weight, after, nDocs, sort, true, doDocScores || sort.needsScores(), doMaxScore);
       lock.lock();
       try {
         final AtomicReaderContext ctx = slice.leaves[0];

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java Tue May  7 11:20:55 2013
@@ -241,7 +241,7 @@ public class MultiPhraseQuery extends Qu
 
       // sort by increasing docFreq order
       if (slop == 0) {
-        ArrayUtil.mergeSort(postingsFreqs);
+        ArrayUtil.timSort(postingsFreqs);
       }
 
       if (slop == 0) {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQuery.java Tue May  7 11:20:55 2013
@@ -248,8 +248,10 @@ public abstract class MultiTermQuery ext
    * Term.
    */
   public MultiTermQuery(final String field) {
+    if (field == null) {
+      throw new IllegalArgumentException("field must not be null");
+    }
     this.field = field;
-    assert field != null;
   }
 
   /** Returns the field name for this query */

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryWrapperFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryWrapperFilter.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryWrapperFilter.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/MultiTermQueryWrapperFilter.java Tue May  7 11:20:55 2013
@@ -88,13 +88,13 @@ public class MultiTermQueryWrapperFilter
     final Fields fields = reader.fields();
     if (fields == null) {
       // reader has no fields
-      return DocIdSet.EMPTY_DOCIDSET;
+      return null;
     }
 
     final Terms terms = fields.terms(query.field);
     if (terms == null) {
       // field does not exist
-      return DocIdSet.EMPTY_DOCIDSET;
+      return null;
     }
 
     final TermsEnum termsEnum = query.getTermsEnum(terms);
@@ -116,7 +116,7 @@ public class MultiTermQueryWrapperFilter
 
       return bitSet;
     } else {
-      return DocIdSet.EMPTY_DOCIDSET;
+      return null;
     }
   }
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/NGramPhraseQuery.java Tue May  7 11:20:55 2013
@@ -64,6 +64,7 @@ public class NGramPhraseQuery extends Ph
 
     // now create the new optimized phrase query for n-gram
     PhraseQuery optimized = new PhraseQuery();
+    optimized.setBoost(getBoost());
     int pos = 0;
     final int lastPos = terms.length - 1;
     for(int i = 0; i < terms.length; i++){

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java Tue May  7 11:20:55 2013
@@ -278,7 +278,7 @@ public class PhraseQuery extends Query {
 
       // sort by increasing docFreq order
       if (slop == 0) {
-        ArrayUtil.mergeSort(postingsFreqs);
+        ArrayUtil.timSort(postingsFreqs);
       }
 
       if (slop == 0) {  // optimize exact case

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/ReferenceManager.java Tue May  7 11:20:55 2013
@@ -81,7 +81,7 @@ public abstract class ReferenceManager<G
    * the operation was successful.
    * @throws AlreadyClosedException if the reference manager has been {@link #close() closed}. 
    */
-  protected abstract boolean tryIncRef(G reference);
+  protected abstract boolean tryIncRef(G reference) throws IOException;
 
   /**
    * Obtain the current reference. You must match every call to acquire with one
@@ -90,7 +90,7 @@ public abstract class ReferenceManager<G
    * released.
    * @throws AlreadyClosedException if the reference manager has been {@link #close() closed}. 
    */
-  public final G acquire() {
+  public final G acquire() throws IOException {
     G ref;
     do {
       if ((ref = current) == null) {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Scorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Scorer.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Scorer.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Scorer.java Tue May  7 11:20:55 2013
@@ -58,6 +58,7 @@ public abstract class Scorer extends Doc
    * @param collector The collector to which all matching documents are passed.
    */
   public void score(Collector collector) throws IOException {
+    assert docID() == -1; // not started
     collector.setScorer(this);
     int doc;
     while ((doc = nextDoc()) != NO_MORE_DOCS) {
@@ -80,11 +81,11 @@ public abstract class Scorer extends Doc
    * @return true if more matching documents may remain.
    */
   public boolean score(Collector collector, int max, int firstDocID) throws IOException {
+    assert docID() == firstDocID;
     collector.setScorer(this);
-    int doc = firstDocID;
-    while (doc < max) {
+    int doc;
+    for (doc = firstDocID; doc < max; doc = nextDoc()) {
       collector.collect(doc);
-      doc = nextDoc();
     }
     return doc != NO_MORE_DOCS;
   }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherFactory.java Tue May  7 11:20:55 2013
@@ -26,7 +26,7 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.lucene.search.similarities.Similarity; // javadocs
 
 /**
- * Factory class used by {@link SearcherManager} and {@link NRTManager} to
+ * Factory class used by {@link SearcherManager} to
  * create new IndexSearchers. The default implementation just creates 
  * an IndexSearcher with no custom behavior:
  * 

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherLifetimeManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherLifetimeManager.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherLifetimeManager.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherLifetimeManager.java Tue May  7 11:20:55 2013
@@ -24,7 +24,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.lucene.search.NRTManager;        // javadocs
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.util.IOUtils;
@@ -41,8 +40,8 @@ import org.apache.lucene.util.IOUtils;
  *
  * Per search-request, if it's a "new" search request, then
  * obtain the latest searcher you have (for example, by
- * using {@link SearcherManager} or {@link NRTManager}), and
- * then record this searcher:
+ * using {@link SearcherManager}), and then record this
+ * searcher:
  *
  * <pre class="prettyprint">
  *   // Record the current searcher, and save the returend
@@ -143,8 +142,7 @@ public class SearcherLifetimeManager imp
 
   /** Records that you are now using this IndexSearcher.
    *  Always call this when you've obtained a possibly new
-   *  {@link IndexSearcher}, for example from one of the
-   *  <code>get</code> methods in {@link NRTManager} or {@link
+   *  {@link IndexSearcher}, for example from {@link
    *  SearcherManager}.  It's fine if you already passed the
    *  same searcher to this method before.
    *

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SearcherManager.java Tue May  7 11:20:55 2013
@@ -144,8 +144,11 @@ public final class SearcherManager exten
     }
   }
 
-  // NOTE: decRefs incoming reader on throwing an exception
-  static IndexSearcher getSearcher(SearcherFactory searcherFactory, IndexReader reader) throws IOException {
+  /** Expert: creates a searcher from the provided {@link
+   *  IndexReader} using the provided {@link
+   *  SearcherFactory}.  NOTE: this decRefs incoming reader
+   * on throwing an exception. */
+  public static IndexSearcher getSearcher(SearcherFactory searcherFactory, IndexReader reader) throws IOException {
     boolean success = false;
     final IndexSearcher searcher;
     try {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java Tue May  7 11:20:55 2013
@@ -561,7 +561,7 @@ final class SloppyPhraseScorer extends S
 
   @Override
   public int nextDoc() throws IOException {
-    return advance(max.doc);
+    return advance(max.doc + 1); // advance to the next doc after #docID()
   }
   
   @Override
@@ -571,27 +571,25 @@ final class SloppyPhraseScorer extends S
 
   @Override
   public int advance(int target) throws IOException {
-    sloppyFreq = 0.0f;
-    if (!advanceMin(target)) {
-      return NO_MORE_DOCS;
-    }        
-    boolean restart=false;
-    while (sloppyFreq == 0.0f) {
-      while (min.doc < max.doc || restart) {
-        restart = false;
+    assert target > docID();
+    do {
+      if (!advanceMin(target)) {
+        return NO_MORE_DOCS;
+      }
+      while (min.doc < max.doc) {
         if (!advanceMin(max.doc)) {
           return NO_MORE_DOCS;
-        }        
+        }
       }
       // found a doc with all of the terms
       sloppyFreq = phraseFreq(); // check for phrase
-      restart = true;
-    } 
+      target = min.doc + 1; // next target in case sloppyFreq is still 0
+    } while (sloppyFreq == 0f);
 
     // found a match
     return max.doc;
   }
-  
+
   @Override
   public long cost() {
     return cost;

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Sort.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Sort.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Sort.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/Sort.java Tue May  7 11:20:55 2013
@@ -201,4 +201,15 @@ public class Sort {
   public int hashCode() {
     return 0x45aaf665 + Arrays.hashCode(fields);
   }
+
+  /** Whether the relevance score is needed to sort documents. */
+  boolean needsScores() {
+    for (SortField sortField : fields) {
+      if (sortField.getType() == SortField.Type.SCORE) {
+        return true;
+      }
+    }
+    return false;
+  }
+
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TermRangeQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TermRangeQuery.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TermRangeQuery.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TermRangeQuery.java Tue May  7 11:20:55 2013
@@ -19,6 +19,7 @@ package org.apache.lucene.search;
 
 import java.io.IOException;
 
+import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.util.AttributeSource;
@@ -122,9 +123,9 @@ public class TermRangeQuery extends Mult
       }
       buffer.append(includeLower ? '[' : '{');
       // TODO: all these toStrings for queries should just output the bytes, it might not be UTF-8!
-      buffer.append(lowerTerm != null ? ("*".equals(lowerTerm.utf8ToString()) ? "\\*" : lowerTerm.utf8ToString())  : "*");
+      buffer.append(lowerTerm != null ? ("*".equals(Term.toString(lowerTerm)) ? "\\*" : Term.toString(lowerTerm))  : "*");
       buffer.append(" TO ");
-      buffer.append(upperTerm != null ? ("*".equals(upperTerm.utf8ToString()) ? "\\*" : upperTerm.utf8ToString()) : "*");
+      buffer.append(upperTerm != null ? ("*".equals(Term.toString(upperTerm)) ? "\\*" : Term.toString(upperTerm)) : "*");
       buffer.append(includeUpper ? ']' : '}');
       buffer.append(ToStringUtils.boost(getBoost()));
       return buffer.toString();

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/TopTermsRewrite.java Tue May  7 11:20:55 2013
@@ -156,7 +156,7 @@ public abstract class TopTermsRewrite<Q 
     
     final Q q = getTopLevelQuery();
     final ScoreTerm[] scoreTerms = stQueue.toArray(new ScoreTerm[stQueue.size()]);
-    ArrayUtil.mergeSort(scoreTerms, scoreTermSortByTermComp);
+    ArrayUtil.timSort(scoreTerms, scoreTermSortByTermComp);
     
     for (final ScoreTerm st : scoreTerms) {
       final Term term = new Term(query.field, st.bytes);

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java Tue May  7 11:20:55 2013
@@ -204,7 +204,7 @@ public class NearSpansOrdered extends Sp
 
   /** Advance the subSpans to the same document */
   private boolean toSameDoc() throws IOException {
-    ArrayUtil.mergeSort(subSpansByDoc, spanDocComparator);
+    ArrayUtil.timSort(subSpansByDoc, spanDocComparator);
     int firstIndex = 0;
     int maxDoc = subSpansByDoc[subSpansByDoc.length - 1].doc();
     while (subSpansByDoc[firstIndex].doc() != maxDoc) {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java Tue May  7 11:20:55 2013
@@ -42,12 +42,8 @@ public class SpanScorer extends Scorer {
     this.docScorer = docScorer;
     this.spans = spans;
 
-    if (this.spans.next()) {
-      doc = -1;
-    } else {
-      doc = NO_MORE_DOCS;
-      more = false;
-    }
+    doc = -1;
+    more = spans.next();
   }
 
   @Override

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/Spans.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/Spans.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/Spans.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/Spans.java Tue May  7 11:20:55 2013
@@ -29,7 +29,11 @@ public abstract class Spans {
   public abstract boolean next() throws IOException;
 
   /** Skips to the first match beyond the current, whose document number is
-   * greater than or equal to <i>target</i>. <p>Returns true iff there is such
+   * greater than or equal to <i>target</i>.
+   * <p>The behavior of this method is <b>undefined</b> when called with
+   * <code> target &le; current</code>, or after the iterator has exhausted.
+   * Both cases may result in unpredicted behavior.
+   * <p>Returns true iff there is such
    * a match.  <p>Behaves as if written: <pre class="prettyprint">
    *   boolean skipTo(int target) {
    *     do {

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java Tue May  7 11:20:55 2013
@@ -71,6 +71,7 @@ public class TermSpans extends Spans {
 
   @Override
   public boolean skipTo(int target) throws IOException {
+    assert target > doc;
     doc = postings.advance(target);
     if (doc == DocIdSetIterator.NO_MORE_DOCS) {
       return false;

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/Directory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/Directory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/Directory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/Directory.java Tue May  7 11:20:55 2013
@@ -184,7 +184,7 @@ public abstract class Directory implemen
    * <pre class="prettyprint">
    * Directory to; // the directory to copy to
    * for (String file : dir.listAll()) {
-   *   dir.copy(to, file, newFile); // newFile can be either file, or a new name
+   *   dir.copy(to, file, newFile, IOContext.DEFAULT); // newFile can be either file, or a new name
    * }
    * </pre>
    * <p>

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java Tue May  7 11:20:55 2013
@@ -298,8 +298,12 @@ public abstract class FSDirectory extend
       throw new IOException("Cannot overwrite: " + file);
   }
 
-  protected void onIndexOutputClosed(FSIndexOutput io) {
-    staleFiles.add(io.name);
+  /**
+   * Sub classes should call this method on closing an open {@link IndexOutput}, reporting the name of the file
+   * that was closed. {@code FSDirectory} needs this information to take care of syncing stale files.
+   */
+  protected void onIndexOutputClosed(String name) {
+    staleFiles.add(name);
   }
 
   @Override
@@ -392,65 +396,6 @@ public abstract class FSDirectory extend
     return chunkSize;
   }
 
-  /** Base class for reading input from a RandomAccessFile */
-  protected abstract static class FSIndexInput extends BufferedIndexInput {
-    /** the underlying RandomAccessFile */
-    protected final RandomAccessFile file;
-    boolean isClone = false;
-    /** maximum read length on a 32bit JVM to prevent incorrect OOM, see LUCENE-1566 */ 
-    protected final int chunkSize;
-    /** start offset: non-zero in the slice case */
-    protected final long off;
-    /** end offset (start+length) */
-    protected final long end;
-    
-    /** Create a new FSIndexInput, reading the entire file from <code>path</code> */
-    protected FSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException {
-      super(resourceDesc, context);
-      this.file = new RandomAccessFile(path, "r"); 
-      this.chunkSize = chunkSize;
-      this.off = 0L;
-      this.end = file.length();
-    }
-    
-    /** Create a new FSIndexInput, representing a slice of an existing open <code>file</code> */
-    protected FSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) {
-      super(resourceDesc, bufferSize);
-      this.file = file;
-      this.chunkSize = chunkSize;
-      this.off = off;
-      this.end = off + length;
-      this.isClone = true; // well, we are sorta?
-    }
-    
-    @Override
-    public void close() throws IOException {
-      // only close the file if this is not a clone
-      if (!isClone) {
-        file.close();
-      }
-    }
-    
-    @Override
-    public FSIndexInput clone() {
-      FSIndexInput clone = (FSIndexInput)super.clone();
-      clone.isClone = true;
-      return clone;
-    }
-    
-    @Override
-    public final long length() {
-      return end - off;
-    }
-    
-    /** Method used for testing. Returns true if the underlying
-     *  file descriptor is valid.
-     */
-    boolean isFDValid() throws IOException {
-      return file.getFD().valid();
-    }
-  }
-  
   /**
    * Writes output with {@link RandomAccessFile#write(byte[], int, int)}
    */
@@ -476,7 +421,7 @@ public abstract class FSDirectory extend
     
     @Override
     public void close() throws IOException {
-      parent.onIndexOutputClosed(this);
+      parent.onIndexOutputClosed(name);
       // only close the file if it has not been closed yet
       if (isOpen) {
         boolean success = false;

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java Tue May  7 11:20:55 2013
@@ -19,11 +19,11 @@ package org.apache.lucene.store;
  
 import java.io.IOException;
 import java.io.File;
-import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException; // javadoc @link
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.StandardOpenOption;
 
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
@@ -133,7 +133,7 @@ public class MMapDirectory extends FSDir
     this.chunkSizePower = 31 - Integer.numberOfLeadingZeros(maxChunkSize);
     assert this.chunkSizePower >= 0 && this.chunkSizePower <= 30;
   }
-
+  
   /**
    * <code>true</code>, if this platform supports unmapping mmapped files.
    */
@@ -189,12 +189,9 @@ public class MMapDirectory extends FSDir
   @Override
   public IndexInput openInput(String name, IOContext context) throws IOException {
     ensureOpen();
-    File f = new File(getDirectory(), name);
-    RandomAccessFile raf = new RandomAccessFile(f, "r");
-    try {
-      return new MMapIndexInput("MMapIndexInput(path=\"" + f + "\")", raf);
-    } finally {
-      raf.close();
+    File file = new File(getDirectory(), name);
+    try (FileChannel c = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
+      return new MMapIndexInput("MMapIndexInput(path=\"" + file.toString() + "\")", c);
     }
   }
   
@@ -218,8 +215,8 @@ public class MMapDirectory extends FSDir
   private final class MMapIndexInput extends ByteBufferIndexInput {
     private final boolean useUnmapHack;
     
-    MMapIndexInput(String resourceDescription, RandomAccessFile raf) throws IOException {
-      super(resourceDescription, map(raf, 0, raf.length()), raf.length(), chunkSizePower, getUseUnmap());
+    MMapIndexInput(String resourceDescription, FileChannel fc) throws IOException {
+      super(resourceDescription, map(fc, 0, fc.size()), fc.size(), chunkSizePower, getUseUnmap());
       this.useUnmapHack = getUseUnmap();
     }
     
@@ -256,9 +253,9 @@ public class MMapDirectory extends FSDir
   }
   
   /** Maps a file into a set of buffers */
-  ByteBuffer[] map(RandomAccessFile raf, long offset, long length) throws IOException {
+  ByteBuffer[] map(FileChannel fc, long offset, long length) throws IOException {
     if ((length >>> chunkSizePower) >= Integer.MAX_VALUE)
-      throw new IllegalArgumentException("RandomAccessFile too big for chunk size: " + raf.toString());
+      throw new IllegalArgumentException("RandomAccessFile too big for chunk size: " + fc.toString());
     
     final long chunkSize = 1L << chunkSizePower;
     
@@ -268,13 +265,12 @@ public class MMapDirectory extends FSDir
     ByteBuffer buffers[] = new ByteBuffer[nrBuffers];
     
     long bufferStart = 0L;
-    FileChannel rafc = raf.getChannel();
     for (int bufNr = 0; bufNr < nrBuffers; bufNr++) { 
       int bufSize = (int) ( (length > (bufferStart + chunkSize))
           ? chunkSize
               : (length - bufferStart)
           );
-      buffers[bufNr] = rafc.map(MapMode.READ_ONLY, offset + bufferStart, bufSize);
+      buffers[bufNr] = fc.map(MapMode.READ_ONLY, offset + bufferStart, bufSize);
       bufferStart += bufSize;
     }
     

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java Tue May  7 11:20:55 2013
@@ -20,10 +20,10 @@ package org.apache.lucene.store;
 import java.io.File;
 import java.io.EOFException;
 import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException; // javadoc @link
 import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
 import java.util.concurrent.Future; // javadoc
 
 /**
@@ -77,7 +77,9 @@ public class NIOFSDirectory extends FSDi
   @Override
   public IndexInput openInput(String name, IOContext context) throws IOException {
     ensureOpen();
-    return new NIOFSIndexInput(new File(getDirectory(), name), context, getReadChunkSize());
+    File path = new File(getDirectory(), name);
+    FileChannel fc = FileChannel.open(path.toPath(), StandardOpenOption.READ);
+    return new NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context, getReadChunkSize());
   }
   
   @Override
@@ -85,7 +87,7 @@ public class NIOFSDirectory extends FSDi
       final IOContext context) throws IOException {
     ensureOpen();
     final File path = new File(getDirectory(), name);
-    final RandomAccessFile descriptor = new RandomAccessFile(path, "r");
+    final FileChannel descriptor = FileChannel.open(path.toPath(), StandardOpenOption.READ);
     return new Directory.IndexInputSlicer() {
 
       @Override
@@ -95,7 +97,7 @@ public class NIOFSDirectory extends FSDi
 
       @Override
       public IndexInput openSlice(String sliceDescription, long offset, long length) {
-        return new NIOFSIndexInput(sliceDescription, path, descriptor, descriptor.getChannel(), offset,
+        return new NIOFSIndexInput("NIOFSIndexInput(" + sliceDescription + " in path=\"" + path + "\" slice=" + offset + ":" + (offset+length) + ")", descriptor, offset,
             length, BufferedIndexInput.bufferSize(context), getReadChunkSize());
       }
     };
@@ -104,21 +106,54 @@ public class NIOFSDirectory extends FSDi
   /**
    * Reads bytes with {@link FileChannel#read(ByteBuffer, long)}
    */
-  protected static class NIOFSIndexInput extends FSIndexInput {
-
+  protected static class NIOFSIndexInput extends BufferedIndexInput {
+    /** the file channel we will read from */
+    protected final FileChannel channel;
+    /** is this instance a clone and hence does not own the file to close it */
+    boolean isClone = false;
+    /** maximum read length on a 32bit JVM to prevent incorrect OOM, see LUCENE-1566 */ 
+    protected final int chunkSize;
+    /** start offset: non-zero in the slice case */
+    protected final long off;
+    /** end offset (start+length) */
+    protected final long end;
+    
     private ByteBuffer byteBuf; // wraps the buffer for NIO
 
-    final FileChannel channel;
-
-    public NIOFSIndexInput(File path, IOContext context, int chunkSize) throws IOException {
-      super("NIOFSIndexInput(path=\"" + path + "\")", path, context, chunkSize);
-      channel = file.getChannel();
+    public NIOFSIndexInput(String resourceDesc, FileChannel fc, IOContext context, int chunkSize) throws IOException {
+      super(resourceDesc, context);
+      this.channel = fc; 
+      this.chunkSize = chunkSize;
+      this.off = 0L;
+      this.end = fc.size();
+    }
+    
+    public NIOFSIndexInput(String resourceDesc, FileChannel fc, long off, long length, int bufferSize, int chunkSize) {
+      super(resourceDesc, bufferSize);
+      this.channel = fc;
+      this.chunkSize = chunkSize;
+      this.off = off;
+      this.end = off + length;
+      this.isClone = true;
+    }
+    
+    @Override
+    public void close() throws IOException {
+      if (!isClone) {
+        channel.close();
+      }
     }
     
-    public NIOFSIndexInput(String sliceDescription, File path, RandomAccessFile file, FileChannel fc, long off, long length, int bufferSize, int chunkSize) {
-      super("NIOFSIndexInput(" + sliceDescription + " in path=\"" + path + "\" slice=" + off + ":" + (off+length) + ")", file, off, length, bufferSize, chunkSize);
-      channel = fc;
-      isClone = true;
+    @Override
+    public NIOFSIndexInput clone() {
+      NIOFSIndexInput clone = (NIOFSIndexInput)super.clone();
+      clone.isClone = true;
+      return clone;
+    }
+    
+    @Override
+    public final long length() {
+      return end - off;
     }
 
     @Override
@@ -186,5 +221,4 @@ public class NIOFSDirectory extends FSDi
     @Override
     protected void seekInternal(long pos) throws IOException {}
   }
-
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java Tue May  7 11:20:55 2013
@@ -55,7 +55,8 @@ public class SimpleFSDirectory extends F
   public IndexInput openInput(String name, IOContext context) throws IOException {
     ensureOpen();
     final File path = new File(directory, name);
-    return new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + path.getPath() + "\")", path, context, getReadChunkSize());
+    RandomAccessFile raf = new RandomAccessFile(path, "r");
+    return new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + path.getPath() + "\")", raf, context, getReadChunkSize());
   }
 
   @Override
@@ -83,14 +84,52 @@ public class SimpleFSDirectory extends F
    * Reads bytes with {@link RandomAccessFile#seek(long)} followed by
    * {@link RandomAccessFile#read(byte[], int, int)}.  
    */
-  protected static class SimpleFSIndexInput extends FSIndexInput {
-  
-    public SimpleFSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException {
-      super(resourceDesc, path, context, chunkSize);
+  protected static class SimpleFSIndexInput extends BufferedIndexInput {
+    /** the file channel we will read from */
+    protected final RandomAccessFile file;
+    /** is this instance a clone and hence does not own the file to close it */
+    boolean isClone = false;
+    /** maximum read length on a 32bit JVM to prevent incorrect OOM, see LUCENE-1566 */ 
+    protected final int chunkSize;
+    /** start offset: non-zero in the slice case */
+    protected final long off;
+    /** end offset (start+length) */
+    protected final long end;
+    
+    public SimpleFSIndexInput(String resourceDesc, RandomAccessFile file, IOContext context, int chunkSize) throws IOException {
+      super(resourceDesc, context);
+      this.file = file; 
+      this.chunkSize = chunkSize;
+      this.off = 0L;
+      this.end = file.length();
     }
     
     public SimpleFSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) {
-      super(resourceDesc, file, off, length, bufferSize, chunkSize);
+      super(resourceDesc, bufferSize);
+      this.file = file;
+      this.chunkSize = chunkSize;
+      this.off = off;
+      this.end = off + length;
+      this.isClone = true;
+    }
+    
+    @Override
+    public void close() throws IOException {
+      if (!isClone) {
+        file.close();
+      }
+    }
+    
+    @Override
+    public SimpleFSIndexInput clone() {
+      SimpleFSIndexInput clone = (SimpleFSIndexInput)super.clone();
+      clone.isClone = true;
+      return clone;
+    }
+    
+    @Override
+    public final long length() {
+      return end - off;
     }
   
     /** IndexInput methods */
@@ -136,5 +175,9 @@ public class SimpleFSDirectory extends F
     @Override
     protected void seekInternal(long position) {
     }
+    
+    boolean isFDValid() throws IOException {
+      return file.getFD().valid();
+    }
   }
 }

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/ArrayUtil.java Tue May  7 11:20:55 2013
@@ -604,161 +604,85 @@ public final class ArrayUtil {
 
     return result;
   }
-  
-  /** SorterTemplate with custom {@link Comparator} */
-  private static <T> SorterTemplate getSorter(final T[] a, final Comparator<? super T> comp) {
-    return new SorterTemplate() {
-      @Override
-      protected void swap(int i, int j) {
-        final T o = a[i];
-        a[i] = a[j];
-        a[j] = o;
-      }
-      
-      @Override
-      protected int compare(int i, int j) {
-        return comp.compare(a[i], a[j]);
-      }
 
-      @Override
-      protected void setPivot(int i) {
-        pivot = a[i];
-      }
-  
-      @Override
-      protected int comparePivot(int j) {
-        return comp.compare(pivot, a[j]);
-      }
-      
-      private T pivot;
-    };
+  private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> {
+    NaturalComparator() {}
+    @Override
+    public int compare(T o1, T o2) {
+      return o1.compareTo(o2);
+    }
   }
-  
-  /** Natural SorterTemplate */
-  private static <T extends Comparable<? super T>> SorterTemplate getSorter(final T[] a) {
-    return new SorterTemplate() {
-      @Override
-      protected void swap(int i, int j) {
-        final T o = a[i];
-        a[i] = a[j];
-        a[j] = o;
-      }
-      
-      @Override
-      protected int compare(int i, int j) {
-        return a[i].compareTo(a[j]);
-      }
 
-      @Override
-      protected void setPivot(int i) {
-        pivot = a[i];
-      }
-  
-      @Override
-      protected int comparePivot(int j) {
-        return pivot.compareTo(a[j]);
-      }
-      
-      private T pivot;
-    };
-  }
+  private static final Comparator<?> NATURAL_COMPARATOR = new NaturalComparator<>();
 
-  // quickSorts (endindex is exclusive!):
-  
-  /**
-   * Sorts the given array slice using the {@link Comparator}. This method uses the quick sort
-   * algorithm, but falls back to insertion sort for small arrays.
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T> void quickSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a, comp).quickSort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array using the {@link Comparator}. This method uses the quick sort
-   * algorithm, but falls back to insertion sort for small arrays.
-   */
-  public static <T> void quickSort(T[] a, Comparator<? super T> comp) {
-    quickSort(a, 0, a.length, comp);
+  /** Get the natural {@link Comparator} for the provided object class. */
+  @SuppressWarnings("unchecked")
+  public static <T extends Comparable<? super T>> Comparator<T> naturalComparator() {
+    return (Comparator<T>) NATURAL_COMPARATOR;
   }
-  
-  /**
-   * Sorts the given array slice in natural order. This method uses the quick sort
-   * algorithm, but falls back to insertion sort for small arrays.
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T extends Comparable<? super T>> void quickSort(T[] a, int fromIndex, int toIndex) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a).quickSort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array in natural order. This method uses the quick sort
-   * algorithm, but falls back to insertion sort for small arrays.
-   */
-  public static <T extends Comparable<? super T>> void quickSort(T[] a) {
-    quickSort(a, 0, a.length);
+
+  /** Swap values stored in slots <code>i</code> and <code>j</code> */
+  public static <T> void swap(T[] arr, int i, int j) {
+    final T tmp = arr[i];
+    arr[i] = arr[j];
+    arr[j] = tmp;
   }
 
-  // mergeSorts:
+  // intro-sorts
   
   /**
-   * Sorts the given array slice using the {@link Comparator}. This method uses the merge sort
+   * Sorts the given array slice using the {@link Comparator}. This method uses the intro sort
    * algorithm, but falls back to insertion sort for small arrays.
    * @param fromIndex start index (inclusive)
    * @param toIndex end index (exclusive)
    */
-  public static <T> void mergeSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
+  public static <T> void introSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
     if (toIndex-fromIndex <= 1) return;
-    //System.out.println("SORT: " + (toIndex-fromIndex));
-    getSorter(a, comp).mergeSort(fromIndex, toIndex-1);
+    new ArrayIntroSorter<>(a, comp).sort(fromIndex, toIndex);
   }
   
   /**
-   * Sorts the given array using the {@link Comparator}. This method uses the merge sort
+   * Sorts the given array using the {@link Comparator}. This method uses the intro sort
    * algorithm, but falls back to insertion sort for small arrays.
    */
-  public static <T> void mergeSort(T[] a, Comparator<? super T> comp) {
-    mergeSort(a, 0, a.length, comp);
+  public static <T> void introSort(T[] a, Comparator<? super T> comp) {
+    introSort(a, 0, a.length, comp);
   }
   
   /**
-   * Sorts the given array slice in natural order. This method uses the merge sort
+   * Sorts the given array slice in natural order. This method uses the intro sort
    * algorithm, but falls back to insertion sort for small arrays.
    * @param fromIndex start index (inclusive)
    * @param toIndex end index (exclusive)
    */
-  public static <T extends Comparable<? super T>> void mergeSort(T[] a, int fromIndex, int toIndex) {
+  public static <T extends Comparable<? super T>> void introSort(T[] a, int fromIndex, int toIndex) {
     if (toIndex-fromIndex <= 1) return;
-    getSorter(a).mergeSort(fromIndex, toIndex-1);
+    introSort(a, fromIndex, toIndex, ArrayUtil.<T>naturalComparator());
   }
   
   /**
-   * Sorts the given array in natural order. This method uses the merge sort
+   * Sorts the given array in natural order. This method uses the intro sort
    * algorithm, but falls back to insertion sort for small arrays.
    */
-  public static <T extends Comparable<? super T>> void mergeSort(T[] a) {
-    mergeSort(a, 0, a.length);
+  public static <T extends Comparable<? super T>> void introSort(T[] a) {
+    introSort(a, 0, a.length);
   }
 
-  // timSorts:
-
+  // tim sorts:
+  
   /**
-   * Sorts the given array slice using the {@link Comparator}. This method uses the TimSort
+   * Sorts the given array slice using the {@link Comparator}. This method uses the Tim sort
    * algorithm, but falls back to binary sort for small arrays.
    * @param fromIndex start index (inclusive)
    * @param toIndex end index (exclusive)
    */
   public static <T> void timSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
     if (toIndex-fromIndex <= 1) return;
-    getSorter(a, comp).timSort(fromIndex, toIndex-1);
+    new ArrayTimSorter<>(a, comp, a.length / 64).sort(fromIndex, toIndex);
   }
   
   /**
-   * Sorts the given array using the {@link Comparator}. This method uses the TimSort
+   * Sorts the given array using the {@link Comparator}. This method uses the Tim sort
    * algorithm, but falls back to binary sort for small arrays.
    */
   public static <T> void timSort(T[] a, Comparator<? super T> comp) {
@@ -766,102 +690,22 @@ public final class ArrayUtil {
   }
   
   /**
-   * Sorts the given array slice in natural order. This method uses the TimSort
+   * Sorts the given array slice in natural order. This method uses the Tim sort
    * algorithm, but falls back to binary sort for small arrays.
    * @param fromIndex start index (inclusive)
    * @param toIndex end index (exclusive)
    */
   public static <T extends Comparable<? super T>> void timSort(T[] a, int fromIndex, int toIndex) {
     if (toIndex-fromIndex <= 1) return;
-    getSorter(a).timSort(fromIndex, toIndex-1);
+    timSort(a, fromIndex, toIndex, ArrayUtil.<T>naturalComparator());
   }
   
   /**
-   * Sorts the given array in natural order. This method uses the TimSort
+   * Sorts the given array in natural order. This method uses the Tim sort
    * algorithm, but falls back to binary sort for small arrays.
    */
   public static <T extends Comparable<? super T>> void timSort(T[] a) {
     timSort(a, 0, a.length);
   }
 
-  // insertionSorts:
-  
-  /**
-   * Sorts the given array slice using the {@link Comparator}. This method uses the insertion sort
-   * algorithm. It is only recommended to use this algorithm for partially sorted small arrays!
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T> void insertionSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a, comp).insertionSort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array using the {@link Comparator}. This method uses the insertion sort
-   * algorithm. It is only recommended to use this algorithm for partially sorted small arrays!
-   */
-  public static <T> void insertionSort(T[] a, Comparator<? super T> comp) {
-    insertionSort(a, 0, a.length, comp);
-  }
-  
-  /**
-   * Sorts the given array slice in natural order. This method uses the insertion sort
-   * algorithm. It is only recommended to use this algorithm for partially sorted small arrays!
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T extends Comparable<? super T>> void insertionSort(T[] a, int fromIndex, int toIndex) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a).insertionSort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array in natural order. This method uses the insertion sort
-   * algorithm. It is only recommended to use this algorithm for partially sorted small arrays!
-   */
-  public static <T extends Comparable<? super T>> void insertionSort(T[] a) {
-    insertionSort(a, 0, a.length);
-  }
-
-  // binarySorts:
-
-  /**
-   * Sorts the given array slice using the {@link Comparator}. This method uses the binary sort
-   * algorithm. It is only recommended to use this algorithm for small arrays!
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T> void binarySort(T[] a, int fromIndex, int toIndex, Comparator<? super T> comp) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a, comp).binarySort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array using the {@link Comparator}. This method uses the binary sort
-   * algorithm. It is only recommended to use this algorithm for small arrays!
-   */
-  public static <T> void binarySort(T[] a, Comparator<? super T> comp) {
-    binarySort(a, 0, a.length, comp);
-  }
-  
-  /**
-   * Sorts the given array slice in natural order. This method uses the binary sort
-   * algorithm. It is only recommended to use this algorithm for small arrays!
-   * @param fromIndex start index (inclusive)
-   * @param toIndex end index (exclusive)
-   */
-  public static <T extends Comparable<? super T>> void binarySort(T[] a, int fromIndex, int toIndex) {
-    if (toIndex-fromIndex <= 1) return;
-    getSorter(a).binarySort(fromIndex, toIndex-1);
-  }
-  
-  /**
-   * Sorts the given array in natural order. This method uses the binary sort
-   * algorithm. It is only recommended to use this algorithm for small arrays!
-   */
-  public static <T extends Comparable<? super T>> void binarySort(T[] a) {
-    binarySort(a, 0, a.length);
-  }
-
-}
\ No newline at end of file
+}

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/AttributeSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/AttributeSource.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/AttributeSource.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/AttributeSource.java Tue May  7 11:20:55 2013
@@ -55,9 +55,9 @@ public class AttributeSource {
     
     private static final class DefaultAttributeFactory extends AttributeFactory {
       private static final WeakIdentityMap<Class<? extends Attribute>, WeakReference<Class<? extends AttributeImpl>>> attClassImplMap =
-        WeakIdentityMap.newConcurrentHashMap();
+        WeakIdentityMap.newConcurrentHashMap(false);
       
-      private DefaultAttributeFactory() {}
+      DefaultAttributeFactory() {}
     
       @Override
       public AttributeImpl createAttributeInstance(Class<? extends Attribute> attClass) {
@@ -201,7 +201,7 @@ public class AttributeSource {
   
   /** a cache that stores all interfaces for known implementation classes for performance (slow reflection) */
   private static final WeakIdentityMap<Class<? extends AttributeImpl>,LinkedList<WeakReference<Class<? extends Attribute>>>> knownImplClasses =
-    WeakIdentityMap.newConcurrentHashMap();
+    WeakIdentityMap.newConcurrentHashMap(false);
   
   static LinkedList<WeakReference<Class<? extends Attribute>>> getAttributeInterfaces(final Class<? extends AttributeImpl> clazz) {
     LinkedList<WeakReference<Class<? extends Attribute>>> foundInterfaces = knownImplClasses.get(clazz);

Modified: lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/BytesRefHash.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/BytesRefHash.java?rev=1479862&r1=1479861&r2=1479862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/BytesRefHash.java (original)
+++ lucene/dev/branches/lucene4258/lucene/core/src/java/org/apache/lucene/util/BytesRefHash.java Tue May  7 11:20:55 2013
@@ -163,7 +163,7 @@ public final class BytesRefHash {
    */
   public int[] sort(final Comparator<BytesRef> comp) {
     final int[] compact = compact();
-    new SorterTemplate() {
+    new IntroSorter() {
       @Override
       protected void swap(int i, int j) {
         final int o = compact[i];
@@ -197,7 +197,7 @@ public final class BytesRefHash {
       
       private final BytesRef pivot = new BytesRef(),
         scratch1 = new BytesRef(), scratch2 = new BytesRef();
-    }.quickSort(0, count - 1);
+    }.sort(0, count);
     return compact;
   }
 
@@ -402,6 +402,12 @@ public final class BytesRefHash {
     return hashPos;
   }
 
+  /** Adds a "arbitrary" int offset instead of a BytesRef
+   *  term.  This is used in the indexer to hold the hash for term
+   *  vectors, because they do not redundantly store the byte[] term
+   *  directly and instead reference the byte[] term
+   *  already stored by the postings BytesRefHash.  See
+   *  add(int textStart) in TermsHashPerField. */
   public int addByPoolOffset(int offset) {
     assert bytesStart != null : "Bytesstart is null - not initialized";
     // final position