Index: lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java --- lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java Fri Jan 28 18:24:40 2011 -0500 @@ -65,7 +65,7 @@ // create dir data IndexWriter indexWriter = new IndexWriter(dir, newIndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer())); + TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); for (int i = 0; i < 20; i++) { Document document = new Document(); @@ -91,7 +91,7 @@ // create dir data IndexWriter indexWriter = new IndexWriter(dir, newIndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer())); + TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); indexWriter.setInfoStream(VERBOSE ? System.out : null); if (VERBOSE) { System.out.println("TEST: make test index"); Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java --- lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java Fri Jan 28 18:24:40 2011 -0500 @@ -32,7 +32,7 @@ public void setUp() throws Exception { super.setUp(); dir = newDirectory(); - IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer())); + IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); Document doc; for (int i = 0; i < NUM_DOCS; i++) { doc = new Document(); Index: lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java --- lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java Fri Jan 28 18:24:40 2011 -0500 @@ -59,7 +59,7 @@ super.setUp(); store = newDirectory(); IndexWriter writer = new IndexWriter(store, newIndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer())); + TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); for (int i = 0; i < NUM_DOCS; i++) { Document d = new Document(); Index: lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java --- lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java Fri Jan 28 18:24:40 2011 -0500 @@ -20,16 +20,17 @@ import java.io.IOException; import java.util.HashSet; +import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.index.DocsEnum; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.MultiFields; import org.apache.lucene.index.RandomIndexWriter; import org.apache.lucene.index.Term; -import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.index.MultiFields; import org.apache.lucene.store.Directory; +import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.util.BytesRef; public class DuplicateFilterTest extends LuceneTestCase { private static final String KEY_FIELD = "url"; @@ -42,7 +43,7 @@ public void setUp() throws Exception { super.setUp(); directory = newDirectory(); - RandomIndexWriter writer = new RandomIndexWriter(random, directory); + RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); //Add series of docs with filterable fields : url, text and dates flags addDoc(writer, "http://lucene.apache.org", "lucene 1.4.3 available", "20040101"); Index: lucene/src/java/org/apache/lucene/index/BufferedDeletes.java --- lucene/src/java/org/apache/lucene/index/BufferedDeletes.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/java/org/apache/lucene/index/BufferedDeletes.java Fri Jan 28 18:24:40 2011 -0500 @@ -19,10 +19,12 @@ import java.io.IOException; import java.io.PrintStream; -import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; import java.util.Date; import java.util.Map.Entry; -import java.util.Map; +import java.util.Comparator; +import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -32,13 +34,25 @@ import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Weight; -/** Holds a {@link SegmentDeletes} for each segment in the - * index. */ +/** Tracks {@link SegmentDeletes} for each segment in the + * index. When DocumensWriter flushes, its buffered + * deletes are pushed onto the segment(s) it flushed. + * Eventually, we "apply" these deletes (resolve them to + * the actual docIDs, per segment). Currently the only + * "automatic" place where we do this is when a merge is + * started (we apply deletes only to the to-be-merged + * segments). We also apply to all segmetns when NRT + * reader is pulled, or commit is called. */ class BufferedDeletes { - // Deletes for all flushed/merged segments: - private final Map deletesMap = new HashMap(); + // TODO: maybe linked list? + private final List deletes = new ArrayList(); + + // Starts at 1 so that SegmentInfos that have never had + // deletes applied (whose bufferedDelGen defaults to 0) + // will be correct: + private long nextGen = 1; // used only by assert private Term lastDeleteTerm; @@ -54,7 +68,7 @@ private synchronized void message(String message) { if (infoStream != null) { - infoStream.println("BD " + messageID + " [" + new Date() + "; " + Thread.currentThread().getName() + "]: BD " + message); + infoStream.println("BD " + messageID + " [" + new Date() + "; " + Thread.currentThread().getName() + "]: " + message); } } @@ -62,40 +76,29 @@ this.infoStream = infoStream; } - public synchronized void pushDeletes(SegmentDeletes newDeletes, SegmentInfo info) { - pushDeletes(newDeletes, info, false); - } - - // Moves all pending deletes onto the provided segment, - // then clears the pending deletes - public synchronized void pushDeletes(SegmentDeletes newDeletes, SegmentInfo info, boolean noLimit) { - assert newDeletes.any(); - numTerms.addAndGet(newDeletes.numTermDeletes.get()); - - if (!noLimit) { - assert !deletesMap.containsKey(info); - assert info != null; - deletesMap.put(info, newDeletes); - bytesUsed.addAndGet(newDeletes.bytesUsed.get()); - } else { - final SegmentDeletes deletes = getDeletes(info); - bytesUsed.addAndGet(-deletes.bytesUsed.get()); - deletes.update(newDeletes, noLimit); - bytesUsed.addAndGet(deletes.bytesUsed.get()); - } + // Appends a new packet of buffered deletes to the stream, + // setting its generation: + public synchronized void push(SegmentDeletes packet) { + assert packet.any(); + assert checkDeleteStats(); + packet.gen = nextGen++; + deletes.add(packet); + numTerms.addAndGet(packet.numTermDeletes.get()); + bytesUsed.addAndGet(packet.bytesUsed.get()); if (infoStream != null) { - message("push deletes seg=" + info + " dels=" + getDeletes(info)); + message("push deletes " + packet + " delGen=" + packet.gen + " packetCount=" + deletes.size()); } assert checkDeleteStats(); } - + public synchronized void clear() { - deletesMap.clear(); + deletes.clear(); + nextGen = 1; numTerms.set(0); bytesUsed.set(0); } - synchronized boolean any() { + public boolean any() { return bytesUsed.get() != 0; } @@ -107,193 +110,203 @@ return bytesUsed.get(); } - // IW calls this on finishing a merge. While the merge - // was running, it's possible new deletes were pushed onto - // our last (and only our last) segment. In this case we - // must carry forward those deletes onto the merged - // segment. - synchronized void commitMerge(MergePolicy.OneMerge merge) { - assert checkDeleteStats(); - if (infoStream != null) { - message("commitMerge merge.info=" + merge.info + " merge.segments=" + merge.segments); + public static class ApplyDeletesResult { + // True if any actual deletes took place: + public final boolean anyDeletes; + + // Current gen, for the merged segment: + public final long gen; + + ApplyDeletesResult(boolean anyDeletes, long gen) { + this.anyDeletes = anyDeletes; + this.gen = gen; } - final SegmentInfo lastInfo = merge.segments.lastElement(); - final SegmentDeletes lastDeletes = deletesMap.get(lastInfo); - if (lastDeletes != null) { - deletesMap.remove(lastInfo); - assert !deletesMap.containsKey(merge.info); - deletesMap.put(merge.info, lastDeletes); - // don't need to update numTerms/bytesUsed since we - // are just moving the deletes from one info to - // another - if (infoStream != null) { - message("commitMerge done: new deletions=" + lastDeletes); - } - } else if (infoStream != null) { - message("commitMerge done: no new deletions"); - } - assert !anyDeletes(merge.segments.range(0, merge.segments.size()-1)); - assert checkDeleteStats(); } - synchronized void clear(SegmentDeletes deletes) { - deletes.clear(); - } - - public synchronized boolean applyDeletes(IndexWriter.ReaderPool readerPool, SegmentInfos segmentInfos, SegmentInfos applyInfos) throws IOException { - if (!any()) { - return false; + // Sorts SegmentInfos from smallest to biggest bufferedDelGen: + private static final Comparator sortByDelGen = new Comparator() { + @Override + public int compare(SegmentInfo si1, SegmentInfo si2) { + final long cmp = si1.getBufferedDeletesGen() - si2.getBufferedDeletesGen(); + if (cmp > 0) { + return 1; + } else if (cmp < 0) { + return -1; + } else { + return 0; + } } + + @Override + public boolean equals(Object other) { + return sortByDelGen == other; + } + }; + + /** Resolves the buffered deleted Term/Query/docIDs, into + * actual deleted docIDs in the deletedDocs BitVector for + * each SegmentReader. This is called when a merge kicks + * off (applying only to the to-be-merged segments), when + * deletes are using too much RAM or hit their flush + * count, or when app calls IW.commit/close, or + * IW.getReader. */ + public synchronized ApplyDeletesResult applyDeletes(IndexWriter.ReaderPool readerPool, SegmentInfos infos) throws IOException { final long t0 = System.currentTimeMillis(); - if (infoStream != null) { - message("applyDeletes: applyInfos=" + applyInfos + "; index=" + segmentInfos); + if (infos.size() == 0) { + return new ApplyDeletesResult(false, nextGen++); } assert checkDeleteStats(); - assert applyInfos.size() > 0; + if (!any()) { + message("applyDeletes: no deletes; skipping"); + return new ApplyDeletesResult(false, nextGen++); + } - boolean any = false; - - final SegmentInfo lastApplyInfo = applyInfos.lastElement(); - final int lastIdx = segmentInfos.indexOf(lastApplyInfo); - - final SegmentInfo firstInfo = applyInfos.firstElement(); - final int firstIdx = segmentInfos.indexOf(firstInfo); + if (infoStream != null) { + message("applyDeletes: infos=" + infos + " packetCount=" + deletes.size()); + } - // applyInfos must be a slice of segmentInfos - assert lastIdx - firstIdx + 1 == applyInfos.size(); - - // iterate over all segment infos backwards - // coalesceing deletes along the way - // when we're at or below the last of the - // segments to apply to, start applying the deletes - // we traverse up to the first apply infos + SegmentInfos infos2 = new SegmentInfos(); + infos2.addAll(infos); + Collections.sort(infos2, sortByDelGen); + SegmentDeletes coalescedDeletes = null; - boolean hasDeletes = false; - for (int segIdx=segmentInfos.size()-1; segIdx >= firstIdx; segIdx--) { - final SegmentInfo info = segmentInfos.info(segIdx); - final SegmentDeletes deletes = deletesMap.get(info); - assert deletes == null || deletes.any(); + boolean anyNewDeletes = false; - if (deletes == null && coalescedDeletes == null) { - continue; - } + int infosIDX = infos2.size()-1; + int delIDX = deletes.size()-1; - if (infoStream != null) { - message("applyDeletes: seg=" + info + " segment's deletes=[" + (deletes == null ? "null" : deletes) + "]; coalesced deletes=[" + (coalescedDeletes == null ? "null" : coalescedDeletes) + "]"); - } + while (infosIDX >= 0) { + //System.out.println("BD: cycle delIDX=" + delIDX + " infoIDX=" + infosIDX); - hasDeletes |= deletes != null; + final SegmentDeletes packet = delIDX >= 0 ? deletes.get(delIDX) : null; + final SegmentInfo info = infos2.get(infosIDX); + final long segGen = info.getBufferedDeletesGen(); - if (segIdx <= lastIdx && hasDeletes) { - - final long delCountInc = applyDeletes(readerPool, info, coalescedDeletes, deletes); - - if (delCountInc != 0) { - any = true; - } - if (infoStream != null) { - message("deletes touched " + delCountInc + " docIDs"); - } - - if (deletes != null) { - // we've applied doc ids, and they're only applied - // on the current segment - bytesUsed.addAndGet(-deletes.docIDs.size() * SegmentDeletes.BYTES_PER_DEL_DOCID); - deletes.clearDocIDs(); - } - } - - // now coalesce at the max limit - if (deletes != null) { + if (packet != null && segGen < packet.gen) { + //System.out.println(" coalesce"); if (coalescedDeletes == null) { coalescedDeletes = new SegmentDeletes(); } - // TODO: we could make this single pass (coalesce as - // we apply the deletes - coalescedDeletes.update(deletes, true); + coalescedDeletes.update(packet); + delIDX--; + } else if (packet != null && segGen == packet.gen) { + //System.out.println(" eq"); + + // Lock order: IW -> BD -> RP + assert readerPool.infoIsLive(info); + SegmentReader reader = readerPool.get(info, false); + int delCount = 0; + try { + if (coalescedDeletes != null) { + delCount += applyDeletes(coalescedDeletes, reader); + } + delCount += applyDeletes(packet, reader); + } finally { + readerPool.release(reader); + } + anyNewDeletes |= delCount > 0; + + // We've applied doc ids, and they're only applied + // on the current segment + bytesUsed.addAndGet(-packet.docIDs.size() * SegmentDeletes.BYTES_PER_DEL_DOCID); + packet.clearDocIDs(); + + if (infoStream != null) { + message("seg=" + info + " segGen=" + segGen + " segDeletes=[" + packet + "]; coalesced deletes=[" + (coalescedDeletes == null ? "null" : coalescedDeletes) + "] delCount=" + delCount); + } + + if (coalescedDeletes == null) { + coalescedDeletes = new SegmentDeletes(); + } + coalescedDeletes.update(packet); + delIDX--; + infosIDX--; + info.setBufferedDeletesGen(nextGen); + + } else { + //System.out.println(" gt"); + + if (coalescedDeletes != null) { + // Lock order: IW -> BD -> RP + assert readerPool.infoIsLive(info); + SegmentReader reader = readerPool.get(info, false); + int delCount = 0; + try { + delCount += applyDeletes(coalescedDeletes, reader); + } finally { + readerPool.release(reader); + } + anyNewDeletes |= delCount > 0; + + if (infoStream != null) { + message("seg=" + info + " segGen=" + segGen + " coalesced deletes=[" + (coalescedDeletes == null ? "null" : coalescedDeletes) + "] delCount=" + delCount); + } + } + info.setBufferedDeletesGen(nextGen); + + infosIDX--; } } - // move all deletes to segment just before our merge. - if (firstIdx > 0) { - - SegmentDeletes mergedDeletes = null; - // TODO: we could also make this single pass - for (SegmentInfo info : applyInfos) { - final SegmentDeletes deletes = deletesMap.get(info); - if (deletes != null) { - assert deletes.any(); - if (mergedDeletes == null) { - mergedDeletes = getDeletes(segmentInfos.info(firstIdx-1)); - numTerms.addAndGet(-mergedDeletes.numTermDeletes.get()); - assert numTerms.get() >= 0; - bytesUsed.addAndGet(-mergedDeletes.bytesUsed.get()); - assert bytesUsed.get() >= 0; - } - - mergedDeletes.update(deletes, true); - } - } - - if (mergedDeletes != null) { - numTerms.addAndGet(mergedDeletes.numTermDeletes.get()); - bytesUsed.addAndGet(mergedDeletes.bytesUsed.get()); - } - - if (infoStream != null) { - if (mergedDeletes != null) { - message("applyDeletes: merge all deletes into seg=" + segmentInfos.info(firstIdx-1) + ": " + mergedDeletes); - } else { - message("applyDeletes: no deletes to merge"); - } - } - } else { - // We drop the deletes in this case, because we've - // applied them to segment infos starting w/ the first - // segment. There are no prior segments so there's no - // reason to keep them around. When the applyInfos == - // segmentInfos this means all deletes have been - // removed: - } - remove(applyInfos); - assert checkDeleteStats(); - assert applyInfos != segmentInfos || !any(); - if (infoStream != null) { message("applyDeletes took " + (System.currentTimeMillis()-t0) + " msec"); } - return any; + // assert infos != segmentInfos || !any() : "infos=" + infos + " segmentInfos=" + segmentInfos + " any=" + any; + + return new ApplyDeletesResult(anyNewDeletes, nextGen++); } - - private synchronized long applyDeletes(IndexWriter.ReaderPool readerPool, - SegmentInfo info, - SegmentDeletes coalescedDeletes, - SegmentDeletes segmentDeletes) throws IOException { - assert readerPool.infoIsLive(info); - - assert coalescedDeletes == null || coalescedDeletes.docIDs.size() == 0; - - long delCount = 0; - // Lock order: IW -> BD -> RP - SegmentReader reader = readerPool.get(info, false); - try { - if (coalescedDeletes != null) { - delCount += applyDeletes(coalescedDeletes, reader); + public synchronized long getNextGen() { + return nextGen++; + } + + // Lock order IW -> BD + public synchronized void prune(SegmentInfos segmentInfos) { + assert checkDeleteStats(); + long minGen = Long.MAX_VALUE; + for(SegmentInfo info : segmentInfos) { + minGen = Math.min(info.getBufferedDeletesGen(), minGen); + } + + if (infoStream != null) { + message("prune sis=" + segmentInfos + " minGen=" + minGen + " packetCount=" + deletes.size()); + } + + final int limit = deletes.size(); + for(int delIDX=0;delIDX= minGen) { + prune(delIDX); + assert checkDeleteStats(); + return; } - if (segmentDeletes != null) { - delCount += applyDeletes(segmentDeletes, reader); + } + + // All deletes pruned + prune(limit); + assert !any(); + assert checkDeleteStats(); + } + + private synchronized void prune(int count) { + if (count > 0) { + if (infoStream != null) { + message("pruneDeletes: prune " + count + " packets; " + (deletes.size() - count) + " packets remain"); } - } finally { - readerPool.release(reader); + for(int delIDX=0;delIDX= 0; + bytesUsed.addAndGet(-packet.bytesUsed.get()); + assert bytesUsed.get() >= 0; + } + deletes.subList(0, count).clear(); } - return delCount; } - + private synchronized long applyDeletes(SegmentDeletes deletes, SegmentReader reader) throws IOException { long delCount = 0; @@ -399,39 +412,6 @@ return delCount; } - public synchronized SegmentDeletes getDeletes(SegmentInfo info) { - SegmentDeletes deletes = deletesMap.get(info); - if (deletes == null) { - deletes = new SegmentDeletes(); - deletesMap.put(info, deletes); - } - return deletes; - } - - public synchronized void remove(SegmentInfos infos) { - assert infos.size() > 0; - for (SegmentInfo info : infos) { - SegmentDeletes deletes = deletesMap.get(info); - if (deletes != null) { - bytesUsed.addAndGet(-deletes.bytesUsed.get()); - assert bytesUsed.get() >= 0: "bytesUsed=" + bytesUsed; - numTerms.addAndGet(-deletes.numTermDeletes.get()); - assert numTerms.get() >= 0: "numTerms=" + numTerms; - deletesMap.remove(info); - } - } - } - - // used only by assert - private boolean anyDeletes(SegmentInfos infos) { - for(SegmentInfo info : infos) { - if (deletesMap.containsKey(info)) { - return true; - } - } - return false; - } - // used only by assert private boolean checkDeleteTerm(Term term) { if (term != null) { @@ -445,9 +425,9 @@ private boolean checkDeleteStats() { int numTerms2 = 0; long bytesUsed2 = 0; - for(SegmentDeletes deletes : deletesMap.values()) { - numTerms2 += deletes.numTermDeletes.get(); - bytesUsed2 += deletes.bytesUsed.get(); + for(SegmentDeletes packet : deletes) { + numTerms2 += packet.numTermDeletes.get(); + bytesUsed2 += packet.bytesUsed.get(); } assert numTerms2 == numTerms.get(): "numTerms2=" + numTerms2 + " vs " + numTerms.get(); assert bytesUsed2 == bytesUsed.get(): "bytesUsed2=" + bytesUsed2 + " vs " + bytesUsed; Index: lucene/src/java/org/apache/lucene/index/DocumentsWriter.java --- lucene/src/java/org/apache/lucene/index/DocumentsWriter.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/java/org/apache/lucene/index/DocumentsWriter.java Fri Jan 28 18:24:40 2011 -0500 @@ -508,16 +508,17 @@ private void pushDeletes(SegmentInfo newSegment, SegmentInfos segmentInfos) { // Lock order: DW -> BD if (pendingDeletes.any()) { - if (newSegment != null) { + if (segmentInfos.size() > 0 || newSegment != null) { if (infoStream != null) { - message("flush: push buffered deletes to newSegment"); + message("flush: push buffered deletes"); } - bufferedDeletes.pushDeletes(pendingDeletes, newSegment); - } else if (segmentInfos.size() > 0) { + bufferedDeletes.push(pendingDeletes); if (infoStream != null) { - message("flush: push buffered deletes to previously flushed segment " + segmentInfos.lastElement()); + message("flush: delGen=" + pendingDeletes.gen); } - bufferedDeletes.pushDeletes(pendingDeletes, segmentInfos.lastElement(), true); + if (newSegment != null) { + newSegment.setBufferedDeletesGen(pendingDeletes.gen); + } } else { if (infoStream != null) { message("flush: drop buffered deletes: no segments"); @@ -527,6 +528,8 @@ // affect anything. } pendingDeletes = new SegmentDeletes(); + } else if (newSegment != null) { + newSegment.setBufferedDeletesGen(bufferedDeletes.getNextGen()); } } @@ -639,7 +642,6 @@ // Lock order: IW -> DW -> BD pushDeletes(newSegment, segmentInfos); - if (infoStream != null) { message("flush time " + (System.currentTimeMillis()-startTime) + " msec"); } Index: lucene/src/java/org/apache/lucene/index/IndexWriter.java --- lucene/src/java/org/apache/lucene/index/IndexWriter.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/java/org/apache/lucene/index/IndexWriter.java Fri Jan 28 18:24:40 2011 -0500 @@ -2526,9 +2526,12 @@ message("apply all deletes during flush"); } flushDeletesCount.incrementAndGet(); - if (bufferedDeletes.applyDeletes(readerPool, segmentInfos, segmentInfos)) { + final BufferedDeletes.ApplyDeletesResult result = bufferedDeletes.applyDeletes(readerPool, segmentInfos); + if (result.anyDeletes) { checkpoint(); } + bufferedDeletes.prune(segmentInfos); + assert !bufferedDeletes.any(); flushControl.clearDeletes(); } else if (infoStream != null) { message("don't apply deletes now delTermCount=" + bufferedDeletes.numTerms() + " bytesUsed=" + bufferedDeletes.bytesUsed()); @@ -2567,28 +2570,12 @@ return docWriter.getNumDocs(); } - private int ensureContiguousMerge(MergePolicy.OneMerge merge) { - - int first = segmentInfos.indexOf(merge.segments.info(0)); - if (first == -1) - throw new MergePolicy.MergeException("could not find segment " + merge.segments.info(0).name + " in current index " + segString(), directory); - - final int numSegments = segmentInfos.size(); - - final int numSegmentsToMerge = merge.segments.size(); - for(int i=0;i= numSegments || !segmentInfos.info(first+i).equals(info)) { - if (segmentInfos.indexOf(info) == -1) - throw new MergePolicy.MergeException("MergePolicy selected a segment (" + info.name + ") that is not in the current index " + segString(), directory); - else - throw new MergePolicy.MergeException("MergePolicy selected non-contiguous segments to merge (" + merge.segString(directory) + " vs " + segString() + "), which IndexWriter (currently) cannot handle", - directory); + private void ensureValidMerge(MergePolicy.OneMerge merge) { + for(SegmentInfo info : merge.segments) { + if (segmentInfos.indexOf(info) == -1) { + throw new MergePolicy.MergeException("MergePolicy selected a segment (" + info.name + ") that is not in the current index " + segString(), directory); } } - - return first; } /** Carefully merges deletes for the segments we just @@ -2613,9 +2600,11 @@ // started merging: int docUpto = 0; int delCount = 0; + long minGen = Long.MAX_VALUE; for(int i=0; i < sourceSegments.size(); i++) { SegmentInfo info = sourceSegments.info(i); + minGen = Math.min(info.getBufferedDeletesGen(), minGen); int docCount = info.docCount; SegmentReader previousReader = merge.readersClone[i]; final Bits prevDelDocs = previousReader.getDeletedDocs(); @@ -2666,9 +2655,17 @@ assert mergedReader.numDeletedDocs() == delCount; mergedReader.hasChanges = delCount > 0; + + // If new deletes were applied while we were merging + // (which happens if eg commit() or getReader() is + // called during our merge), then it better be the case + // that the delGen has increased for all our merged + // segments: + assert !mergedReader.hasChanges || minGen > mergedReader.getSegmentInfo().getBufferedDeletesGen(); + + mergedReader.getSegmentInfo().setBufferedDeletesGen(minGen); } - /* FIXME if we want to support non-contiguous segment merges */ synchronized private boolean commitMerge(MergePolicy.OneMerge merge, SegmentReader mergedReader) throws IOException { assert testPoint("startCommitMerge"); @@ -2694,7 +2691,7 @@ return false; } - final int start = ensureContiguousMerge(merge); + ensureValidMerge(merge); commitMergedDeletes(merge, mergedReader); @@ -2704,10 +2701,32 @@ // format as well: setMergeDocStoreIsCompoundFile(merge); - segmentInfos.subList(start, start + merge.segments.size()).clear(); assert !segmentInfos.contains(merge.info); - segmentInfos.add(start, merge.info); - + + final Set mergedAway = new HashSet(merge.segments); + int segIdx = 0; + int newSegIdx = 0; + boolean inserted = false; + final int curSegCount = segmentInfos.size(); + while(segIdx < curSegCount) { + final SegmentInfo info = segmentInfos.info(segIdx++); + if (mergedAway.contains(info)) { + if (!inserted) { + segmentInfos.set(segIdx-1, merge.info); + inserted = true; + newSegIdx++; + } + } else { + segmentInfos.set(newSegIdx++, info); + } + } + assert newSegIdx == curSegCount - merge.segments.size() + 1; + segmentInfos.subList(newSegIdx, segmentInfos.size()).clear(); + + if (infoStream != null) { + message("after commit: " + segString()); + } + closeMergeReaders(merge, false); // Must note the change to segmentInfos so any commits @@ -2719,16 +2738,12 @@ // disk, updating SegmentInfo, etc.: readerPool.clear(merge.segments); - // remove pending deletes of the segments - // that were merged, moving them onto the segment just - // before the merged segment - // Lock order: IW -> BD - bufferedDeletes.commitMerge(merge); - if (merge.optimize) { // cascade the optimize: segmentsToOptimize.add(merge.info); } + + return true; } @@ -2856,7 +2871,7 @@ } } - ensureContiguousMerge(merge); + ensureValidMerge(merge); pendingMerges.add(merge); @@ -2883,10 +2898,6 @@ final synchronized void mergeInit(MergePolicy.OneMerge merge) throws IOException { boolean success = false; try { - // Lock order: IW -> BD - if (bufferedDeletes.applyDeletes(readerPool, segmentInfos, merge.segments)) { - checkpoint(); - } _mergeInit(merge); success = true; } finally { @@ -2910,6 +2921,9 @@ throw new IllegalStateException("this writer hit an OutOfMemoryError; cannot merge"); } + // TODO: is there any perf benefit to sorting + // merged segments? eg biggest to smallest? + if (merge.info != null) // mergeInit already done return; @@ -2922,6 +2936,17 @@ // names. merge.info = new SegmentInfo(newSegmentName(), 0, directory, false, false, null, false); + // Lock order: IW -> BD + final BufferedDeletes.ApplyDeletesResult result = bufferedDeletes.applyDeletes(readerPool, merge.segments); + if (result.anyDeletes) { + checkpoint(); + } + + merge.info.setBufferedDeletesGen(result.gen); + + // Lock order: IW -> BD + bufferedDeletes.prune(segmentInfos); + Map details = new HashMap(); details.put("optimize", Boolean.toString(merge.optimize)); details.put("mergeFactor", Integer.toString(merge.segments.size())); Index: lucene/src/java/org/apache/lucene/index/LogMergePolicy.java --- lucene/src/java/org/apache/lucene/index/LogMergePolicy.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/java/org/apache/lucene/index/LogMergePolicy.java Fri Jan 28 18:24:40 2011 -0500 @@ -19,6 +19,8 @@ import java.io.IOException; import java.util.Set; +import java.util.Arrays; +import java.util.Comparator; /**

