LUCENE-2953: PriorityQueue's internal heap was made private final

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1079707 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2011-03-09 09:18:56 +00:00
parent b466795470
commit bdaa02c3c0
22 changed files with 92 additions and 79 deletions

View File

@ -202,6 +202,12 @@ API Changes
which takes Analyzer as a parameter, for easier customization by subclasses.
(Robert Muir)
* LUCENE-2953: PriorityQueue's internal heap was made private, as subclassing
with generics can lead to ClassCastException. For advanced use (e.g. in Solr)
a method getHeapArray() was added to retrieve the internal heap array as a
non-generic Object[]. Also the initialize(int) function was moved into the
ctor. (Uwe Schindler, Yonik Seeley)
New features
* LUCENE-2604: Added RegexpQuery support to QueryParser. Regular expressions

View File

@ -524,7 +524,7 @@ class FragmentQueue extends PriorityQueue<TextFragment>
{
public FragmentQueue(int size)
{
initialize(size);
super(size);
}
@Override

View File

@ -255,7 +255,7 @@ final class TotalTermFreqComparatorSortDescending implements Comparator<TermStat
**/
final class TermStatsQueue extends PriorityQueue<TermStats> {
TermStatsQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -335,7 +335,7 @@ public class FuzzyLikeThisQuery extends Query
private static class ScoreTermQueue extends PriorityQueue<ScoreTerm> {
public ScoreTermQueue(int size){
initialize(size);
super(size);
}
/* (non-Javadoc)

View File

@ -1006,7 +1006,7 @@ public final class MoreLikeThis {
*/
private static class FreqQ extends PriorityQueue<Object[]> {
FreqQ (int s) {
initialize(s);
super(s);
}
@Override

View File

@ -41,7 +41,7 @@ public final class SuggestWordQueue extends PriorityQueue<SuggestWord> {
* @param size The size of the queue
*/
public SuggestWordQueue (int size) {
initialize(size);
super(size);
comparator = DEFAULT_COMPARATOR;
}
@ -51,7 +51,7 @@ public final class SuggestWordQueue extends PriorityQueue<SuggestWord> {
* @param comparator The comparator.
*/
public SuggestWordQueue(int size, Comparator<SuggestWord> comparator){
initialize(size);
super(size);
this.comparator = comparator;
}

View File

@ -129,7 +129,7 @@ public final class MultiFieldsEnum extends FieldsEnum {
private final static class FieldMergeQueue extends PriorityQueue<FieldsEnumWithSlice> {
FieldMergeQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -427,7 +427,7 @@ public final class MultiTermsEnum extends TermsEnum {
private final static class TermMergeQueue extends PriorityQueue<TermsEnumWithSlice> {
Comparator<BytesRef> termComp;
TermMergeQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -56,15 +56,13 @@ public abstract class FieldValueHitQueue extends PriorityQueue<FieldValueHitQueu
public OneComparatorFieldValueHitQueue(SortField[] fields, int size)
throws IOException {
super(fields);
super(fields, size);
SortField field = fields[0];
setComparator(0,field.getComparator(size, 0));
oneReverseMul = field.reverse ? -1 : 1;
reverseMul[0] = oneReverseMul;
initialize(size);
}
/**
@ -98,7 +96,7 @@ public abstract class FieldValueHitQueue extends PriorityQueue<FieldValueHitQueu
public MultiComparatorsFieldValueHitQueue(SortField[] fields, int size)
throws IOException {
super(fields);
super(fields, size);
int numComparators = comparators.length;
for (int i = 0; i < numComparators; ++i) {
@ -107,8 +105,6 @@ public abstract class FieldValueHitQueue extends PriorityQueue<FieldValueHitQueu
reverseMul[i] = field.reverse ? -1 : 1;
setComparator(i, field.getComparator(size, i));
}
initialize(size);
}
@Override
@ -133,7 +129,8 @@ public abstract class FieldValueHitQueue extends PriorityQueue<FieldValueHitQueu
}
// prevent instantiation and extension.
private FieldValueHitQueue(SortField[] fields) {
private FieldValueHitQueue(SortField[] fields, int size) {
super(size);
// When we get here, fields.length is guaranteed to be > 0, therefore no
// need to check it again.

View File

@ -63,17 +63,15 @@ final class HitQueue extends PriorityQueue<ScoreDoc> {
* @see #getSentinelObject()
*/
HitQueue(int size, boolean prePopulate) {
this.prePopulate = prePopulate;
initialize(size);
super(size, prePopulate);
}
// Returns null if prePopulate is false.
@Override
protected ScoreDoc getSentinelObject() {
// Always set the doc Id to MAX_VALUE so that it won't be favored by
// lessThan. This generally should not happen since if score is not NEG_INF,
// TopScoreDocCollector will always add the object to the queue.
return !prePopulate ? null : new ScoreDoc(Integer.MAX_VALUE, Float.NEGATIVE_INFINITY);
return new ScoreDoc(Integer.MAX_VALUE, Float.NEGATIVE_INFINITY);
}
@Override

View File

@ -432,7 +432,7 @@ class UnionDocsAndPositionsEnum extends DocsAndPositionsEnum {
private static final class DocsQueue extends PriorityQueue<DocsAndPositionsEnum> {
DocsQueue(List<DocsAndPositionsEnum> docsEnums) throws IOException {
initialize(docsEnums.size());
super(docsEnums.size());
Iterator<DocsAndPositionsEnum> i = docsEnums.iterator();
while (i.hasNext()) {

View File

@ -21,7 +21,7 @@ import org.apache.lucene.util.PriorityQueue;
final class PhraseQueue extends PriorityQueue<PhrasePositions> {
PhraseQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -53,7 +53,7 @@ public class NearSpansUnordered extends Spans {
private class CellQueue extends PriorityQueue<SpansCell> {
public CellQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -145,7 +145,7 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
private class SpanQueue extends PriorityQueue<Spans> {
public SpanQueue(int size) {
initialize(size);
super(size);
}
@Override

View File

@ -28,8 +28,52 @@ package org.apache.lucene.util;
*/
public abstract class PriorityQueue<T> {
private int size;
private int maxSize;
protected T[] heap;
private final int maxSize;
private final T[] heap;
public PriorityQueue(int maxSize) {
this(maxSize, true);
}
@SuppressWarnings("unchecked")
public PriorityQueue(int maxSize, boolean prepopulate) {
size = 0;
int heapSize;
if (0 == maxSize)
// We allocate 1 extra to avoid if statement in top()
heapSize = 2;
else {
if (maxSize == Integer.MAX_VALUE) {
// Don't wrap heapSize to -1, in this case, which
// causes a confusing NegativeArraySizeException.
// Note that very likely this will simply then hit
// an OOME, but at least that's more indicative to
// caller that this values is too big. We don't +1
// in this case, but it's very unlikely in practice
// one will actually insert this many objects into
// the PQ:
heapSize = Integer.MAX_VALUE;
} else {
// NOTE: we add +1 because all access to heap is
// 1-based not 0-based. heap[0] is unused.
heapSize = maxSize + 1;
}
}
heap = (T[]) new Object[heapSize]; // T is unbounded type, so this unchecked cast works always
this.maxSize = maxSize;
if (prepopulate) {
// If sentinel objects are supported, populate the queue with them
T sentinel = getSentinelObject();
if (sentinel != null) {
heap[1] = sentinel;
for (int i = 2; i < heap.length; i++) {
heap[i] = getSentinelObject();
}
size = maxSize;
}
}
}
/** Determines the ordering of objects in this priority queue. Subclasses
* must define this one method.
@ -80,45 +124,6 @@ public abstract class PriorityQueue<T> {
return null;
}
/** Subclass constructors must call this. */
@SuppressWarnings("unchecked")
protected final void initialize(int maxSize) {
size = 0;
int heapSize;
if (0 == maxSize)
// We allocate 1 extra to avoid if statement in top()
heapSize = 2;
else {
if (maxSize == Integer.MAX_VALUE) {
// Don't wrap heapSize to -1, in this case, which
// causes a confusing NegativeArraySizeException.
// Note that very likely this will simply then hit
// an OOME, but at least that's more indicative to
// caller that this values is too big. We don't +1
// in this case, but it's very unlikely in practice
// one will actually insert this many objects into
// the PQ:
heapSize = Integer.MAX_VALUE;
} else {
// NOTE: we add +1 because all access to heap is
// 1-based not 0-based. heap[0] is unused.
heapSize = maxSize + 1;
}
}
heap = (T[]) new Object[heapSize]; // T is unbounded type, so this unchecked cast works always
this.maxSize = maxSize;
// If sentinel objects are supported, populate the queue with them
T sentinel = getSentinelObject();
if (sentinel != null) {
heap[1] = sentinel;
for (int i = 2; i < heap.length; i++) {
heap[i] = getSentinelObject();
}
size = maxSize;
}
}
/**
* Adds an Object to a PriorityQueue in log(size) time. If one tries to add
* more objects than maxSize from initialize an
@ -247,4 +252,11 @@ public abstract class PriorityQueue<T> {
}
heap[i] = node; // install saved node
}
/** This method returns the internal heap array as Object[].
* @lucene.internal
*/
protected final Object[] getHeapArray() {
return (Object[]) heap;
}
}

View File

@ -23,8 +23,7 @@ public class TestPriorityQueue extends LuceneTestCase {
private static class IntegerQueue extends PriorityQueue<Integer> {
public IntegerQueue(int count) {
super();
initialize(count);
super(count);
}
@Override

View File

@ -124,7 +124,7 @@ public class QualityQueriesFinder {
private static class TermsDfQueue extends PriorityQueue<TermDf> {
TermsDfQueue (int maxSize) {
initialize(maxSize);
super(maxSize);
}
@Override
protected boolean lessThan(TermDf tf1, TermDf tf2) {

View File

@ -354,13 +354,17 @@ public class ConcurrentLRUCache<K,V> {
private static class PQueue<K,V> extends PriorityQueue<CacheEntry<K,V>> {
int myMaxSize;
final Object[] heap;
PQueue(int maxSz) {
super.initialize(maxSz);
super(maxSz);
heap = getHeapArray();
myMaxSize = maxSz;
}
@SuppressWarnings("unchecked")
Iterable<CacheEntry<K,V>> getValues() {
return Collections.unmodifiableCollection(Arrays.asList(heap));
return (Iterable) Collections.unmodifiableCollection(Arrays.asList(heap));
}
@Override
@ -370,12 +374,13 @@ public class ConcurrentLRUCache<K,V> {
}
// necessary because maxSize is private in base class
@SuppressWarnings("unchecked")
public CacheEntry<K,V> myInsertWithOverflow(CacheEntry<K,V> element) {
if (size() < myMaxSize) {
add(element);
return null;
} else if (size() > 0 && !lessThan(element, heap[1])) {
CacheEntry<K,V> ret = heap[1];
} else if (size() > 0 && !lessThan(element, (CacheEntry<K,V>) heap[1])) {
CacheEntry<K,V> ret = (CacheEntry<K,V>) heap[1];
heap[1] = element;
updateTop();
return ret;

View File

@ -586,7 +586,7 @@ public class LukeRequestHandler extends RequestHandlerBase
public TermHistogram histogram;
TopTermQueue(int size) {
initialize(size);
super(size);
histogram = new TermHistogram();
}

View File

@ -82,6 +82,7 @@ class ShardFieldSortedHitQueue extends PriorityQueue {
protected List<String> fieldNames = new ArrayList<String>();
public ShardFieldSortedHitQueue(SortField[] fields, int size) {
super(size);
final int n = fields.length;
comparators = new Comparator[n];
this.fields = new SortField[n];
@ -107,8 +108,6 @@ class ShardFieldSortedHitQueue extends PriorityQueue {
//System.out.println("%%%%%%%%%%%%%%%%%% got "+fields[i].getType() +" for "+ fieldname +" fields[i].getReverse(): "+fields[i].getReverse());
}
initialize(size);
}
@Override

View File

@ -114,10 +114,7 @@ class PerSegmentSingleValuedFaceting {
// now merge the per-segment results
PriorityQueue<SegFacet> queue = new PriorityQueue<SegFacet>() {
{
initialize(leaves.length);
}
PriorityQueue<SegFacet> queue = new PriorityQueue<SegFacet>(leaves.length) {
@Override
protected boolean lessThan(SegFacet a, SegFacet b) {
return a.tempBR.compareTo(b.tempBR) < 0;

View File

@ -39,7 +39,7 @@ public abstract class Lookup {
public static final class LookupPriorityQueue extends PriorityQueue<LookupResult> {
public LookupPriorityQueue(int size) {
initialize(size);
super(size);
}
@Override