Index: lucene/core/src/java/org/apache/lucene/codecs/intblock/FixedIntBlockIndexInput.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/intblock/FixedIntBlockIndexInput.java (revision 1352570) +++ lucene/core/src/java/org/apache/lucene/codecs/intblock/FixedIntBlockIndexInput.java (working copy) @@ -75,7 +75,8 @@ public void readBlock() throws IOException; } - private static class Reader extends IntIndexInput.Reader { + // nocommit public + public static class Reader extends IntIndexInput.Reader { private final IndexInput in; protected final int[] pending; @@ -103,21 +104,38 @@ pendingFP = fp; pendingUpto = upto; seekPending = true; + //System.out.println("seek fp=" + fp + " upto=" + upto); } - private void maybeSeek() throws IOException { + // nocommit + public void maybeSeek() throws IOException { + //System.out.println("maybeSeek: " + seekPending); if (seekPending) { if (pendingFP != lastBlockFP) { // need new block + //System.out.println(" seek fp=" + pendingFP); in.seek(pendingFP); lastBlockFP = pendingFP; blockReader.readBlock(); } upto = pendingUpto; seekPending = false; + //System.out.println(" upto=" + upto + " this=" + this); } } + public int getUpto() { + return upto; + } + + public int[] getBlock() { + return pending; + } + + public BlockReader getBlockReader() { + return blockReader; + } + @Override public int next() throws IOException { this.maybeSeek(); Index: lucene/core/src/java/org/apache/lucene/codecs/sep/SepPostingsReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/sep/SepPostingsReader.java (revision 1352570) +++ lucene/core/src/java/org/apache/lucene/codecs/sep/SepPostingsReader.java (working copy) @@ -303,7 +303,8 @@ return postingsEnum.init(fieldInfo, termState, liveDocs); } - class SepDocsEnum extends DocsEnum { + // nocommit public + public class SepDocsEnum extends DocsEnum { int docFreq; int doc = -1; int accum; @@ -348,6 +349,14 @@ } } + public IntIndexInput.Reader getDocReader() { + return docReader; + } + + public IntIndexInput.Reader getFreqReader() { + return freqReader; + } + SepDocsEnum init(FieldInfo fieldInfo, SepTermState termState, Bits liveDocs) throws IOException { this.liveDocs = liveDocs; this.indexOptions = fieldInfo.getIndexOptions(); Index: lucene/core/src/java/org/apache/lucene/search/BlockTermScorer.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/BlockTermScorer.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/search/BlockTermScorer.java (working copy) @@ -0,0 +1,146 @@ +package org.apache.lucene.search; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; + +import org.apache.lucene.codecs.intblock.FixedIntBlockIndexInput; +import org.apache.lucene.index.DocsEnum; +import org.apache.lucene.search.similarities.Similarity; +import org.apache.lucene.util.Bits; + +/** Expert: A Scorer for documents matching a Term. + */ +final class BlockTermScorer extends Scorer { + private final FixedIntBlockIndexInput.BlockReader docBlockReader; + private final FixedIntBlockIndexInput.BlockReader freqBlockReader; + private final Similarity.ExactSimScorer docScorer; + private final int[] docBuffer; + private final int[] freqBuffer; + private final Bits acceptDocs; + private final int bufferLen; + private final int docFreq; + + private int upto; + private int bufferUpto; + private int docID; + private int freq; + + /** + * Construct a TermScorer. + * + * @param weight + * The weight of the Term in the query. + * @param td + * An iterator over the documents matching the Term. + * @param docScorer + * The Similarity.ExactSimScorer implementation + * to be used for score computations. + */ + BlockTermScorer(Weight weight, + FixedIntBlockIndexInput.Reader docBlockReader, + FixedIntBlockIndexInput.Reader freqBlockReader, + Bits acceptDocs, + int docFreq, + Similarity.ExactSimScorer docScorer) throws IOException { + super(weight); + this.docScorer = docScorer; + this.docBlockReader = docBlockReader.getBlockReader(); + this.freqBlockReader = freqBlockReader.getBlockReader(); + this.acceptDocs = acceptDocs; + this.docFreq = docFreq; + docBlockReader.maybeSeek(); + freqBlockReader.maybeSeek(); + bufferUpto = docBlockReader.getUpto(); + docBuffer = docBlockReader.getBlock(); + freqBuffer = freqBlockReader.getBlock(); + bufferLen = docBuffer.length; + assert docBuffer.length == freqBuffer.length; + assert bufferUpto == freqBlockReader.getUpto(): upto + " vs " + freqBlockReader.getUpto() + " dF=" + docFreq; + //System.out.println("dF=" + docFreq); + } + + @Override + public int docID() { + return docID; + } + + @Override + public float freq() throws IOException { + return freq; + } + + /** + * Advances to the next document matching the query.
+ * + * @return the document matching the query or NO_MORE_DOCS if there are no more documents. + */ + @Override + public int nextDoc() throws IOException { + while (true) { + if (upto == docFreq) { + return docID = NO_MORE_DOCS; + } + + upto++; + + if (bufferUpto == bufferLen) { + //System.out.println("readBlock"); + docBlockReader.readBlock(); + freqBlockReader.readBlock(); + bufferUpto = 0; + } + docID += docBuffer[bufferUpto]; + if (acceptDocs != null && !acceptDocs.get(docID)) { + bufferUpto++; + continue; + } + + freq = freqBuffer[bufferUpto]; + bufferUpto++; + //System.out.println(" doc=" + docID + " bufferUpto=" + bufferUpto + " freq=" + freq); + + return docID; + } + } + + @Override + public float score() throws IOException { + assert docID() != NO_MORE_DOCS; + return docScorer.score(docID, freq); + } + + /** + * Advances to the first match beyond the current whose document number is + * greater than or equal to a given target.
+ * The implementation uses {@link DocsEnum#advance(int)}. + * + * @param target + * The target document number. + * @return the matching document or NO_MORE_DOCS if none exist. + */ + @Override + public int advance(int target) throws IOException { + throw new UnsupportedOperationException(); + } + + /** Returns a string representation of this TermScorer. */ + @Override + public String toString() { return "scorer(" + weight + ")"; } + +} Index: lucene/core/src/java/org/apache/lucene/search/TermQuery.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/TermQuery.java (revision 1352570) +++ lucene/core/src/java/org/apache/lucene/search/TermQuery.java (working copy) @@ -20,9 +20,12 @@ import java.io.IOException; import java.util.Set; +import org.apache.lucene.codecs.intblock.FixedIntBlockIndexInput; +import org.apache.lucene.codecs.sep.IntIndexInput; +import org.apache.lucene.codecs.sep.SepPostingsReader.SepDocsEnum; +import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.IndexReaderContext; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermState; @@ -43,6 +46,13 @@ private final int docFreq; private final TermContext perReaderTermState; + private boolean noSkip; + + // nocommit + public void setNoSkip() { + noSkip = true; + } + final class TermWeight extends Weight { private final Similarity similarity; private final Similarity.SimWeight stats; @@ -85,7 +95,24 @@ } DocsEnum docs = termsEnum.docs(acceptDocs, null, true); if (docs != null) { - return new TermScorer(this, docs, createDocScorer(context)); + if ((topScorer || noSkip) && docs instanceof SepDocsEnum) { + SepDocsEnum sepDocs = (SepDocsEnum) docs; + IntIndexInput.Reader docReader = sepDocs.getDocReader(); + IntIndexInput.Reader freqReader = sepDocs.getFreqReader(); + if (docReader instanceof FixedIntBlockIndexInput.Reader) { + assert freqReader instanceof FixedIntBlockIndexInput.Reader; + return new BlockTermScorer(this, + (FixedIntBlockIndexInput.Reader) docReader, + (FixedIntBlockIndexInput.Reader) freqReader, + acceptDocs, + termsEnum.docFreq(), + createDocScorer(context)); + } else { + return new TermScorer(this, docs, createDocScorer(context)); + } + } else { + return new TermScorer(this, docs, createDocScorer(context)); + } } else { // Index does not store freq info docs = termsEnum.docs(acceptDocs, null, false);