~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.apache.lucene.index;
2
 
 
3
 
/**
4
 
 * Copyright 2004 The Apache Software Foundation
5
 
 *
6
 
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 
 * you may not use this file except in compliance with the License.
8
 
 * You may obtain a copy of the License at
9
 
 *
10
 
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 
 *
12
 
 * Unless required by applicable law or agreed to in writing, software
13
 
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 
 * See the License for the specific language governing permissions and
16
 
 * limitations under the License.
17
 
 */
18
 
 
19
 
import java.io.IOException;
20
 
import java.io.PrintStream;
21
 
import java.util.ArrayList;
22
 
import java.util.Collections;
23
 
import java.util.List;
24
 
import java.util.Random;
25
 
import java.util.concurrent.atomic.AtomicBoolean;
26
 
 
27
 
import org.apache.lucene.analysis.MockAnalyzer;
28
 
import org.apache.lucene.analysis.WhitespaceAnalyzer;
29
 
import org.apache.lucene.document.Document;
30
 
import org.apache.lucene.document.Field;
31
 
import org.apache.lucene.document.Field.Index;
32
 
import org.apache.lucene.document.Field.Store;
33
 
import org.apache.lucene.search.TermQuery;
34
 
import org.apache.lucene.search.IndexSearcher;
35
 
import org.apache.lucene.search.Query;
36
 
import org.apache.lucene.search.TopDocs;
37
 
import org.apache.lucene.store.Directory;
38
 
import org.apache.lucene.store.MockDirectoryWrapper;
39
 
import org.apache.lucene.store.AlreadyClosedException;
40
 
import org.apache.lucene.store.RAMDirectory;
41
 
import org.apache.lucene.util.LuceneTestCase;
42
 
import org.apache.lucene.util._TestUtil;
43
 
import org.apache.lucene.util.ThreadInterruptedException;
44
 
import java.util.concurrent.atomic.AtomicInteger;
45
 
 
46
 
public class TestIndexWriterReader extends LuceneTestCase {
47
 
  static PrintStream infoStream = VERBOSE ? System.out : null;
48
 
  
49
 
  public static int count(Term t, IndexReader r) throws IOException {
50
 
    int count = 0;
51
 
    TermDocs td = r.termDocs(t);
52
 
    while (td.next()) {
53
 
      td.doc();
54
 
      count++;
55
 
    }
56
 
    td.close();
57
 
    return count;
58
 
  }
59
 
  
60
 
  public void testAddCloseOpen() throws IOException {
61
 
    Directory dir1 = newDirectory();
62
 
    IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
63
 
    
64
 
    IndexWriter writer = new IndexWriter(dir1, iwc);
65
 
    for (int i = 0; i < 97 ; i++) {
66
 
      IndexReader reader = writer.getReader();
67
 
      if (i == 0) {
68
 
        writer.addDocument(DocHelper.createDocument(i, "x", 1 + random.nextInt(5)));
69
 
      } else {
70
 
        int previous = random.nextInt(i);
71
 
        // a check if the reader is current here could fail since there might be
72
 
        // merges going on.
73
 
        switch (random.nextInt(5)) {
74
 
        case 0:
75
 
        case 1:
76
 
        case 2:
77
 
          writer.addDocument(DocHelper.createDocument(i, "x", 1 + random.nextInt(5)));
78
 
          break;
79
 
        case 3:
80
 
          writer.updateDocument(new Term("id", "" + previous), DocHelper.createDocument(
81
 
              previous, "x", 1 + random.nextInt(5)));
82
 
          break;
83
 
        case 4:
84
 
          writer.deleteDocuments(new Term("id", "" + previous));
85
 
        }
86
 
      }
87
 
      assertFalse(reader.isCurrent());
88
 
      reader.close();
89
 
    }
90
 
    writer.forceMerge(1); // make sure all merging is done etc.
91
 
    IndexReader reader = writer.getReader();
92
 
    writer.commit(); // no changes that are not visible to the reader
93
 
    assertTrue(reader.isCurrent());
94
 
    writer.close();
95
 
    assertTrue(reader.isCurrent()); // all changes are visible to the reader
96
 
    iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
97
 
    writer = new IndexWriter(dir1, iwc);
98
 
    assertTrue(reader.isCurrent());
99
 
    writer.addDocument(DocHelper.createDocument(1, "x", 1+random.nextInt(5)));
100
 
    assertTrue(reader.isCurrent()); // segments in ram but IW is different to the readers one
101
 
    writer.close();
102
 
    assertFalse(reader.isCurrent()); // segments written
103
 
    reader.close();
104
 
    dir1.close();
105
 
  }
106
 
  
107
 
