1 package org.apache.lucene.index;
3 * Copyright 2006 The Apache Software Foundation
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 import org.apache.lucene.store.Directory;
19 import org.apache.lucene.analysis.MockAnalyzer;
20 import org.apache.lucene.analysis.standard.StandardAnalyzer;
21 import org.apache.lucene.document.Document;
22 import org.apache.lucene.document.Field;
23 import org.apache.lucene.document.Field.Index;
24 import org.apache.lucene.document.Field.Store;
25 import org.apache.lucene.document.Field.TermVector;
26 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
27 import org.apache.lucene.util.LuceneTestCase;
29 import java.io.IOException;
30 import java.util.Random;
33 public class TestIndexWriterMerging extends LuceneTestCase
37 * Tests that index merging (specifically addIndexes(Directory...)) doesn't
38 * change the index order of documents.
40 public void testLucene() throws IOException {
43 Directory indexA = newDirectory();
44 Directory indexB = newDirectory();
46 fillIndex(random, indexA, 0, num);
47 boolean fail = verifyIndex(indexA, 0);
50 fail("Index a is invalid");
53 fillIndex(random, indexB, num, num);
54 fail = verifyIndex(indexB, num);
57 fail("Index b is invalid");
60 Directory merged = newDirectory();
62 IndexWriter writer = new IndexWriter(
64 newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
65 setMergePolicy(newLogMergePolicy(2))
67 writer.setInfoStream(VERBOSE ? System.out : null);
68 writer.addIndexes(new Directory[]{indexA, indexB});
72 fail = verifyIndex(merged, 0);
74 assertFalse("The merged index is invalid", fail);
80 private boolean verifyIndex(Directory directory, int startAt) throws IOException
83 IndexReader reader = IndexReader.open(directory, true);
85 int max = reader.maxDoc();
86 for (int i = 0; i < max; i++)
88 Document temp = reader.document(i);
89 //System.out.println("doc "+i+"="+temp.getField("count").stringValue());
90 //compare the index doc number to the value that it should be
91 if (!temp.getField("count").stringValue().equals((i + startAt) + ""))
94 System.out.println("Document " + (i + startAt) + " is returning document " + temp.getField("count").stringValue());
101 private void fillIndex(Random random, Directory dir, int start, int numDocs) throws IOException {
103 IndexWriter writer = new IndexWriter(
105 newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
106 setOpenMode(OpenMode.CREATE).
107 setMaxBufferedDocs(2).
108 setMergePolicy(newLogMergePolicy(2))
111 for (int i = start; i < (start + numDocs); i++)
113 Document temp = new Document();
114 temp.add(newField("count", (""+i), Field.Store.YES, Field.Index.NOT_ANALYZED));
116 writer.addDocument(temp);
121 // LUCENE-325: test expungeDeletes, when 2 singular merges
123 public void testExpungeDeletes() throws IOException {
124 Directory dir = newDirectory();
125 IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
126 TEST_VERSION_CURRENT, new MockAnalyzer(random))
127 .setMaxBufferedDocs(2).setRAMBufferSizeMB(
128 IndexWriterConfig.DISABLE_AUTO_FLUSH));
129 writer.setInfoStream(VERBOSE ? System.out : null);
130 Document document = new Document();
132 document = new Document();
133 Field storedField = newField("stored", "stored", Field.Store.YES,
135 document.add(storedField);
136 Field termVectorField = newField("termVector", "termVector",
137 Field.Store.NO, Field.Index.NOT_ANALYZED,
138 Field.TermVector.WITH_POSITIONS_OFFSETS);
139 document.add(termVectorField);
140 for(int i=0;i<10;i++)
141 writer.addDocument(document);
144 IndexReader ir = IndexReader.open(dir, false);
145 assertEquals(10, ir.maxDoc());
146 assertEquals(10, ir.numDocs());
147 ir.deleteDocument(0);
148 ir.deleteDocument(7);
149 assertEquals(8, ir.numDocs());
152 writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
153 assertEquals(8, writer.numDocs());
154 assertEquals(10, writer.maxDoc());
155 writer.expungeDeletes();
156 assertEquals(8, writer.numDocs());
158 ir = IndexReader.open(dir, true);
159 assertEquals(8, ir.maxDoc());
160 assertEquals(8, ir.numDocs());
165 // LUCENE-325: test expungeDeletes, when many adjacent merges are required
166 public void testExpungeDeletes2() throws IOException {
167 Directory dir = newDirectory();
168 IndexWriter writer = new IndexWriter(
170 newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
171 setMaxBufferedDocs(2).
172 setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH).
173 setMergePolicy(newLogMergePolicy(50))
176 Document document = new Document();
178 document = new Document();
179 Field storedField = newField("stored", "stored", Store.YES,
181 document.add(storedField);
182 Field termVectorField = newField("termVector", "termVector",
183 Store.NO, Index.NOT_ANALYZED,
184 TermVector.WITH_POSITIONS_OFFSETS);
185 document.add(termVectorField);
186 for(int i=0;i<98;i++)
187 writer.addDocument(document);
190 IndexReader ir = IndexReader.open(dir, false);
191 assertEquals(98, ir.maxDoc());
192 assertEquals(98, ir.numDocs());
193 for(int i=0;i<98;i+=2)
194 ir.deleteDocument(i);
195 assertEquals(49, ir.numDocs());
198 writer = new IndexWriter(
200 newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
201 setMergePolicy(newLogMergePolicy(3))
203 assertEquals(49, writer.numDocs());
204 writer.expungeDeletes();
206 ir = IndexReader.open(dir, true);
207 assertEquals(49, ir.maxDoc());
208 assertEquals(49, ir.numDocs());
213 // LUCENE-325: test expungeDeletes without waiting, when
214 // many adjacent merges are required
215 public void testExpungeDeletes3() throws IOException {
216 Directory dir = newDirectory();
217 IndexWriter writer = new IndexWriter(
219 newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
220 setMaxBufferedDocs(2).
221 setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH).
222 setMergePolicy(newLogMergePolicy(50))
225 Document document = new Document();
227 document = new Document();
228 Field storedField = newField("stored", "stored", Field.Store.YES,
230 document.add(storedField);
231 Field termVectorField = newField("termVector", "termVector",
232 Field.Store.NO, Field.Index.NOT_ANALYZED,
233 Field.TermVector.WITH_POSITIONS_OFFSETS);
234 document.add(termVectorField);
235 for(int i=0;i<98;i++)
236 writer.addDocument(document);
239 IndexReader ir = IndexReader.open(dir, false);
240 assertEquals(98, ir.maxDoc());
241 assertEquals(98, ir.numDocs());
242 for(int i=0;i<98;i+=2)
243 ir.deleteDocument(i);
244 assertEquals(49, ir.numDocs());
247 writer = new IndexWriter(
249 newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).
250 setMergePolicy(newLogMergePolicy(3))
252 writer.expungeDeletes(false);
254 ir = IndexReader.open(dir, true);
255 assertEquals(49, ir.maxDoc());
256 assertEquals(49, ir.numDocs());
261 // Just intercepts all merges & verifies that we are never
262 // merging a segment with >= 20 (maxMergeDocs) docs
263 private class MyMergeScheduler extends MergeScheduler {
265 synchronized public void merge(IndexWriter writer)
266 throws CorruptIndexException, IOException {
269 MergePolicy.OneMerge merge = writer.getNextMerge();
273 for(int i=0;i<merge.segments.size();i++) {
274 assert merge.segments.get(i).docCount < 20;
281 public void close() {}
285 public void testSetMaxMergeDocs() throws IOException {
286 Directory dir = newDirectory();
287 IndexWriterConfig conf = newIndexWriterConfig(
288 TEST_VERSION_CURRENT, new MockAnalyzer(random))
289 .setMergeScheduler(new MyMergeScheduler()).setMaxBufferedDocs(2).setMergePolicy(newLogMergePolicy());
290 LogMergePolicy lmp = (LogMergePolicy) conf.getMergePolicy();
291 lmp.setMaxMergeDocs(20);
292 lmp.setMergeFactor(2);
293 IndexWriter iw = new IndexWriter(dir, conf);
294 iw.setInfoStream(VERBOSE ? System.out : null);
295 Document document = new Document();
296 document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
297 Field.TermVector.YES));
298 for(int i=0;i<177;i++)
299 iw.addDocument(document);