Index: BooleanScorer.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/BooleanScorer.java,v retrieving revision 1.14 diff -u -3 -p -u -w -r1.14 BooleanScorer.java --- BooleanScorer.java 10 Dec 2004 19:36:40 -0000 1.14 +++ BooleanScorer.java 16 Jan 2005 21:09:17 -0000 @@ -1,7 +1,8 @@ package org.apache.lucene.search; /** - * Copyright 2004 The Apache Software Foundation + * Copyright 2005 Paul Elschot + * Derived from BooleanScorer of 16 January 2005. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +19,9 @@ package org.apache.lucene.search; import java.io.IOException; +import java.util.Arrays; +import java.util.Comparator; + final class BooleanScorer extends Scorer { private SubScorer scorers = null; private BucketTable bucketTable = new BucketTable(this); @@ -35,7 +39,7 @@ final class BooleanScorer extends Scorer static final class SubScorer { public Scorer scorer; - public boolean done; + public boolean done; // FIXME: remove from next list instead of marking done. public boolean required = false; public boolean prohibited = false; public HitCollector collector; @@ -173,6 +177,8 @@ final class BooleanScorer extends Scorer more = true; } } + + // bucketTable.sortValidListByDocNr(); // sort here to score next() docs in order. } while (bucketTable.first != null || more); return false; @@ -184,6 +190,30 @@ final class BooleanScorer extends Scorer return current.score * coordFactors[current.coord]; } + public boolean skipTo(int target) throws IOException { + if (target < end) { + bucketTable.removeSmallerDocsValidList(target); + current = bucketTable.first; + return (current != null) || next(); + } else { + bucketTable.first = null; // clear valid list + boolean more = false; + for (SubScorer sub = scorers; sub != null; sub = sub.next) { + Scorer scorer = sub.scorer; + if (!sub.done) { + if (target > scorer.doc()) { + more = true; + } else if (scorer.skipTo(target)) { + more = true; + } else { + sub.done = true; + } + } + } + return more && next(); + } + } + static final class Bucket { int doc = -1; // tells if bucket is valid float score; // incremental score @@ -211,6 +241,54 @@ final class BooleanScorer extends Scorer public HitCollector newCollector(int mask) { return new Collector(mask, this); } + + void removeSmallerDocsValidList(int target) { + /* Throw away earlier computed scores, sigh. */ + Bucket b = first; + Bucket prev = first; + while (b != null) { + if (b.doc >= target) { + prev = b; + b = b.next; + } else if (b == prev) { // delete first + b = b.next; + prev = b; + first = b; + } else { // delete later + b = b.next; + prev.next = b; + } + } + } + + private Bucket[] tmpBuckets = new Bucket[SIZE]; + void sortValidListByDocNr() { /* may not be needed */ + Bucket b = first; + int nrValidBuckets = 0; + while (b != null) { + tmpBuckets[nrValidBuckets++] = b; + b = b.next; + } + Arrays.sort(tmpBuckets, 0, nrValidBuckets, + new Comparator() { + public int compare(Object b1, Object b2) { + return ((Bucket) b1).doc - ((Bucket) b2).doc; + } + } + ); + if (nrValidBuckets > 0) { + first = tmpBuckets[0]; + b = tmpBuckets[0]; + for (int i = 1; i < nrValidBuckets; i++) { + if (b.doc >= tmpBuckets[i].doc) { + throw new AssertionError("tmpBuckets not sorted"); + } + b.next = tmpBuckets[i]; + b = tmpBuckets[i]; + } + b.next = null; + } + } } static final class Collector extends HitCollector { @@ -243,10 +321,6 @@ final class BooleanScorer extends Scorer } } - public boolean skipTo(int target) { - throw new UnsupportedOperationException(); - } - public Explanation explain(int doc) { throw new UnsupportedOperationException(); } @@ -261,6 +335,5 @@ final class BooleanScorer extends Scorer buffer.append(")"); return buffer.toString(); } - }