  public void testUpdateDocument() throws Exception {
108
 
    boolean doFullMerge = true;
109
 
 
110
 
    Directory dir1 = newDirectory();
111
 
    IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
112
 
    if (iwc.getMaxBufferedDocs() < 20) {
113
 
      iwc.setMaxBufferedDocs(20);
114
 
    }
115
 
    // no merging
116
 
    if (random.nextBoolean()) {
117
 
      iwc.setMergePolicy(NoMergePolicy.NO_COMPOUND_FILES);
118
 
    } else {
119
 
      iwc.setMergePolicy(NoMergePolicy.COMPOUND_FILES);
120
 
    }
121
 
    IndexWriter writer = new IndexWriter(dir1, iwc);
122
 
 
123
 
    // create the index
124
 
    createIndexNoClose(!doFullMerge, "index1", writer);
125
 
 
126
 
    // writer.flush(false, true, true);
127
 
 
128
 
    // get a reader
129
 
    IndexReader r1 = writer.getReader();
130
 
    assertTrue(r1.isCurrent());
131
 
 
132
 
    String id10 = r1.document(10).getField("id").stringValue();
133
 
    
134
 
    Document newDoc = r1.document(10);
135
 
    newDoc.removeField("id");
136
 
    newDoc.add(newField("id", Integer.toString(8000), Store.YES, Index.NOT_ANALYZED));
137
 
    writer.updateDocument(new Term("id", id10), newDoc);
138
 
    assertFalse(r1.isCurrent());
139
 
 
140
 
    IndexReader r2 = writer.getReader();
141
 
    assertTrue(r2.isCurrent());
142
 
    assertEquals(0, count(new Term("id", id10), r2));
143
 
    assertEquals(1, count(new Term("id", Integer.toString(8000)), r2));
144
 
    
145
 
    r1.close();
146
 
    writer.close();
147
 
    assertTrue(r2.isCurrent());
148
 
    
149
 
    IndexReader r3 = IndexReader.open(dir1, true);
150
 
    assertTrue(r3.isCurrent());
151
 
    assertTrue(r2.isCurrent());
152
 
    assertEquals(0, count(new Term("id", id10), r3));
153
 
    assertEquals(1, count(new Term("id", Integer.toString(8000)), r3));
154
 
 
155
 
    writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
156
 
    Document doc = new Document();
157
 
    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
158
 
    writer.addDocument(doc);
159
 
    assertTrue(r2.isCurrent());
160
 
    assertTrue(r3.isCurrent());
161
 
 
162
 
    writer.close();
163
 
 
164
 
    assertFalse(r2.isCurrent());
165
 
    assertTrue(!r3.isCurrent());
166
 
 
167
 
    r2.close();
168
 
    r3.close();
169
 
    
170
 
    dir1.close();
171
 
  }
172
 
  
173
 
  public void testIsCurrent() throws IOException {
174
 
    Directory dir = newDirectory();
175
 
    IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
176
 
    
177
 
    IndexWriter writer = new IndexWriter(dir, iwc);
178
 
    Document doc = new Document();
179
 
    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
180
 
    writer.addDocument(doc);
181
 
    writer.close();
182
 
    
183
 
    iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
184
 
    writer = new IndexWriter(dir, iwc);
185
 
    doc = new Document();
186
 
    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
187
 
    IndexReader nrtReader = writer.getReader();
188
 
    assertTrue(nrtReader.isCurrent());
189
 
    writer.addDocument(doc);
190
 
    assertFalse(nrtReader.isCurrent()); // should see the changes
191
 
    writer.forceMerge(1); // make sure we don't have a merge going on
192
 
    assertFalse(nrtReader.isCurrent());
193
 
    nrtReader.close();
194
 
    
195
 
    IndexReader dirReader = IndexReader.open(dir);
196
 
    nrtReader = writer.getReader();
197
 
    
198
 
    assertTrue(dirReader.isCurrent());
199
 
    assertTrue(nrtReader.isCurrent()); // nothing was committed yet so we are still current
200
 
    assertEquals(2, nrtReader.maxDoc()); // sees the actual document added
201
 
    assertEquals(1, dirReader.maxDoc());
202
 
    writer.close(); // close is actually a commit both should see the changes
203
 
    assertTrue(nrtReader.isCurrent()); 
204
 
    assertFalse(dirReader.isCurrent()); // this reader has been opened before the writer was closed / committed
205
 
    
206
 
    dirReader.close();
207
 
    nrtReader.close();
208
 
    dir.close();
209
 
  }
210
 
  
211
 
  /**
212
 
   * Test using IW.addIndexes
213
 
   * 
214
 
   * @throws Exception
215
 
   */
216
 
  public void testAddIndexes() throws Exception {
217
 
    boolean doFullMerge = false;
218
 
 
219
 
    Directory dir1 = newDirectory();
220
 
    IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
221
 
    if (iwc.getMaxBufferedDocs() < 20) {
222
 
      iwc.setMaxBufferedDocs(20);
223
 
    }
224
 
    // no merging
225
 
    if (random.nextBoolean()) {
226
 
      iwc.setMergePolicy(NoMergePolicy.NO_COMPOUND_FILES);
227
 
    } else {
228
 
      iwc.setMergePolicy(NoMergePolicy.COMPOUND_FILES);
229
 
    }
230
 
    IndexWriter writer = new IndexWriter(dir1, iwc);
231
 
 
232
 
    writer.setInfoStream(infoStream);
233
 
    // create the index
234
 
    createIndexNoClose(!doFullMerge, "index1", writer);
235
 
    writer.flush(false, true);
236
 
 
237
 
    // create a 2nd index
238
 
    Directory dir2 = newDirectory();
239
 
    IndexWriter writer2 = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
240
 
    writer2.setInfoStream(infoStream);
241
 
    createIndexNoClose(!doFullMerge, "index2", writer2);
242
 
    writer2.close();
243
 
 
244
 
    IndexReader r0 = writer.getReader();
245
 
    assertTrue(r0.isCurrent());
246
 
    writer.addIndexes(new Directory[] { dir2 });
247
 
    assertFalse(r0.isCurrent());
248
 
    r0.close();
249
 
 
250
 
    IndexReader r1 = writer.getReader();
251
 
    assertTrue(r1.isCurrent());
252
 
 
253
 
    writer.commit();
254
 
    assertTrue(r1.isCurrent()); // we have seen all changes - no change after opening the NRT reader
255
 
 
256
 
    assertEquals(200, r1.maxDoc());
257
 
 
258
 
    int index2df = r1.docFreq(new Term("indexname", "index2"));
259
 
 
260
 
    assertEquals(100, index2df);
261
 
 
262
 
    // verify the docs are from different indexes
263
 
    Document doc5 = r1.document(5);
264
 
    assertEquals("index1", doc5.get("indexname"));
265
 
    Document doc150 = r1.document(150);
266
 
    assertEquals("index2", doc150.get("indexname"));
267
 
    r1.close();
268
 
    writer.close();
269
 
    dir1.close();
270
 
    dir2.close();
271
 
  }
272
 
  
273
 
