Index: lucene/src/java/org/apache/lucene/search/FieldCache.java =================================================================== --- lucene/src/java/org/apache/lucene/search/FieldCache.java (revision 1172228) +++ lucene/src/java/org/apache/lucene/search/FieldCache.java (working copy) @@ -22,6 +22,7 @@ import org.apache.lucene.util.RamUsageEstimator; import org.apache.lucene.document.NumericField; // for javadocs import org.apache.lucene.analysis.NumericTokenStream; // for javadocs +import org.apache.lucene.util.FixedBitSet; import java.io.IOException; import java.io.Serializable; @@ -315,7 +316,7 @@ * reader.maxDoc(), with turned on bits for each docid that * does not have a value for this field. */ - public DocIdSet getUnValuedDocs (IndexReader reader, String field) + public FixedBitSet getUnValuedDocs (IndexReader reader, String field) throws IOException; /** Checks the internal cache for an appropriate entry, and if none is Index: lucene/src/java/org/apache/lucene/search/FieldCacheImpl.java =================================================================== --- lucene/src/java/org/apache/lucene/search/FieldCacheImpl.java (revision 1172228) +++ lucene/src/java/org/apache/lucene/search/FieldCacheImpl.java (working copy) @@ -32,7 +32,7 @@ import org.apache.lucene.index.TermEnum; import org.apache.lucene.util.BitVector; import org.apache.lucene.util.DocIdBitSet; -import org.apache.lucene.util.OpenBitSet; +import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.StringHelper; import org.apache.lucene.util.FieldCacheSanityChecker; @@ -425,11 +425,13 @@ Entry entry = entryKey; String field = entry.field; + FixedBitSet res = new FixedBitSet(reader.maxDoc()); + if (reader.maxDoc() == reader.docFreq(new Term(field))) { - return DocIdSet.EMPTY_DOCIDSET; + // TODO: maybe return null instead of empty BitSet? + return res; } - OpenBitSet res = new OpenBitSet(reader.maxDoc()); TermDocs termDocs = reader.termDocs(); TermEnum termEnum = reader.terms (new Term (field)); try { @@ -438,7 +440,7 @@ if (term==null || term.field() != field) break; termDocs.seek (termEnum); while (termDocs.next()) { - res.fastSet(termDocs.doc()); + res.set(termDocs.doc()); } } while (termEnum.next()); } finally { @@ -737,9 +739,9 @@ return infoStream; } - public DocIdSet getUnValuedDocs(IndexReader reader, String field) + public FixedBitSet getUnValuedDocs(IndexReader reader, String field) throws IOException { - return (DocIdSet) caches.get(UnValuedDocsCache.class).get(reader, new Entry(field, null)); + return (FixedBitSet) caches.get(UnValuedDocsCache.class).get(reader, new Entry(field, null)); } } Index: lucene/src/java/org/apache/lucene/search/FieldComparator.java =================================================================== --- lucene/src/java/org/apache/lucene/search/FieldComparator.java (revision 1172228) +++ lucene/src/java/org/apache/lucene/search/FieldComparator.java (working copy) @@ -29,7 +29,7 @@ import org.apache.lucene.search.FieldCache.IntParser; import org.apache.lucene.search.FieldCache.ShortParser; import org.apache.lucene.search.FieldCache.StringIndex; -import org.apache.lucene.util.OpenBitSet; +import org.apache.lucene.util.FixedBitSet; /** * Expert: a FieldComparator compares hits so as to determine their @@ -196,6 +196,7 @@ public static final class ByteComparator extends FieldComparator { private final byte[] values; private byte[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private ByteParser parser; private byte bottom; @@ -213,24 +214,26 @@ @Override public int compareBottom(int doc) { - return bottom - currentReaderValues[doc]; + byte v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + return bottom - v2; } @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + byte v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getBytes(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final byte byteValue = missingValue.byteValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = byteValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override @@ -295,6 +298,7 @@ public static final class DoubleComparator extends FieldComparator { private final double[] values; private double[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private DoubleParser parser; private double bottom; @@ -320,7 +324,9 @@ @Override public int compareBottom(int doc) { - final double v2 = currentReaderValues[doc]; + double v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; if (bottom > v2) { return 1; } else if (bottom < v2) { @@ -332,19 +338,18 @@ @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + double v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getDoubles(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final double doubleValue = missingValue.doubleValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = doubleValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override @@ -363,6 +368,7 @@ public static final class FloatComparator extends FieldComparator { private final float[] values; private float[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private FloatParser parser; private float bottom; @@ -392,7 +398,9 @@ public int compareBottom(int doc) { // TODO: are there sneaky non-branch ways to compute // sign of float? - final float v2 = currentReaderValues[doc]; + float v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; if (bottom > v2) { return 1; } else if (bottom < v2) { @@ -404,19 +412,18 @@ @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + float v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getFloats(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final float floatValue = missingValue.floatValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = floatValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override @@ -435,6 +442,7 @@ public static final class IntComparator extends FieldComparator { private final int[] values; private int[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private IntParser parser; private int bottom; // Value of bottom of queue @@ -468,7 +476,9 @@ // -1/+1/0 sign // Cannot return bottom - values[slot2] because that // may overflow - final int v2 = currentReaderValues[doc]; + int v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; if (bottom > v2) { return 1; } else if (bottom < v2) { @@ -480,19 +490,18 @@ @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + int v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getInts(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final int intValue = missingValue.intValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = intValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override @@ -511,6 +520,7 @@ public static final class LongComparator extends FieldComparator { private final long[] values; private long[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private LongParser parser; private long bottom; @@ -540,7 +550,9 @@ public int compareBottom(int doc) { // TODO: there are sneaky non-branch ways to compute // -1/+1/0 sign - final long v2 = currentReaderValues[doc]; + long v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; if (bottom > v2) { return 1; } else if (bottom < v2) { @@ -552,19 +564,18 @@ @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + long v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getLongs(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final long longValue = missingValue.longValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = longValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override @@ -651,6 +662,7 @@ public static final class ShortComparator extends FieldComparator { private final short[] values; private short[] currentReaderValues; + private FixedBitSet unvaluedDocs = null; private final String field; private ShortParser parser; private short bottom; @@ -668,24 +680,26 @@ @Override public int compareBottom(int doc) { - return bottom - currentReaderValues[doc]; + short v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + return bottom - v2; } @Override public void copy(int slot, int doc) { - values[slot] = currentReaderValues[doc]; + short v2 = currentReaderValues[doc]; + if (unvaluedDocs != null && v2 == 0 && unvaluedDocs.get(doc)) + v2 = missingValue; + values[slot] = v2; } @Override public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getShorts(reader, field, parser); - if (missingValue != null) { - DocIdSetIterator iterator = FieldCache.DEFAULT.getUnValuedDocs(reader, field).iterator(); - final short shortValue = missingValue.shortValue(); - for (int doc=iterator.nextDoc(); doc!=DocIdSetIterator.NO_MORE_DOCS; doc=iterator.nextDoc()) { - currentReaderValues[doc] = shortValue; - } - } + unvaluedDocs = (missingValue != null) ? + FieldCache.DEFAULT.getUnValuedDocs(reader, field) : + null; } @Override