This class implements a {@link MergePolicy} that tries * to merge segments into levels of exponentially @@ -67,6 +69,7 @@ // out there wrote his own LMP ... protected long maxMergeSizeForOptimize = Long.MAX_VALUE; protected int maxMergeDocs = DEFAULT_MAX_MERGE_DOCS; + protected boolean requireContiguousMerge = false; protected double noCFSRatio = DEFAULT_NO_CFS_RATIO; @@ -105,6 +108,21 @@ writer.get().message("LMP: " + message); } + /** If true, merges must be in-order slice of the + * segments. If false, then the merge policy is free to + * pick any segments. The default is false, which is + * in general more efficient than true since it gives the + * merge policy more freedom to pick closely sized + * segments. */ + public void setRequireContiguousMerge(boolean v) { + requireContiguousMerge = v; + } + + /** See {@link #setRequireContiguousMerge}. */ + public boolean getRequireContiguousMerge() { + return requireContiguousMerge; + } + /**

Returns the number of segments that are merged at * once and also controls the total number of segments * allowed to accumulate in the index.

*/ @@ -356,6 +374,8 @@ } return null; } + + // TODO: handle non-contiguous merge case differently? // Find the newest (rightmost) segment that needs to // be optimized (other segments may have been flushed @@ -454,6 +474,37 @@ return spec; } + private static class SegmentInfoAndLevel implements Comparable { + SegmentInfo info; + float level; + int index; + + public SegmentInfoAndLevel(SegmentInfo info, float level, int index) { + this.info = info; + this.level = level; + this.index = index; + } + + // Sorts largest to smallest + public int compareTo(Object o) { + SegmentInfoAndLevel other = (SegmentInfoAndLevel) o; + if (level < other.level) + return 1; + else if (level > other.level) + return -1; + else + return 0; + } + } + + private static class SortByIndex implements Comparator { + public int compare(SegmentInfoAndLevel o1, SegmentInfoAndLevel o2) { + return o1.index - o2.index; + } + } + + private static final SortByIndex sortByIndex = new SortByIndex(); + /** Checks if any merges are now necessary and returns a * {@link MergePolicy.MergeSpecification} if so. A merge * is necessary when there are more than {@link @@ -470,7 +521,7 @@ // Compute levels, which is just log (base mergeFactor) // of the size of each segment - float[] levels = new float[numSegments]; + SegmentInfoAndLevel[] levels = new SegmentInfoAndLevel[numSegments]; final float norm = (float) Math.log(mergeFactor); for(int i=0;i ent : in.terms.entrySet()) { final Term term = ent.getKey(); @@ -111,13 +115,7 @@ // only incr bytesUsed if this term wasn't already buffered: bytesUsed.addAndGet(BYTES_PER_DEL_TERM); } - final Integer limit; - if (noLimit) { - limit = MAX_INT; - } else { - limit = ent.getValue(); - } - terms.put(term, limit); + terms.put(term, MAX_INT); } for (Map.Entry ent : in.queries.entrySet()) { @@ -126,13 +124,7 @@ // only incr bytesUsed if this query wasn't already buffered: bytesUsed.addAndGet(BYTES_PER_DEL_QUERY); } - final Integer limit; - if (noLimit) { - limit = MAX_INT; - } else { - limit = ent.getValue(); - } - queries.put(query, limit); + queries.put(query, MAX_INT); } // docIDs never move across segments and the docIDs Index: lucene/src/java/org/apache/lucene/index/SegmentInfo.java --- lucene/src/java/org/apache/lucene/index/SegmentInfo.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/java/org/apache/lucene/index/SegmentInfo.java Fri Jan 28 18:24:40 2011 -0500 @@ -94,6 +94,10 @@ // specific versions afterwards ("3.0", "3.1" etc.). // see Constants.LUCENE_MAIN_VERSION. private String version; + + // NOTE: only used in-RAM by IW to track buffered deletes; + // this is never written to/read from the Directory + private long bufferedDeletesGen; public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasProx, SegmentCodecs segmentCodecs, boolean hasVectors) { @@ -244,7 +248,8 @@ if (sizeInBytesWithStore != -1) return sizeInBytesWithStore; sizeInBytesWithStore = 0; for (final String fileName : files()) { - // We don't count bytes used by a shared doc store against this segment + // We don't count bytes used by a shared doc store + // against this segment if (docStoreOffset == -1 || !IndexFileNames.isDocStoreFile(fileName)) { sizeInBytesWithStore += dir.fileLength(fileName); } @@ -672,5 +677,12 @@ public String getVersion() { return version; } - + + long getBufferedDeletesGen() { + return bufferedDeletesGen; + } + + void setBufferedDeletesGen(long v) { + bufferedDeletesGen = v; + } } Index: lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java --- lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java Fri Jan 28 18:24:40 2011 -0500 @@ -91,8 +91,8 @@ IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMergeScheduler(new MyMergeScheduler()) - .setMaxBufferedDocs(2).setRAMBufferSizeMB( - IndexWriterConfig.DISABLE_AUTO_FLUSH)); + .setMaxBufferedDocs(2).setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH) + .setMergePolicy(newLogMergePolicy())); LogMergePolicy logMP = (LogMergePolicy) writer.getConfig().getMergePolicy(); logMP.setMergeFactor(10); for(int i=0;i<20;i++) Index: lucene/src/test/org/apache/lucene/TestSearch.java --- lucene/src/test/org/apache/lucene/TestSearch.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/TestSearch.java Fri Jan 28 18:24:40 2011 -0500 @@ -74,8 +74,11 @@ Directory directory = newDirectory(); Analyzer analyzer = new MockAnalyzer(); IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } + IndexWriter writer = new IndexWriter(directory, conf); String[] docs = { @@ -90,6 +93,7 @@ for (int j = 0; j < docs.length; j++) { Document d = new Document(); d.add(newField("contents", docs[j], Field.Store.YES, Field.Index.ANALYZED)); + d.add(newField("id", ""+j, Field.Index.NOT_ANALYZED_NO_NORMS)); writer.addDocument(d); } writer.close(); @@ -106,6 +110,10 @@ }; ScoreDoc[] hits = null; + Sort sort = new Sort(new SortField[] { + SortField.FIELD_SCORE, + new SortField("id", SortField.INT)}); + QueryParser parser = new QueryParser(TEST_VERSION_CURRENT, "contents", analyzer); parser.setPhraseSlop(4); for (int j = 0; j < queries.length; j++) { @@ -115,7 +123,7 @@ System.out.println("TEST: query=" + query); } - hits = searcher.search(query, null, 1000).scoreDocs; + hits = searcher.search(query, null, 1000, sort).scoreDocs; out.println(hits.length + " total results"); for (int i = 0 ; i < hits.length && i < 10; i++) { Index: lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java --- lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java Fri Jan 28 18:24:40 2011 -0500 @@ -80,8 +80,10 @@ Directory directory = newDirectory(); Analyzer analyzer = new MockAnalyzer(); IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFiles); + final MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFiles); + } IndexWriter writer = new IndexWriter(directory, conf); if (VERBOSE) { System.out.println("TEST: now build index"); @@ -93,9 +95,6 @@ for (int j = 0; j < MAX_DOCS; j++) { Document d = new Document(); d.add(newField(PRIORITY_FIELD, HIGH_PRIORITY, Field.Store.YES, Field.Index.ANALYZED)); - - // NOTE: this ID_FIELD produces no tokens since - // MockAnalyzer discards numbers d.add(newField(ID_FIELD, Integer.toString(j), Field.Store.YES, Field.Index.ANALYZED)); writer.addDocument(d); } @@ -112,7 +111,11 @@ System.out.println("TEST: search query=" + query); } - ScoreDoc[] hits = searcher.search(query, null, MAX_DOCS).scoreDocs; + final Sort sort = new Sort(new SortField[] { + SortField.FIELD_SCORE, + new SortField(ID_FIELD, SortField.INT)}); + + ScoreDoc[] hits = searcher.search(query, null, MAX_DOCS, sort).scoreDocs; printHits(out, hits, searcher); checkHits(hits, MAX_DOCS, searcher); @@ -127,7 +130,7 @@ query = parser.parse(HIGH_PRIORITY + " OR " + MED_PRIORITY); out.println("Query: " + query.toString(PRIORITY_FIELD)); - hits = searcher.search(query, null, MAX_DOCS).scoreDocs; + hits = searcher.search(query, null, MAX_DOCS, sort).scoreDocs; printHits(out, hits, searcher); checkHits(hits, MAX_DOCS, searcher); @@ -149,7 +152,7 @@ private void checkHits(ScoreDoc[] hits, int expectedCount, IndexSearcher searcher) throws IOException { assertEquals("total results", expectedCount, hits.length); for (int i = 0 ; i < hits.length; i++) { - if ( i < 10 || (i > 94 && i < 105) ) { + if (i < 10 || (i > 94 && i < 105) ) { Document d = searcher.doc(hits[i].doc); assertEquals("check " + i, String.valueOf(i), d.get(ID_FIELD)); } Index: lucene/src/test/org/apache/lucene/index/MockRandomMergePolicy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ lucene/src/test/org/apache/lucene/index/MockRandomMergePolicy.java Fri Jan 28 18:24:40 2011 -0500 @@ -0,0 +1,93 @@ +package org.apache.lucene.index; + +/** + * 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 java.io.IOException; +import java.util.Collections; +import java.util.Random; +import java.util.Set; + +import org.apache.lucene.util._TestUtil; + +public class MockRandomMergePolicy extends MergePolicy { + private final Random random; + + public MockRandomMergePolicy(Random random) { + // fork a private random, since we are called + // unpredictably from threads: + this.random = new Random(random.nextLong()); + } + + @Override + public MergeSpecification findMerges(SegmentInfos segmentInfos) { + MergeSpecification mergeSpec = null; + //System.out.println("MRMP: findMerges sis=" + segmentInfos); + + if (segmentInfos.size() > 1 && random.nextInt(5) == 3) { + + SegmentInfos segmentInfos2 = new SegmentInfos(); + segmentInfos2.addAll(segmentInfos); + Collections.shuffle(segmentInfos2, random); + + // TODO: sometimes make more than 1 merge? + mergeSpec = new MergeSpecification(); + final int segsToMerge = _TestUtil.nextInt(random, 1, segmentInfos.size()); + mergeSpec.add(new OneMerge(segmentInfos2.range(0, segsToMerge))); + } + + return mergeSpec; + } + + @Override + public MergeSpecification findMergesForOptimize( + SegmentInfos segmentInfos, int maxSegmentCount, Set segmentsToOptimize) + throws CorruptIndexException, IOException { + + //System.out.println("MRMP: findMergesForOptimize sis=" + segmentInfos); + MergeSpecification mergeSpec = null; + if (segmentInfos.size() > 1 || (segmentInfos.size() == 1 && segmentInfos.info(0).hasDeletions())) { + mergeSpec = new MergeSpecification(); + SegmentInfos segmentInfos2 = new SegmentInfos(); + segmentInfos2.addAll(segmentInfos); + Collections.shuffle(segmentInfos2, random); + int upto = 0; + while(upto < segmentInfos.size()) { + int inc = _TestUtil.nextInt(random, 1, segmentInfos.size()-upto); + mergeSpec.add(new OneMerge(segmentInfos2.range(upto, upto+inc))); + upto += inc; + } + } + return mergeSpec; + } + + @Override + public MergeSpecification findMergesToExpungeDeletes( + SegmentInfos segmentInfos) + throws CorruptIndexException, IOException { + return findMerges(segmentInfos); + } + + @Override + public void close() { + } + + @Override + public boolean useCompoundFile(SegmentInfos infos, SegmentInfo mergedInfo) throws IOException { + return random.nextBoolean(); + } +} Index: lucene/src/test/org/apache/lucene/index/TestAddIndexes.java --- lucene/src/test/org/apache/lucene/index/TestAddIndexes.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestAddIndexes.java Fri Jan 28 18:24:40 2011 -0500 @@ -452,6 +452,7 @@ setMaxBufferedDocs(100). setMergePolicy(newLogMergePolicy(10)) ); + writer.setInfoStream(VERBOSE ? System.out : null); writer.addIndexes(aux); assertEquals(30, writer.maxDoc()); assertEquals(3, writer.getSegmentCount()); Index: lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java --- lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java Fri Jan 28 18:24:40 2011 -0500 @@ -131,6 +131,7 @@ .setMaxBufferedDocs(7); ((LogMergePolicy) conf.getMergePolicy()).setMergeFactor(3); IndexWriter writer = new MockIndexWriter(directory, conf); + writer.setInfoStream(VERBOSE ? System.out : null); // Establish a base index of 100 docs: for(int i=0;i<100;i++) { Index: lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java --- lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java Fri Jan 28 18:24:40 2011 -0500 @@ -132,11 +132,15 @@ IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()) .setMergePolicy(mp)); + writer.setInfoStream(VERBOSE ? System.out : null); Document doc = new Document(); Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED); doc.add(idField); for(int i=0;i<10;i++) { + if (VERBOSE) { + System.out.println("\nTEST: cycle"); + } for(int j=0;j<100;j++) { idField.setValue(Integer.toString(i*100+j)); writer.addDocument(doc); @@ -144,6 +148,9 @@ int delID = i; while(delID < 100*(1+i)) { + if (VERBOSE) { + System.out.println("TEST: del " + delID); + } writer.deleteDocuments(new Term("id", ""+delID)); delID += 10; } Index: lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java --- lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java Fri Jan 28 18:24:40 2011 -0500 @@ -119,6 +119,9 @@ } public void onInit(List commits) throws IOException { + if (VERBOSE) { + System.out.println("TEST: onInit"); + } verifyCommitOrder(commits); numOnInit++; // do no deletions on init @@ -126,6 +129,9 @@ } public void onCommit(List commits) throws IOException { + if (VERBOSE) { + System.out.println("TEST: onCommit"); + } verifyCommitOrder(commits); doDeletes(commits, true); } @@ -200,8 +206,10 @@ IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()) .setIndexDeletionPolicy(policy); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(true); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(true); + } IndexWriter writer = new IndexWriter(dir, conf); writer.close(); @@ -215,8 +223,10 @@ conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode( OpenMode.APPEND).setIndexDeletionPolicy(policy); - lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(true); + mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(true); + } writer = new IndexWriter(dir, conf); for(int j=0;j<17;j++) { addDoc(writer); @@ -280,6 +290,10 @@ public void testKeepAllDeletionPolicy() throws IOException { for(int pass=0;pass<2;pass++) { + if (VERBOSE) { + System.out.println("TEST: cycle pass=" + pass); + } + boolean useCompoundFile = (pass % 2) != 0; // Never deletes a commit @@ -292,34 +306,48 @@ TEST_VERSION_CURRENT, new MockAnalyzer()) .setIndexDeletionPolicy(policy).setMaxBufferedDocs(10) .setMergeScheduler(new SerialMergeScheduler()); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); - lmp.setMergeFactor(10); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } IndexWriter writer = new IndexWriter(dir, conf); for(int i=0;i<107;i++) { addDoc(writer); } writer.close(); - conf = newIndexWriterConfig(TEST_VERSION_CURRENT, - new MockAnalyzer()).setOpenMode( - OpenMode.APPEND).setIndexDeletionPolicy(policy); - lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); - writer = new IndexWriter(dir, conf); - writer.optimize(); - writer.close(); - - assertEquals(1, policy.numOnInit); + final boolean isOptimized; + { + IndexReader r = IndexReader.open(dir); + isOptimized = r.isOptimized(); + r.close(); + } + if (!isOptimized) { + conf = newIndexWriterConfig(TEST_VERSION_CURRENT, + new MockAnalyzer()).setOpenMode( + OpenMode.APPEND).setIndexDeletionPolicy(policy); + mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } + if (VERBOSE) { + System.out.println("TEST: open writer for optimize"); + } + writer = new IndexWriter(dir, conf); + writer.setInfoStream(VERBOSE ? System.out : null); + writer.optimize(); + writer.close(); + } + assertEquals(isOptimized ? 0:1, policy.numOnInit); // If we are not auto committing then there should // be exactly 2 commits (one per close above): - assertEquals(2, policy.numOnCommit); + assertEquals(1 + (isOptimized ? 0:1), policy.numOnCommit); // Test listCommits Collection commits = IndexReader.listCommits(dir); // 2 from closing writer - assertEquals(2, commits.size()); + assertEquals(1 + (isOptimized ? 0:1), commits.size()); // Make sure we can open a reader on each commit: for (final IndexCommit commit : commits) { @@ -480,8 +508,10 @@ TEST_VERSION_CURRENT, new MockAnalyzer()) .setOpenMode(OpenMode.CREATE).setIndexDeletionPolicy(policy) .setMaxBufferedDocs(10); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } IndexWriter writer = new IndexWriter(dir, conf); for(int i=0;i<107;i++) { addDoc(writer); @@ -490,8 +520,10 @@ conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()) .setOpenMode(OpenMode.APPEND).setIndexDeletionPolicy(policy); - lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); + mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(true); + } writer = new IndexWriter(dir, conf); writer.optimize(); writer.close(); @@ -529,8 +561,10 @@ TEST_VERSION_CURRENT, new MockAnalyzer()) .setOpenMode(OpenMode.CREATE).setIndexDeletionPolicy(policy) .setMaxBufferedDocs(10); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } IndexWriter writer = new IndexWriter(dir, conf); for(int i=0;i<17;i++) { addDoc(writer); @@ -586,24 +620,34 @@ IndexWriterConfig conf = newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()) .setOpenMode(OpenMode.CREATE).setIndexDeletionPolicy(policy); - LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy(); - lmp.setUseCompoundFile(useCompoundFile); + MergePolicy mp = conf.getMergePolicy(); + if (mp instanceof LogMergePolicy) { + ((LogMergePolicy) mp).setUseCompoundFile(useCompoundFile); + } IndexWriter writer = new IndexWriter(dir, conf); writer.close(); Term searchTerm = new Term("content", "aaa"); Query query = new TermQuery(searchTerm); for(int i=0;i 5 + extraFileCount); - + assertTrue("flush should have occurred and files should have been created", dir.listAll().length > 5 + extraFileCount); + // After rollback, IW should remove all files writer.rollback(); assertEquals("no files should exist in the directory after rollback", 0, dir.listAll().length); @@ -2846,7 +2844,7 @@ public void testNoUnwantedTVFiles() throws Exception { Directory dir = newDirectory(); - IndexWriter indexWriter = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setRAMBufferSizeMB(0.01)); + IndexWriter indexWriter = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setRAMBufferSizeMB(0.01).setMergePolicy(newLogMergePolicy())); ((LogMergePolicy) indexWriter.getConfig().getMergePolicy()).setUseCompoundFile(false); String BIG="alskjhlaksjghlaksjfhalksvjepgjioefgjnsdfjgefgjhelkgjhqewlrkhgwlekgrhwelkgjhwelkgrhwlkejg"; Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java Fri Jan 28 18:24:40 2011 -0500 @@ -684,7 +684,7 @@ MockDirectoryWrapper dir = newDirectory(); IndexWriter modifier = new IndexWriter(dir, newIndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer(MockTokenizer.WHITESPACE, false)).setMaxBufferedDeleteTerms(2).setReaderPooling(false)); + TEST_VERSION_CURRENT, new MockAnalyzer(MockTokenizer.WHITESPACE, false)).setMaxBufferedDeleteTerms(2).setReaderPooling(false).setMergePolicy(newLogMergePolicy())); modifier.setInfoStream(VERBOSE ? System.out : null); LogMergePolicy lmp = (LogMergePolicy) modifier.getConfig().getMergePolicy(); Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java Fri Jan 28 18:24:40 2011 -0500 @@ -288,6 +288,7 @@ public void testExceptionDocumentsWriterInit() throws IOException { Directory dir = newDirectory(); MockIndexWriter2 w = new MockIndexWriter2(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer())); + w.setInfoStream(VERBOSE ? System.out : null); Document doc = new Document(); doc.add(newField("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); @@ -359,7 +360,7 @@ public void testExceptionOnMergeInit() throws IOException { Directory dir = newDirectory(); IndexWriterConfig conf = newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()) - .setMaxBufferedDocs(2).setMergeScheduler(new ConcurrentMergeScheduler()); + .setMaxBufferedDocs(2).setMergeScheduler(new ConcurrentMergeScheduler()).setMergePolicy(newLogMergePolicy()); ((LogMergePolicy) conf.getMergePolicy()).setMergeFactor(2); MockIndexWriter3 w = new MockIndexWriter3(dir, conf); w.doFail = true; @@ -527,7 +528,7 @@ System.out.println("TEST: cycle i=" + i); } MockDirectoryWrapper dir = newDirectory(); - IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, analyzer)); + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, analyzer).setMergePolicy(newLogMergePolicy())); writer.setInfoStream(VERBOSE ? System.out : null); // don't allow a sudden merge to clean up the deleted @@ -844,7 +845,7 @@ public void testOptimizeExceptions() throws IOException { Directory startDir = newDirectory(); - IndexWriterConfig conf = newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMaxBufferedDocs(2); + IndexWriterConfig conf = newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMaxBufferedDocs(2).setMergePolicy(newLogMergePolicy()); ((LogMergePolicy) conf.getMergePolicy()).setMergeFactor(100); IndexWriter w = new IndexWriter(startDir, conf); for(int i=0;i<27;i++) Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java Fri Jan 28 18:24:40 2011 -0500 @@ -104,7 +104,7 @@ dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()). setMaxBufferedDocs(10). - setMergePolicy(newLogMergePolicy()) + setMergePolicy(newInOrderLogMergePolicy()) ); for (int i = 0; i < 250; i++) { Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java Fri Jan 28 18:24:40 2011 -0500 @@ -58,7 +58,7 @@ IndexWriter writer = new IndexWriter( merged, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()). - setMergePolicy(newLogMergePolicy(2)) + setMergePolicy(newInOrderLogMergePolicy(2)) ); writer.setInfoStream(VERBOSE ? System.out : null); writer.addIndexes(indexA, indexB); @@ -102,7 +102,7 @@ newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()). setOpenMode(OpenMode.CREATE). setMaxBufferedDocs(2). - setMergePolicy(newLogMergePolicy(2)) + setMergePolicy(newInOrderLogMergePolicy(2)) ); for (int i = start; i < (start + numDocs); i++) Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java Fri Jan 28 18:24:40 2011 -0500 @@ -232,7 +232,7 @@ // Make a new dir that will enforce disk usage: MockDirectoryWrapper dir = new MockDirectoryWrapper(random, new RAMDirectory(startDir)); - writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.APPEND)); + writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy())); IOException err = null; writer.setInfoStream(VERBOSE ? System.out : null); @@ -401,10 +401,10 @@ // required is at most 2X total input size of // indices so let's make sure: assertTrue("max free Directory space required exceeded 1X the total input index sizes during " + methodName + - ": max temp usage = " + (dir.getMaxUsedSizeInBytes()-startDiskUsage) + " bytes; " + - "starting disk usage = " + startDiskUsage + " bytes; " + - "input index disk usage = " + inputDiskUsage + " bytes", - (dir.getMaxUsedSizeInBytes()-startDiskUsage) < 2*(startDiskUsage + inputDiskUsage)); + ": max temp usage = " + (dir.getMaxUsedSizeInBytes()-startDiskUsage) + " bytes vs limit=" + (2*(startDiskUsage + inputDiskUsage)) + + "; starting disk usage = " + startDiskUsage + " bytes; " + + "input index disk usage = " + inputDiskUsage + " bytes", + (dir.getMaxUsedSizeInBytes()-startDiskUsage) < 2*(startDiskUsage + inputDiskUsage)); } // Make sure we don't hit disk full during close below: Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java Fri Jan 28 18:24:40 2011 -0500 @@ -365,7 +365,7 @@ int numDirs = 3; Directory mainDir = newDirectory(); - IndexWriter mainWriter = new IndexWriter(mainDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer())); + IndexWriter mainWriter = new IndexWriter(mainDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newLogMergePolicy())); _TestUtil.reduceOpenFiles(mainWriter); mainWriter.setInfoStream(infoStream); @@ -899,7 +899,7 @@ public void testExpungeDeletes() throws Throwable { Directory dir = newDirectory(); - final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer())); + final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newLogMergePolicy())); Document doc = new Document(); doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED)); Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED); Index: lucene/src/test/org/apache/lucene/index/TestLazyBug.java --- lucene/src/test/org/apache/lucene/index/TestLazyBug.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestLazyBug.java Fri Jan 28 18:24:40 2011 -0500 @@ -63,7 +63,7 @@ Directory dir = newDirectory(); try { IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( - TEST_VERSION_CURRENT, new MockAnalyzer())); + TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newLogMergePolicy())); LogMergePolicy lmp = (LogMergePolicy) writer.getConfig().getMergePolicy(); lmp.setUseCompoundFile(false); Index: lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java --- lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java Fri Jan 28 18:24:40 2011 -0500 @@ -45,7 +45,7 @@ super.setUp(); dir = newDirectory(); IndexWriterConfig config = newIndexWriterConfig(TEST_VERSION_CURRENT, - new MockAnalyzer(MockTokenizer.SIMPLE, true)); + new MockAnalyzer(MockTokenizer.SIMPLE, true)).setMergePolicy(newInOrderLogMergePolicy()); config.setSimilarityProvider(new TestSimilarity()); RandomIndexWriter writer = new RandomIndexWriter(random, dir, config); Document doc = new Document(); Index: lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java --- lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java Fri Jan 28 18:24:40 2011 -0500 @@ -69,7 +69,7 @@ public void testSimpleSkip() throws IOException { Directory dir = new CountingRAMDirectory(new RAMDirectory()); - IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new PayloadAnalyzer()).setCodecProvider(_TestUtil.alwaysCodec("Standard"))); + IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new PayloadAnalyzer()).setCodecProvider(_TestUtil.alwaysCodec("Standard")).setMergePolicy(newInOrderLogMergePolicy())); Term term = new Term("test", "a"); for (int i = 0; i < 5000; i++) { Document d1 = new Document(); Index: lucene/src/test/org/apache/lucene/index/TestNRTThreads.java --- lucene/src/test/org/apache/lucene/index/TestNRTThreads.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/index/TestNRTThreads.java Fri Jan 28 18:24:40 2011 -0500 @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.HashSet; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.Executors; @@ -94,7 +95,7 @@ } } }); - + final IndexWriter writer = new IndexWriter(dir, conf); if (VERBOSE) { writer.setInfoStream(System.out); @@ -105,10 +106,12 @@ ((ConcurrentMergeScheduler) ms).setMaxThreadCount(1); ((ConcurrentMergeScheduler) ms).setMaxMergeCount(1); } + /* LogMergePolicy lmp = (LogMergePolicy) writer.getConfig().getMergePolicy(); if (lmp.getMergeFactor() > 5) { lmp.setMergeFactor(5); } + */ final int NUM_INDEX_THREADS = 2; final int NUM_SEARCH_THREADS = 3; @@ -118,7 +121,7 @@ final AtomicInteger addCount = new AtomicInteger(); final AtomicInteger delCount = new AtomicInteger(); - final List delIDs = Collections.synchronizedList(new ArrayList()); + final Set delIDs = Collections.synchronizedSet(new HashSet()); final long stopTime = System.currentTimeMillis() + RUN_TIME_SEC*1000; Thread[] threads = new Thread[NUM_INDEX_THREADS]; @@ -142,20 +145,20 @@ } if (random.nextBoolean()) { if (VERBOSE) { - //System.out.println(Thread.currentThread().getName() + ": add doc id:" + doc.get("id")); + System.out.println(Thread.currentThread().getName() + ": add doc id:" + doc.get("id")); } writer.addDocument(doc); } else { // we use update but it never replaces a // prior doc if (VERBOSE) { - //System.out.println(Thread.currentThread().getName() + ": update doc id:" + doc.get("id")); + System.out.println(Thread.currentThread().getName() + ": update doc id:" + doc.get("id")); } writer.updateDocument(new Term("id", doc.get("id")), doc); } if (random.nextInt(5) == 3) { if (VERBOSE) { - //System.out.println(Thread.currentThread().getName() + ": buffer del id:" + doc.get("id")); + System.out.println(Thread.currentThread().getName() + ": buffer del id:" + doc.get("id")); } toDeleteIDs.add(doc.get("id")); } @@ -164,6 +167,9 @@ System.out.println(Thread.currentThread().getName() + ": apply " + toDeleteIDs.size() + " deletes"); } for(String id : toDeleteIDs) { + if (VERBOSE) { + System.out.println(Thread.currentThread().getName() + ": del term=id:" + id); + } writer.deleteDocuments(new Term("id", id)); } final int count = delCount.addAndGet(toDeleteIDs.size()); @@ -347,12 +353,28 @@ final IndexReader r2 = writer.getReader(); final IndexSearcher s = new IndexSearcher(r2); + boolean doFail = false; for(String id : delIDs) { final TopDocs hits = s.search(new TermQuery(new Term("id", id)), 1); if (hits.totalHits != 0) { - fail("doc id=" + id + " is supposed to be deleted, but got docID=" + hits.scoreDocs[0].doc); + System.out.println("doc id=" + id + " is supposed to be deleted, but got docID=" + hits.scoreDocs[0].doc); + doFail = true; } } + + final int endID = Integer.parseInt(docs.nextDoc().get("id")); + for(int id=0;id docs = new HashMap(); IndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.CREATE).setRAMBufferSizeMB( - 0.1).setMaxBufferedDocs(maxBufferedDocs)); + 0.1).setMaxBufferedDocs(maxBufferedDocs).setMergePolicy(newLogMergePolicy())); w.setInfoStream(VERBOSE ? System.out : null); w.commit(); LogMergePolicy lmp = (LogMergePolicy) w.getConfig().getMergePolicy(); @@ -206,7 +206,7 @@ IndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.CREATE) .setRAMBufferSizeMB(0.1).setMaxBufferedDocs(maxBufferedDocs).setMaxThreadStates(maxThreadStates) - .setReaderPooling(doReaderPooling)); + .setReaderPooling(doReaderPooling).setMergePolicy(newLogMergePolicy())); w.setInfoStream(VERBOSE ? System.out : null); LogMergePolicy lmp = (LogMergePolicy) w.getConfig().getMergePolicy(); lmp.setUseCompoundFile(false); @@ -248,7 +248,7 @@ public static void indexSerial(Random random, Map docs, Directory dir) throws IOException { - IndexWriter w = new IndexWriter(dir, LuceneTestCase.newIndexWriterConfig(random, TEST_VERSION_CURRENT, new MockAnalyzer())); + IndexWriter w = new IndexWriter(dir, LuceneTestCase.newIndexWriterConfig(random, TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newLogMergePolicy())); // index all docs in a single thread Iterator iter = docs.values().iterator(); Index: lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java --- lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java Fri Jan 28 18:24:40 2011 -0500 @@ -124,14 +124,14 @@ RandomIndexWriter writer = new RandomIndexWriter(random, index.index, newIndexWriterConfig(random, TEST_VERSION_CURRENT, new MockAnalyzer()) - .setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000))); + .setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)).setMergePolicy(newLogMergePolicy())); + _TestUtil.reduceOpenFiles(writer.w); + while(true) { int minCount = 0; int maxCount = 0; - _TestUtil.reduceOpenFiles(writer.w); - for (int d = minId; d <= maxId; d++) { idField.setValue(pad(d)); int r = index.allowNegativeRandomInts ? random.nextInt() : random Index: lucene/src/test/org/apache/lucene/search/TestDocBoost.java --- lucene/src/test/org/apache/lucene/search/TestDocBoost.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestDocBoost.java Fri Jan 28 18:24:40 2011 -0500 @@ -19,13 +19,14 @@ import java.io.IOException; -import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.*; +import org.apache.lucene.index.IndexReader.AtomicReaderContext; import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexReader.AtomicReaderContext; import org.apache.lucene.index.RandomIndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.store.Directory; +import org.apache.lucene.util.LuceneTestCase; /** Document boost unit test. * @@ -36,7 +37,7 @@ public void testDocBoost() throws Exception { Directory store = newDirectory(); - RandomIndexWriter writer = new RandomIndexWriter(random, store); + RandomIndexWriter writer = new RandomIndexWriter(random, store, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); Fieldable f1 = newField("field", "word", Field.Store.YES, Field.Index.ANALYZED); Fieldable f2 = newField("field", "word", Field.Store.YES, Field.Index.ANALYZED); Index: lucene/src/test/org/apache/lucene/search/TestExplanations.java --- lucene/src/test/org/apache/lucene/search/TestExplanations.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestExplanations.java Fri Jan 28 18:24:40 2011 -0500 @@ -68,7 +68,7 @@ public void setUp() throws Exception { super.setUp(); directory = newDirectory(); - RandomIndexWriter writer= new RandomIndexWriter(random, directory); + RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); for (int i = 0; i < docFields.length; i++) { Document doc = new Document(); doc.add(newField(KEY, ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED)); Index: lucene/src/test/org/apache/lucene/search/TestFieldCache.java --- lucene/src/test/org/apache/lucene/search/TestFieldCache.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestFieldCache.java Fri Jan 28 18:24:40 2011 -0500 @@ -41,7 +41,7 @@ public void setUp() throws Exception { super.setUp(); directory = newDirectory(); - RandomIndexWriter writer= new RandomIndexWriter(random, directory); + RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); long theLong = Long.MAX_VALUE; double theDouble = Double.MAX_VALUE; byte theByte = Byte.MAX_VALUE; Index: lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java --- lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java Fri Jan 28 18:24:40 2011 -0500 @@ -17,17 +17,19 @@ * limitations under the License. */ +import java.util.BitSet; + +import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.index.IndexReader.AtomicReaderContext; import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexReader.AtomicReaderContext; import org.apache.lucene.index.RandomIndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.store.Directory; +import org.apache.lucene.util.DocIdBitSet; import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.util.DocIdBitSet; -import java.util.BitSet; /** * FilteredQuery JUnit tests. @@ -49,7 +51,7 @@ public void setUp() throws Exception { super.setUp(); directory = newDirectory(); - RandomIndexWriter writer = new RandomIndexWriter (random, directory); + RandomIndexWriter writer = new RandomIndexWriter (random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); Document doc = new Document(); doc.add (newField("field", "one two three four five", Field.Store.YES, Field.Index.ANALYZED)); Index: lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java --- lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java Fri Jan 28 18:24:40 2011 -0500 @@ -24,7 +24,6 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; -import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader.AtomicReaderContext; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; @@ -47,14 +46,14 @@ Directory directory = newDirectory(); int[] filterBits = {1, 36}; SimpleDocIdSetFilter filter = new SimpleDocIdSetFilter(filterBits); - IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer())); + IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); searchFiltered(writer, directory, filter, enforceSingleSegment); // run the test on more than one segment enforceSingleSegment = false; // reset - it is stateful filter.reset(); writer.close(); - writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(10)); + writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(10).setMergePolicy(newInOrderLogMergePolicy())); // we index 60 docs - this will create 6 segments searchFiltered(writer, directory, filter, enforceSingleSegment); writer.close(); Index: lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java --- lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java Fri Jan 28 18:24:40 2011 -0500 @@ -79,7 +79,7 @@ int terms = (int) Math.pow(2, bits); Directory dir = newDirectory(); - RandomIndexWriter writer = new RandomIndexWriter(random, dir, new MockAnalyzer(MockTokenizer.KEYWORD, false)); + RandomIndexWriter writer = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(MockTokenizer.KEYWORD, false)).setMergePolicy(newInOrderLogMergePolicy())); Document doc = new Document(); Field field = newField("field", "", Field.Store.NO, Field.Index.ANALYZED); Index: lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java --- lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java Fri Jan 28 18:24:40 2011 -0500 @@ -40,7 +40,7 @@ public void testQuery() throws Exception { Directory dir = newDirectory(); IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig( - TEST_VERSION_CURRENT, analyzer).setMaxBufferedDocs(2)); + TEST_VERSION_CURRENT, analyzer).setMaxBufferedDocs(2).setMergePolicy(newInOrderLogMergePolicy())); addDoc("one", iw, 1f); addDoc("two", iw, 20f); addDoc("three four", iw, 300f); Index: lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java --- lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java Fri Jan 28 18:24:40 2011 -0500 @@ -38,7 +38,7 @@ public void setUp() throws Exception { super.setUp(); directory = newDirectory(); - IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer())); + IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); //writer.setUseCompoundFile(false); //writer.infoStream = System.out; for (int i = 0; i < numDocs; i++) { Index: lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java --- lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java Fri Jan 28 18:24:40 2011 -0500 @@ -55,7 +55,8 @@ directory = newDirectory(); RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()) - .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000))); + .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)) + .setMergePolicy(newInOrderLogMergePolicy())); NumericField field8 = new NumericField("field8", 8, Field.Store.YES, true), Index: lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java --- lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java Fri Jan 28 18:24:40 2011 -0500 @@ -52,7 +52,8 @@ directory = newDirectory(); RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()) - .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000))); + .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)) + .setMergePolicy(newInOrderLogMergePolicy())); NumericField field8 = new NumericField("field8", 8, Field.Store.YES, true), Index: lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java --- lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java Fri Jan 28 18:24:40 2011 -0500 @@ -598,7 +598,7 @@ Directory dir = newDirectory(); Analyzer analyzer = new MockAnalyzer(); - RandomIndexWriter w = new RandomIndexWriter(random, dir, analyzer); + RandomIndexWriter w = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer).setMergePolicy(newInOrderLogMergePolicy())); List> docs = new ArrayList>(); Document d = new Document(); Field f = newField("f", "", Field.Store.NO, Field.Index.ANALYZED); Index: lucene/src/test/org/apache/lucene/search/TestSort.java --- lucene/src/test/org/apache/lucene/search/TestSort.java Wed Jan 26 05:34:40 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestSort.java Fri Jan 28 18:24:40 2011 -0500 @@ -121,7 +121,7 @@ throws IOException { Directory indexStore = newDirectory(); dirs.add(indexStore); - RandomIndexWriter writer = new RandomIndexWriter(random, indexStore); + RandomIndexWriter writer = new RandomIndexWriter(random, indexStore, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer()).setMergePolicy(newInOrderLogMergePolicy())); for (int i=0; i