  public void testAddIndexes2() throws Exception {
274
 
    boolean doFullMerge = false;
275
 
 
276
 
    Directory dir1 = newDirectory();
277
 
    IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
278
 
    writer.setInfoStream(infoStream);
279
 
 
280
 
    // create a 2nd index
281
 
    Directory dir2 = newDirectory();
282
 
    IndexWriter writer2 = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
283
 
    writer2.setInfoStream(infoStream);
284
 
    createIndexNoClose(!doFullMerge, "index2", writer2);
285
 
    writer2.close();
286
 
 
287
 
    writer.addIndexes(new Directory[] { dir2 });
288
 
    writer.addIndexes(new Directory[] { dir2 });
289
 
    writer.addIndexes(new Directory[] { dir2 });
290
 
    writer.addIndexes(new Directory[] { dir2 });
291
 
    writer.addIndexes(new Directory[] { dir2 });
292
 
 
293
 
    IndexReader r1 = writer.getReader();
294
 
    assertEquals(500, r1.maxDoc());
295
 
    
296
 
    r1.close();
297
 
    writer.close();
298
 
    dir1.close();
299
 
    dir2.close();
300
 
  }
301
 
 
302
 
  /**
303
 
   * Deletes using IW.deleteDocuments
304
 
   * 
305
 
   * @throws Exception
306
 
   */
307
 
  public void testDeleteFromIndexWriter() throws Exception {
308
 
    boolean doFullMerge = true;
309
 
 
310
 
    Directory dir1 = newDirectory();
311
 
    IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setReaderTermsIndexDivisor(2));
312
 
    writer.setInfoStream(infoStream);
313
 
    // create the index
314
 
    createIndexNoClose(!doFullMerge, "index1", writer);
315
 
    writer.flush(false, true);
316
 
    // get a reader
317
 
    IndexReader r1 = writer.getReader();
318
 
 
319
 
    String id10 = r1.document(10).getField("id").stringValue();
320
 
 
321
 
    // deleted IW docs should not show up in the next getReader
322
 
    writer.deleteDocuments(new Term("id", id10));
323
 
    IndexReader r2 = writer.getReader();
324
 
    assertEquals(1, count(new Term("id", id10), r1));
325
 
    assertEquals(0, count(new Term("id", id10), r2));
326
 
    
327
 
    String id50 = r1.document(50).getField("id").stringValue();
328
 
    assertEquals(1, count(new Term("id", id50), r1));
329
 
    
330
 
    writer.deleteDocuments(new Term("id", id50));
331
 
    
332
 
    IndexReader r3 = writer.getReader();
333
 
    assertEquals(0, count(new Term("id", id10), r3));
334
 
    assertEquals(0, count(new Term("id", id50), r3));
335
 
    
336
 
    String id75 = r1.document(75).getField("id").stringValue();
337
 
    writer.deleteDocuments(new TermQuery(new Term("id", id75)));
338
 
    IndexReader r4 = writer.getReader();
339
 
    assertEquals(1, count(new Term("id", id75), r3));
340
 
    assertEquals(0, count(new Term("id", id75), r4));
341
 
    
342
 
    r1.close();
343
 
    r2.close();
344
 
    r3.close();
345
 
    r4.close();
346
 
    writer.close();
347
 
        
348
 
    // reopen the writer to verify the delete made it to the directory
349
 
    writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
350
 
    writer.setInfoStream(infoStream);
351
 
    IndexReader w2r1 = writer.getReader();
352
 
    assertEquals(0, count(new Term("id", id10), w2r1));
353
 
    w2r1.close();
354
 
    writer.close();
355
 
    dir1.close();
356
 
  }
