Index: lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java
--- lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java Mon Feb 28 08:24:50 2011 -0500
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java Mon Feb 28 11:41:31 2011 -0500
@@ -62,10 +62,7 @@
reader = iw.getReader();
iw.close();
- // TODO: we should be able to use newSearcher, but custom sorts are broken if IS has an executorservice
- // see LUCENE-2941
- //searcher = newSearcher(reader);
- searcher = new IndexSearcher(reader);
+ searcher = newSearcher(reader);
}
@AfterClass
Index: lucene/src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java
--- lucene/src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java Mon Feb 28 08:24:50 2011 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-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 org.apache.lucene.util.PriorityQueue;
-import org.apache.lucene.util.BytesRef;
-
-/**
- * Expert: Collects sorted results from Searchable's and collates them.
- * The elements put into this queue must be of type FieldDoc.
- *
- *
Created: Feb 11, 2004 2:04:21 PM
- *
- * @since lucene 1.4
- */
-class FieldDocSortedHitQueue extends PriorityQueue {
-
- volatile SortField[] fields = null;
-
- /**
- * Creates a hit queue sorted by the given list of fields.
- * @param fields Fieldable names, in priority order (highest priority first).
- * @param size The number of hits to retain. Must be greater than zero.
- */
- FieldDocSortedHitQueue (int size) {
- initialize (size);
- }
-
-
- /**
- * Allows redefinition of sort fields if they are null.
- * This is to handle the case using ParallelMultiSearcher where the
- * original list contains AUTO and we don't know the actual sort
- * type until the values come back. The fields can only be set once.
- * This method should be synchronized external like all other PQ methods.
- * @param fields
- */
- void setFields (SortField[] fields) {
- this.fields = fields;
- }
-
-
- /** Returns the fields being used to sort. */
- SortField[] getFields() {
- return fields;
- }
-
- /**
- * Returns whether a is less relevant than b.
- * @param a ScoreDoc
- * @param b ScoreDoc
- * @return true if document a should be sorted after document b.
- */
- @SuppressWarnings("unchecked") @Override
- protected final boolean lessThan(final FieldDoc docA, final FieldDoc docB) {
- final int n = fields.length;
- int c = 0;
- for (int i=0; i docB.doc;
-
- return c > 0;
- }
-}
Index: lucene/src/java/org/apache/lucene/search/IndexSearcher.java
--- lucene/src/java/org/apache/lucene/search/IndexSearcher.java Mon Feb 28 08:24:50 2011 -0500
+++ lucene/src/java/org/apache/lucene/search/IndexSearcher.java Mon Feb 28 11:41:31 2011 -0500
@@ -442,13 +442,17 @@
// use all leaves here!
return search (leafContexts, weight, filter, nDocs, sort, fillFields);
} else {
- // TODO: make this respect fillFields
- final FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue(nDocs);
+ final TopFieldCollector topCollector = TopFieldCollector.create(sort, nDocs,
+ fillFields,
+ fieldSortDoTrackScores,
+ fieldSortDoMaxScore,
+ false);
+
final Lock lock = new ReentrantLock();
final ExecutionHelper runner = new ExecutionHelper(executor);
for (int i = 0; i < leafSlices.length; i++) { // search each leaf slice
runner.submit(
- new SearcherCallableWithSort(lock, this, leafSlices[i], weight, filter, nDocs, hq, sort));
+ new SearcherCallableWithSort(lock, this, leafSlices[i], weight, filter, nDocs, topCollector, sort));
}
int totalHits = 0;
float maxScore = Float.NEGATIVE_INFINITY;
@@ -458,11 +462,10 @@
maxScore = Math.max(maxScore, topFieldDocs.getMaxScore());
}
}
- final ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
- for (int i = hq.size() - 1; i >= 0; i--) // put docs in array
- scoreDocs[i] = hq.pop();
- return new TopFieldDocs(totalHits, scoreDocs, hq.getFields(), maxScore);
+ final TopFieldDocs topDocs = (TopFieldDocs) topCollector.topDocs();
+
+ return new TopFieldDocs(totalHits, topDocs.scoreDocs, topDocs.fields, topDocs.getMaxScore());
}
}
@@ -721,12 +724,12 @@
private final Weight weight;
private final Filter filter;
private final int nDocs;
- private final FieldDocSortedHitQueue hq;
+ private final TopFieldCollector hq;
private final Sort sort;
private final LeafSlice slice;
public SearcherCallableWithSort(Lock lock, IndexSearcher searcher, LeafSlice slice, Weight weight,
- Filter filter, int nDocs, FieldDocSortedHitQueue hq, Sort sort) {
+ Filter filter, int nDocs, TopFieldCollector hq, Sort sort) {
this.lock = lock;
this.searcher = searcher;
this.weight = weight;
@@ -737,27 +740,58 @@
this.slice = slice;
}
+ private final class FakeScorer extends Scorer {
+ float score;
+ int doc;
+
+ public FakeScorer() {
+ super(null);
+ }
+
+ @Override
+ public int advance(int target) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int docID() {
+ return doc;
+ }
+
+ @Override
+ public float freq() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int nextDoc() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public float score() {
+ return score;
+ }
+ }
+
+ private final FakeScorer fakeScorer = new FakeScorer();
+
public TopFieldDocs call() throws IOException {
+ assert slice.leaves.length == 1;
final TopFieldDocs docs = searcher.search (slice.leaves, weight, filter, nDocs, sort, true);
lock.lock();
try {
- hq.setFields(docs.fields);
+ final int base = slice.leaves[0].docBase;
+ hq.setNextReader(slice.leaves[0]);
+ hq.setScorer(fakeScorer);
+ for(ScoreDoc scoreDoc : docs.scoreDocs) {
+ fakeScorer.doc = scoreDoc.doc - base;
+ fakeScorer.score = scoreDoc.score;
+ hq.collect(scoreDoc.doc-base);
+ }
} finally {
lock.unlock();
}
-
- final ScoreDoc[] scoreDocs = docs.scoreDocs;
- for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
- final FieldDoc fieldDoc = (FieldDoc) scoreDocs[j];
- //it would be so nice if we had a thread-safe insert
- lock.lock();
- try {
- if (fieldDoc == hq.insertWithOverflow(fieldDoc))
- break;
- } finally {
- lock.unlock();
- }
- }
return docs;
}
}
Index: lucene/src/test/org/apache/lucene/search/TestSort.java
--- lucene/src/test/org/apache/lucene/search/TestSort.java Mon Feb 28 08:24:50 2011 -0500
+++ lucene/src/test/org/apache/lucene/search/TestSort.java Mon Feb 28 11:41:31 2011 -0500
@@ -495,13 +495,15 @@
bottomValue = slotValues[bottom];
}
+ private static final FieldCache.IntParser testIntParser = new FieldCache.IntParser() {
+ public final int parseInt(final BytesRef term) {
+ return (term.bytes[term.offset]-'A') * 123456;
+ }
+ };
+
@Override
public FieldComparator setNextReader(AtomicReaderContext context) throws IOException {
- docValues = FieldCache.DEFAULT.getInts(context.reader, "parser", new FieldCache.IntParser() {
- public final int parseInt(final BytesRef term) {
- return (term.bytes[term.offset]-'A') * 123456;
- }
- });
+ docValues = FieldCache.DEFAULT.getInts(context.reader, "parser", testIntParser);
return this;
}