Index: lucene/core/src/java/org/apache/lucene/util/fst/Util.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/fst/Util.java (revision 1397281) +++ lucene/core/src/java/org/apache/lucene/util/fst/Util.java (working copy) @@ -271,9 +271,6 @@ final Comparator comparator; - // Set once the queue has filled: - FSTPath bottom = null; - TreeSet> queue = null; public TopNSearcher(FST fst, int topN, Comparator comparator) { @@ -291,9 +288,10 @@ assert queue != null; T cost = fst.outputs.add(path.cost, path.arc.output); - //System.out.println(" addIfCompetitive bottom=" + bottom + " queue.size()=" + queue.size()); + //System.out.println(" addIfCompetitive queue.size()=" + queue.size() + " path=" + path + " + label=" + path.arc.label); - if (bottom != null) { + if (queue.size() == topN) { + FSTPath bottom = queue.last(); int comp = comparator.compare(cost, bottom.cost); if (comp > 0) { // Doesn't compete @@ -323,24 +321,11 @@ newInput.length = path.input.length+1; final FSTPath newPath = new FSTPath(cost, path.arc, comparator, newInput); - // this is pointless right? we do it above already: - //newPath.input.grow(path.input.length+1); - //System.arraycopy(path.input.ints, 0, newPath.input.ints, 0, path.input.length); - //newPath.input.ints[path.input.length] = path.arc.label; - //newPath.input.length = path.input.length+1; + queue.add(newPath); - //System.out.println(" add path=" + newPath); - queue.add(newPath); - if (bottom != null) { - final FSTPath removed = queue.pollLast(); - assert removed == bottom; - bottom = queue.last(); - //System.out.println(" now re-set bottom: " + bottom + " queue=" + queue); - } else if (queue.size() == topN) { - // Queue just filled up: - bottom = queue.last(); - //System.out.println(" now set bottom: " + bottom); - } + if (queue.size() == topN+1) { + queue.pollLast(); + } } /** Adds all leaving arcs, including 'finished' arc, if @@ -387,7 +372,7 @@ // For each top N path: while (results.size() < topN) { - //System.out.println("\nfind next path"); + //System.out.println("\nfind next path: queue.size=" + queue.size()); FSTPath path; Index: lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggesterTest.java =================================================================== --- lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggesterTest.java (revision 1397281) +++ lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggesterTest.java (working copy) @@ -789,4 +789,18 @@ assertEquals("a ", results.get(1).key); assertEquals(50, results.get(1).value); } + + public void testQueueExhaustion() throws Exception { + Analyzer a = new MockAnalyzer(random()); + AnalyzingSuggester suggester = new AnalyzingSuggester(a, a, AnalyzingSuggester.EXACT_FIRST, 256, -1); + + suggester.build(new TermFreqArrayIterator(new TermFreq[] { + new TermFreq("a", 2), + new TermFreq("a b c", 3), + new TermFreq("a c a", 1), + new TermFreq("a c b", 1), + })); + + List results = suggester.lookup("a", false, 4); + } } Index: lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java =================================================================== --- lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java (revision 1397281) +++ lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java (working copy) @@ -533,9 +533,6 @@ if (exactFirst) { - Util.TopNSearcher> searcher; - searcher = new Util.TopNSearcher>(fst, num, weightComparator); - int count = 0; for (FSTUtil.Path> path : prefixPaths) { if (fst.findTargetArc(END_BYTE, path.fstNode, scratchArc, bytesReader) != null) { @@ -545,6 +542,9 @@ } } + // Searcher just to find the single exact only + // match, if present: + Util.TopNSearcher> searcher; searcher = new Util.TopNSearcher>(fst, count * maxSurfaceFormsPerAnalyzedForm, weightComparator); // NOTE: we could almost get away with only using