357
 
 
358
 
  public void testAddIndexesAndDoDeletesThreads() throws Throwable {
359
 
    final int numIter = 2;
360
 
    int numDirs = 3;
361
 
    
362
 
    Directory mainDir = newDirectory();
363
 
    IndexWriter mainWriter = new IndexWriter(mainDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
364
 
    _TestUtil.reduceOpenFiles(mainWriter);
365
 
 
366
 
    mainWriter.setInfoStream(infoStream);
367
 
    AddDirectoriesThreads addDirThreads = new AddDirectoriesThreads(numIter, mainWriter);
368
 
    addDirThreads.launchThreads(numDirs);
369
 
    addDirThreads.joinThreads();
370
 
    
371
 
    //assertEquals(100 + numDirs * (3 * numIter / 4) * addDirThreads.NUM_THREADS
372
 
    //    * addDirThreads.NUM_INIT_DOCS, addDirThreads.mainWriter.numDocs());
373
 
    assertEquals(addDirThreads.count.intValue(), addDirThreads.mainWriter.numDocs());
374
 
 
375
 
    addDirThreads.close(true);
376
 
    
377
 
    assertTrue(addDirThreads.failures.size() == 0);
378
 
 
379
 
    _TestUtil.checkIndex(mainDir);
380
 
 
381
 
    IndexReader reader = IndexReader.open(mainDir, true);
382
 
    assertEquals(addDirThreads.count.intValue(), reader.numDocs());
383
 
    //assertEquals(100 + numDirs * (3 * numIter / 4) * addDirThreads.NUM_THREADS
384
 
    //    * addDirThreads.NUM_INIT_DOCS, reader.numDocs());
385
 
    reader.close();
386
 
 
387
 
    addDirThreads.closeDir();
388
 
    mainDir.close();
389
 
  }
390
 
  
391
 
  private class AddDirectoriesThreads {
392
 
    Directory addDir;
393
 
    final static int NUM_THREADS = 5;
394
 
    final static int NUM_INIT_DOCS = 100;
395
 
    int numDirs;
396
 
    final Thread[] threads = new Thread[NUM_THREADS];
397
 
    IndexWriter mainWriter;
398
 
    final List<Throwable> failures = new ArrayList<Throwable>();
399
 
    IndexReader[] readers;
400
 
    boolean didClose = false;
401
 
    AtomicInteger count = new AtomicInteger(0);
402
 
    AtomicInteger numaddIndexes = new AtomicInteger(0);
403
 
    
404
 
    public AddDirectoriesThreads(int numDirs, IndexWriter mainWriter) throws Throwable {
405
 
      this.numDirs = numDirs;
406
 
      this.mainWriter = mainWriter;
407
 
      addDir = newDirectory();
408
 
      IndexWriter writer = new IndexWriter(addDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
409
 
      for (int i = 0; i < NUM_INIT_DOCS; i++) {
410
 
        Document doc = DocHelper.createDocument(i, "addindex", 4);
411
 
        writer.addDocument(doc);
412
 
      }
413
 
        
414
 
      writer.close();
415
 
      
416
 
      readers = new IndexReader[numDirs];
417
 
      for (int i = 0; i < numDirs; i++)
418
 
        readers[i] = IndexReader.open(addDir, false);
419
 
    }
420
 
    
421
 
    void joinThreads() {
422
 
      for (int i = 0; i < NUM_THREADS; i++)
423
 
        try {
424
 
          threads[i].join();
425
 
        } catch (InterruptedException ie) {
426
 
          throw new ThreadInterruptedException(ie);
427
 
        }
428
 
    }
429
 
 
430
 
    void close(boolean doWait) throws Throwable {
431
 
      didClose = true;
432
 
      if (doWait) {
433
 
        mainWriter.waitForMerges();
434
 
      }
435
 
      mainWriter.close(doWait);
436
 
    }
437
 
 
438
 
    void closeDir() throws Throwable {
439
 
      for (int i = 0; i < numDirs; i++)
440
 
        readers[i].close();
441
 
      addDir.close();
442
 
    }
443
 
    
444
 
    void handle(Throwable t) {
445
 
      t.printStackTrace(System.out);
446
 
      synchronized (failures) {
447
 
        failures.add(t);
448
 
      }
449
 
    }
450
 
    
451
 
    void launchThreads(final int numIter) {
452
 
      for (int i = 0; i < NUM_THREADS; i++) {
453
 
        threads[i] = new Thread() {
454
 
          @Override
455
 
          public void run() {
456
 
            try {
457
 
              final Directory[] dirs = new Directory[numDirs];
458
 
              for (int k = 0; k < numDirs; k++)
459
 
                dirs[k] = new MockDirectoryWrapper(random, new RAMDirectory(addDir));
460
 
              //int j = 0;
461
 
              //while (true) {
462
 
                // System.out.println(Thread.currentThread().getName() + ": iter
463
 
                // j=" + j);
464
 
                for (int x=0; x < numIter; x++) {
465
 
                  // only do addIndexes
466
 
                  doBody(x, dirs);
467
 
                }
468
 
                //if (numIter > 0 && j == numIter)
469
 
                //  break;
470
 
                //doBody(j++, dirs);
471
 
                //doBody(5, dirs);
472
 
              //}
473
 
            } catch (Throwable t) {
474
 
              handle(t);
475
 
            }
476
 
          }
477
 
        };
478
 
      }
479
 
      for (int i = 0; i < NUM_THREADS; i++)
480
 
        threads[i].start();
481
 
    }
482
 
    
483
 
    void doBody(int j, Directory[] dirs) throws Throwable {
484
 
      switch (j % 4) {
485
 
        case 0:
486
 
          mainWriter.addIndexes(dirs);
487
 
          mainWriter.forceMerge(1);
488
 
          break;
489
 
        case 1:
490
 
          mainWriter.addIndexes(dirs);
491
 
          numaddIndexes.incrementAndGet();
492
 
          break;
493
 
        case 2:
494
 
          mainWriter.addIndexes(readers);
495
 
          break;
496
 
        case 3:
497
 
          mainWriter.commit();
498
 
      }
499
 
      count.addAndGet(dirs.length*NUM_INIT_DOCS);
500
 
    }
501
 
  }
502
 
 
503
 
  public void testIndexWriterReopenSegmentFullMerge() throws Exception {
504
 
    doTestIndexWriterReopenSegment(true);
505
 
  }
506
 
 
507
 
  public void testIndexWriterReopenSegment() throws Exception {
508
 
    doTestIndexWriterReopenSegment(false);
509
 
  }
510
 
 
511
 
  /**
512
 
   * Tests creating a segment, then check to insure the segment can be seen via
513
 
   * IW.getReader
514
 
   */
515
 
  public void doTestIndexWriterReopenSegment(boolean doFullMerge) throws Exception {
516
 
    Directory dir1 = newDirectory();
517
 
    IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
518
 
    writer.setInfoStream(infoStream);
519
 
    IndexReader r1 = writer.getReader();
520
 
    assertEquals(0, r1.maxDoc());
521
 
    createIndexNoClose(false, "index1", writer);
522
 
    writer.flush(!doFullMerge, true);
523
 
 
524
 
    IndexReader iwr1 = writer.getReader();
525
 
    assertEquals(100, iwr1.maxDoc());
526
 
 
527
 
    IndexReader r2 = writer.getReader();
528
 
    assertEquals(r2.maxDoc(), 100);
529
 
    // add 100 documents
530
 
    for (int x = 10000; x < 10000 + 100; x++) {
531
 
      Document d = DocHelper.createDocument(x, "index1", 5);
532
 
      writer.addDocument(d);
533
 
    }
534
 
    writer.flush(false, true);
535
 
    // verify the reader was reopened internally
536
 
    IndexReader iwr2 = writer.getReader();
537
 
    assertTrue(iwr2 != r1);
538
 
    assertEquals(200, iwr2.maxDoc());
539
 
    // should have flushed out a segment
540
 
    IndexReader r3 = writer.getReader();
541
 
    assertTrue(r2 != r3);
542
 
    assertEquals(200, r3.maxDoc());
543
 
 
544
 
    // dec ref the readers rather than close them because
545
 
    // closing flushes changes to the writer
546
 
    r1.close();
547
 
    iwr1.close();
548
 
    r2.close();
549
 
    r3.close();
550
 
    iwr2.close();
551
 
    writer.close();
552
 
 
553
 
    // test whether the changes made it to the directory
554
 
    writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
555
 
    IndexReader w2r1 = writer.getReader();
556
 
    // insure the deletes were actually flushed to the directory
557
 
    assertEquals(200, w2r1.maxDoc());
558
 
    w2r1.close();
559
 
    writer.close();
560
 
 
561
 
    dir1.close();
562
 
  }
563
 
 
564
 
  /*
565
 
   * Delete a document by term and return the doc id
566
 
   * 
567
 
   * public static int deleteDocument(Term term, IndexWriter writer) throws
568
 
   * IOException { IndexReader reader = writer.getReader(); TermDocs td =
569
 
   * reader.termDocs(term); int doc = -1; //if (td.next()) { // doc = td.doc();
570
 
   * //} //writer.deleteDocuments(term); td.close(); return doc; }
571
 
   */
572
 
  
573
 
  public static void createIndex(Random random, Directory dir1, String indexName,
574
 
      boolean multiSegment) throws IOException {
575
 
    IndexWriter w = new IndexWriter(dir1, LuceneTestCase.newIndexWriterConfig(random,
576
 
        TEST_VERSION_CURRENT, new MockAnalyzer(random))
577
 
        .setMergePolicy(new LogDocMergePolicy()));
578
 
    for (int i = 0; i < 100; i++) {
579
 
      w.addDocument(DocHelper.createDocument(i, indexName, 4));
580
 
      if (multiSegment && (i % 10) == 0) {
581
 
      }
582
 
    }
583
 
    if (!multiSegment) {
584
 
      w.forceMerge(1);
585
 
    }
586
 
    w.close();
587
 
  }
588
 
 
589
 
  public static void createIndexNoClose(boolean multiSegment, String indexName,
590
 
      IndexWriter w) throws IOException {
591
 
    for (int i = 0; i < 100; i++) {
592
 
      w.addDocument(DocHelper.createDocument(i, indexName, 4));
593
 
    }
594
 
    if (!multiSegment) {
595
 
      w.forceMerge(1);
596
 
    }
597
 
  }
598
 
 
599
 
  private static class MyWarmer extends IndexWriter.IndexReaderWarmer {
600
 
    int warmCount;
601
 
    @Override
602
 
    public void warm(IndexReader reader) throws IOException {
603
 
      warmCount++;
604
 
    }
605
 
  }
606
 
 
607
 
  public void testMergeWarmer() throws Exception {
608
 
 
609
 
    Directory dir1 = newDirectory();
610
 
    // Enroll warmer
611
 
    MyWarmer warmer = new MyWarmer();
612
 
    IndexWriter writer = new IndexWriter(
613
 
        dir1,
614
 
        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
615
 
            setMaxBufferedDocs(2).
616
 
            setMergedSegmentWarmer(warmer).
617
 
            setMergeScheduler(new ConcurrentMergeScheduler()).
618
 
            setMergePolicy(newLogMergePolicy())
619
 
    );
620
 
    writer.setInfoStream(infoStream);
621
 
 
622
 
    // create the index
623
 
    createIndexNoClose(false, "test", writer);
624
 
 
625
 
    // get a reader to put writer into near real-time mode
626
 
    IndexReader r1 = writer.getReader();
627
 
    
628
 
    ((LogMergePolicy) writer.getConfig().getMergePolicy()).setMergeFactor(2);
629
 
 
630
 
    int num = atLeast(100);
631
 
    for (int i = 0; i < num; i++) {
632
 
      writer.addDocument(DocHelper.createDocument(i, "test", 4));
633
 
    }
634
 
    ((ConcurrentMergeScheduler) writer.getConfig().getMergeScheduler()).sync();
635
 
 
636
 
    assertTrue(warmer.warmCount > 0);
637
 
    final int count = warmer.warmCount;
638
 
 
639
 
    writer.addDocument(DocHelper.createDocument(17, "test", 4));
640
 
    writer.forceMerge(1);
641
 
    assertTrue(warmer.warmCount > count);
642
 
    
643
 
    writer.close();
644
 
    r1.close();
645
 
    dir1.close();
646
 
  }
647
 
 
648
 
  public void testAfterCommit() throws Exception {
649
 
    Directory dir1 = newDirectory();
650
 
    IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergeScheduler(new ConcurrentMergeScheduler()));
651
 
    writer.commit();
652
 
    writer.setInfoStream(infoStream);
653
 
 
654
 
    // create the index
655
 
    createIndexNoClose(false, "test", writer);
656
 
 
657
 
    // get a reader to put writer into near real-time mode
658
 
    IndexReader r1 = writer.getReader();
659
 
    _TestUtil.checkIndex(dir1);
660
 
    writer.commit();
661
 
    _TestUtil.checkIndex(dir1);
662
 
    assertEquals(100, r1.numDocs());
663
 
 
664
 
    for (int i = 0; i < 10; i++) {
665
 
      writer.addDocument(DocHelper.createDocument(i, "test", 4));
666
 
    }
667
 
    ((ConcurrentMergeScheduler) writer.getConfig().getMergeScheduler()).sync();
668
 
 
669
 
    IndexReader r2 = IndexReader.openIfChanged(r1);
670
 
    if (r2 != null) {
671
 
      r1.close();
672
 
      r1 = r2;
673
 
    }
674
 
    assertEquals(110, r1.numDocs());
675
 
    writer.close();
676
 
    r1.close();
677
 
    dir1.close();
678
 
  }
679
 
 
680
 
  // Make sure reader remains usable even if IndexWriter closes
681
 
  public void testAfterClose() throws Exception {
682
 
    Directory dir1 = newDirectory();
683
 
    IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
684
 
    writer.setInfoStream(infoStream);
685
 
 
686
 
    // create the index
687
 
    createIndexNoClose(false, "test", writer);
688
 
 
689
 
    IndexReader r = writer.getReader();
690
 
    writer.close();
691
 
 
692
 
    _TestUtil.checkIndex(dir1);
693
 
 
694
 
    // reader should remain usable even after IndexWriter is closed:
695
 
    assertEquals(100, r.numDocs());
696
 
    Query q = new TermQuery(new Term("indexname", "test"));
697
 
    IndexSearcher searcher = newSearcher(r);
698
 
    assertEquals(100, searcher.search(q, 10).totalHits);
699
 
    searcher.close();
700
 
    try {
701
 
      IndexReader.openIfChanged(r);
702
 
      fail("failed to hit AlreadyClosedException");
703
 
    } catch (AlreadyClosedException ace) {
704
 
      // expected
705
 
    }
706
 
    r.close();
707
 
    dir1.close();
708
 
  }
709
 
 
710
 
  // Stress test reopen during addIndexes
711
 
  public void testDuringAddIndexes() throws Exception {
712
 
    MockDirectoryWrapper dir1 = newDirectory();
713
 
    final IndexWriter writer = new IndexWriter(
714
 
        dir1,
715
 
        newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).
716
 
            setMergePolicy(newLogMergePolicy(2))
717
 
    );
718
 
    writer.setInfoStream(infoStream);
719
 
    ((LogMergePolicy) writer.getConfig().getMergePolicy()).setMergeFactor(2);
720
 
 
721
 
    // create the index
722
 
    createIndexNoClose(false, "test", writer);
723
 
    writer.commit();
724
 
 
725
 
    final Directory[] dirs = new Directory[10];
726
 
    for (int i=0;i<10;i++) {
727
 
      dirs[i] = new MockDirectoryWrapper(random, new RAMDirectory(dir1));
728
 
    }
729
 
 
730
 
    IndexReader r = writer.getReader();
731
 
 
732
 
    final int NUM_THREAD = 5;
733
 
    final float SECONDS = 0.5f;
734
 
 
735
 
    final long endTime = (long) (System.currentTimeMillis() + 1000.*SECONDS);
736
 
    final List<Throwable> excs = Collections.synchronizedList(new ArrayList<Throwable>());
737
 
 
738
 
    final Thread[] threads = new Thread[NUM_THREAD];
739
 
    for(int i=0;i<NUM_THREAD;i++) {
740
 
      threads[i] = new Thread() {
741
 
          @Override
742
 
          public void run() {
743
 
            do {
744
 
              try {
745
 
                writer.addIndexes(dirs);
746
 
                writer.maybeMerge();
747
 
              } catch (Throwable t) {
748
 
                excs.add(t);
749
 
                throw new RuntimeException(t);
750
 
              }
751
 
            } while(System.currentTimeMillis() < endTime);
752
 
          }
753
 
        };
754
 
      threads[i].setDaemon(true);
755
 
      threads[i].start();
756
 
    }
757
 
 
758
 
    int lastCount = 0;
759
 
    while(System.currentTimeMillis() < endTime) {
760
 
      IndexReader r2 = IndexReader.openIfChanged(r);
761
 
      if (r2 != null) {
762
 
        r.close();
763
 
        r = r2;
764
 
      }
765
 
      Query q = new TermQuery(new Term("indexname", "test"));
766
 
      IndexSearcher searcher = newSearcher(r);
767
 
      final int count = searcher.search(q, 10).totalHits;
768
 
      searcher.close();
769
 
      assertTrue(count >= lastCount);
770
 
      lastCount = count;
771
 
    }
772
 
 
773
 
    for(int i=0;i<NUM_THREAD;i++) {
774
 
      threads[i].join();
775
 
    }
776
 
    // final check
777
 
    IndexReader r2 = IndexReader.openIfChanged(r);
778
 
    if (r2 != null) {
779
 
      r.close();
780
 
      r = r2;
781
 
    }
782
 
    Query q = new TermQuery(new Term("indexname", "test"));
783
 
    IndexSearcher searcher = newSearcher(r);
784
 
    final int count = searcher.search(q, 10).totalHits;
785
 
    searcher.close();
786
 
    assertTrue(count >= lastCount);
787
 
 
788
 
    assertEquals(0, excs.size());
789
 
    r.close();
790
 
    assertEquals(0, dir1.getOpenDeletedFiles().size());
791
 
 
792
 
    writer.close();
793
 
 
794
 
    dir1.close();
795
 
  }
796
 
 
797
 
  // Stress test reopen during add/delete
798
 
  public void testDuringAddDelete() throws Exception {
799
 
    Directory dir1 = newDirectory();
800
 
    final IndexWriter writer = new IndexWriter(
801
 
        dir1,
802
 
        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
803
 
            setMergePolicy(newLogMergePolicy(2))
804
 
    );
805
 
    writer.setInfoStream(infoStream);
806
 
    ((LogMergePolicy) writer.getConfig().getMergePolicy()).setMergeFactor(2);
807
 
 
808
 
    // create the index
809
 
    createIndexNoClose(false, "test", writer);
810
 
    writer.commit();
811
 
 
812
 
    IndexReader r = writer.getReader();
813
 
 
814
 
    final int NUM_THREAD = 5;
815
 
    final float SECONDS = 0.5f;
816
 
 
817
 
    final long endTime = (long) (System.currentTimeMillis() + 1000.*SECONDS);
818
 
    final List<Throwable> excs = Collections.synchronizedList(new ArrayList<Throwable>());
819
 
 
820
 
    final Thread[] threads = new Thread[NUM_THREAD];
821
 
    for(int i=0;i<NUM_THREAD;i++) {
822
 
      threads[i] = new Thread() {
823
 
          final Random r = new Random(random.nextLong());
824
 
 
825
 
          @Override
826
 
          public void run() {
827
 
            int count = 0;
828
 
            do {
829
 
              try {
830
 
                for(int docUpto=0;docUpto<10;docUpto++) {
831
 
                  writer.addDocument(DocHelper.createDocument(10*count+docUpto, "test", 4));
832
 
                }
833
 
                count++;
834
 
                final int limit = count*10;
835
 
                for(int delUpto=0;delUpto<5;delUpto++) {
836
 
                  int x = r.nextInt(limit);
837
 
                  writer.deleteDocuments(new Term("field3", "b"+x));
838
 
                }
839
 
              } catch (Throwable t) {
840
 
                excs.add(t);
841
 
                throw new RuntimeException(t);
842
 
              }
843
 
            } while(System.currentTimeMillis() < endTime);
844
 
          }
845
 
        };
846
 
      threads[i].setDaemon(true);
847
 
      threads[i].start();
848
 
    }
849
 
 
850
 
    int sum = 0;
851
 
    while(System.currentTimeMillis() < endTime) {
852
 
      IndexReader r2 = IndexReader.openIfChanged(r);
853
 
      if (r2 != null) {
854
 
        r.close();
855
 
        r = r2;
856
 
      }
857
 
      Query q = new TermQuery(new Term("indexname", "test"));
858
 
      IndexSearcher searcher = newSearcher(r);
859
 
      sum += searcher.search(q, 10).totalHits;
860
 
      searcher.close();
861
 
    }
862
 
 
863
 
    for(int i=0;i<NUM_THREAD;i++) {
864
 
      threads[i].join();
865
 
    }
866
 
    // at least search once
867
 
    IndexReader r2 = IndexReader.openIfChanged(r);
868
 
    if (r2 != null) {
869
 
      r.close();
870
 
      r = r2;
871
 
    }
872
 
    Query q = new TermQuery(new Term("indexname", "test"));
873
 
    IndexSearcher searcher = newSearcher(r);
874
 
    sum += searcher.search(q, 10).totalHits;
875
 
    searcher.close();
876
 
    assertTrue("no documents found at all", sum > 0);
877
 
 
878
 
    assertEquals(0, excs.size());
879
 
    writer.close();
880
 
 
881
 
    r.close();
882
 
    dir1.close();
883
 
  }
884
 
 
885
 
  public void testForceMergeDeletes() throws Throwable {
886
 
    Directory dir = newDirectory();
887
 
    final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
888
 
    Document doc = new Document();
889
 
    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
890
 
    Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
891
 
    doc.add(id);
892
 
    id.setValue("0");
893
 
    w.addDocument(doc);
894
 
    id.setValue("1");
895
 
    w.addDocument(doc);
896
 
    w.deleteDocuments(new Term("id", "0"));
897
 
 
898
 
    IndexReader r = w.getReader();
899
 
    w.forceMergeDeletes();
900
 
    w.close();
901
 
    r.close();
902
 
    r = IndexReader.open(dir, true);
903
 
    assertEquals(1, r.numDocs());
904
 
    assertFalse(r.hasDeletions());
905
 
    r.close();
906
 
    dir.close();
907
 
  }
908
 
 
909
 
  public void testDeletesNumDocs() throws Throwable {
910
 
    Directory dir = newDirectory();
911
 
    final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
912
 
    Document doc = new Document();
913
 
    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
914
 
    Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
915
 
    doc.add(id);
916
 
    id.setValue("0");
917
 
    w.addDocument(doc);
918
 
    id.setValue("1");
919
 
    w.addDocument(doc);
920
 
    IndexReader r = w.getReader();
921
 
    assertEquals(2, r.numDocs());
922
 
    r.close();
923
 
 
924
 
    w.deleteDocuments(new Term("id", "0"));
925
 
    r = w.getReader();
926
 
    assertEquals(1, r.numDocs());
927
 
    r.close();
928
 
 
929
 
    w.deleteDocuments(new Term("id", "1"));
930
 
    r = w.getReader();
931
 
    assertEquals(0, r.numDocs());
932
 
    r.close();
933
 
 
934
 
    w.close();
935
 
    dir.close();
936
 
  }
937
 
  
938
 
  public void testEmptyIndex() throws Exception {
939
 
    // Ensures that getReader works on an empty index, which hasn't been committed yet.
940
 
    Directory dir = newDirectory();
941
 
    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
942
 
    IndexReader r = w.getReader();
943
 
    assertEquals(0, r.numDocs());
944
 
    r.close();
945
 
    w.close();
946
 
    dir.close();
947
 
  }
948
 
 
949
 
  public void testSegmentWarmer() throws Exception {
950
 
    Directory dir = newDirectory();
951
 
    final AtomicBoolean didWarm = new AtomicBoolean();
952
 
    IndexWriter w = new IndexWriter(
953
 
        dir,
954
 
        newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).
955
 
            setMaxBufferedDocs(2).
956
 
            setReaderPooling(true).
957
 
            setMergedSegmentWarmer(new IndexWriter.IndexReaderWarmer() {
958
 
              @Override
959
 
              public void warm(IndexReader r) throws IOException {
960
 
                IndexSearcher s = newSearcher(r);
961
 
                TopDocs hits = s.search(new TermQuery(new Term("foo", "bar")), 10);
962
 
                assertEquals(20, hits.totalHits);
963
 
                didWarm.set(true);
964
 
                s.close();
965
 
              }
966
 
            }).
967
 
            setMergePolicy(newLogMergePolicy(10))
968
 
    );
969
 
 
970
 
    Document doc = new Document();
971
 
    doc.add(newField("foo", "bar", Field.Store.YES, Field.Index.NOT_ANALYZED));
972
 
    for(int i=0;i<20;i++) {
973
 
      w.addDocument(doc);
974
 
    }
975
 
    w.waitForMerges();
976
 
    w.close();
977
 
    dir.close();
978
 
    assertTrue(didWarm.get());
979
 
  }
980
 
  
981
 
  public void testNoTermsIndex() throws Exception {
982
 
    Directory dir = newDirectory();
983
 
    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
984
 
        TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT))
985
 
        .setReaderTermsIndexDivisor(-1));
986
 
    Document doc = new Document();
987
 
    doc.add(new Field("f", "val", Store.NO, Index.ANALYZED));
988
 
    w.addDocument(doc);
989
 
    IndexReader r = IndexReader.open(w, true);
990
 
    try {
991
 
      r.termDocs(new Term("f", "val"));
992
 
      fail("should have failed to seek since terms index was not loaded");
993
 
    } catch (IllegalStateException e) {
994
 
      // expected - we didn't load the term index
995
 
    } finally {
996
 
      r.close();
997
 
      w.close();
998
 
      dir.close();
999
 
    }
1000
 
  }
1001
 
  
1002
 
  public void testReopenAfterNoRealChange() throws Exception {
1003
 
    Directory d = newDirectory();
1004
 
    IndexWriter w = new IndexWriter(
1005
 
        d,
1006
 
        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
1007
 
    w.setInfoStream(VERBOSE ? System.out : null);
1008
 
 
1009
 
    IndexReader r = w.getReader(); // start pooling readers
1010
 
 
1011
 
    IndexReader r2 = IndexReader.openIfChanged(r);
1012
 
    assertNull(r2);
1013
 
    
1014
 
    w.addDocument(new Document());
1015
 
    IndexReader r3 = IndexReader.openIfChanged(r);
1016
 
    assertNotNull(r3);
1017
 
    assertTrue(r3.getVersion() != r.getVersion());
1018
 
    assertTrue(r3.isCurrent());
1019
 
 
1020
 
    // Deletes nothing in reality...:
1021
 
    w.deleteDocuments(new Term("foo", "bar"));
1022
 
 
1023
 
    // ... but IW marks this as not current:
1024
 
    assertFalse(r3.isCurrent());
1025
 
    IndexReader r4 = IndexReader.openIfChanged(r3);
1026
 
    assertNull(r4);
1027
 
 
1028
 
    // Deletes nothing in reality...:
1029
 
    w.deleteDocuments(new Term("foo", "bar"));
1030
 
    IndexReader r5 = IndexReader.openIfChanged(r3, w, true);
1031
 
    assertNull(r5);
1032
 
 
1033
 
    r3.close();
1034
 
 
1035
 
    w.close();
1036
 
    d.close();
1037
 
  }
1038
 
}