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

« back to all changes in this revision

Viewing changes to lucene/backwards/src/test/org/apache/lucene/index/TestIndexReaderReopen.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
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
5
 
 * contributor license agreements.  See the NOTICE file distributed with
6
 
 * this work for additional information regarding copyright ownership.
7
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
8
 
 * (the "License"); you may not use this file except in compliance with
9
 
 * the License.  You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
import java.io.File;
21
 
import java.io.IOException;
22
 
import java.util.ArrayList;
23
 
import java.util.Collection;
24
 
import java.util.Collections;
25
 
import java.util.HashMap;
26
 
import java.util.HashSet;
27
 
import java.util.List;
28
 
import java.util.Map;
29
 
import java.util.Random;
30
 
import java.util.Set;
31
 
 
32
 
import org.apache.lucene.analysis.MockAnalyzer;
33
 
import org.apache.lucene.document.Document;
34
 
import org.apache.lucene.document.Field.Index;
35
 
import org.apache.lucene.document.Field.Store;
36
 
import org.apache.lucene.document.Field;
37
 
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
38
 
import org.apache.lucene.search.FieldCache;
39
 
import org.apache.lucene.search.IndexSearcher;
40
 
import org.apache.lucene.search.ScoreDoc;
41
 
import org.apache.lucene.search.TermQuery;
42
 
import org.apache.lucene.store.AlreadyClosedException;
43
 
import org.apache.lucene.store.Directory;
44
 
import org.apache.lucene.util.BitVector;
45
 
import org.apache.lucene.util.LuceneTestCase;
46
 
import org.apache.lucene.util._TestUtil;
47
 
 
48
 
public class TestIndexReaderReopen extends LuceneTestCase {
49
 
  
50
 
  public void testReopen() throws Exception {
51
 
    final Directory dir1 = newDirectory();
52
 
    
53
 
    createIndex(random, dir1, false);
54
 
    performDefaultTests(new TestReopen() {
55
 
 
56
 
      @Override
57
 
      protected void modifyIndex(int i) throws IOException {
58
 
        TestIndexReaderReopen.modifyIndex(i, dir1);
59
 
      }
60
 
 
61
 
      @Override
62
 
      protected IndexReader openReader() throws IOException {
63
 
        return IndexReader.open(dir1, false);
64
 
      }
65
 
      
66
 
    });
67
 
    dir1.close();
68
 
    
69
 
    final Directory dir2 = newDirectory();
70
 
    
71
 
    createIndex(random, dir2, true);
72
 
    performDefaultTests(new TestReopen() {
73
 
 
74
 
      @Override
75
 
      protected void modifyIndex(int i) throws IOException {
76
 
        TestIndexReaderReopen.modifyIndex(i, dir2);
77
 
      }
78
 
 
79
 
      @Override
80
 
      protected IndexReader openReader() throws IOException {
81
 
        return IndexReader.open(dir2, false);
82
 
      }
83
 
      
84
 
    });
85
 
    dir2.close();
86
 
  }
87
 
  
88
 
  public void testParallelReaderReopen() throws Exception {
89
 
    final Directory dir1 = newDirectory();
90
 
    createIndex(random, dir1, true);
91
 
    final Directory dir2 = newDirectory();
92
 
    createIndex(random, dir2, true);
93
 
    
94
 
    performDefaultTests(new TestReopen() {
95
 
 
96
 
      @Override
97
 
      protected void modifyIndex(int i) throws IOException {
98
 
        TestIndexReaderReopen.modifyIndex(i, dir1);
99
 
        TestIndexReaderReopen.modifyIndex(i, dir2);
100
 
      }
101
 
 
102
 
      @Override
103
 
      protected IndexReader openReader() throws IOException {
104
 
        ParallelReader pr = new ParallelReader();
105
 
        pr.add(IndexReader.open(dir1, false));
106
 
        pr.add(IndexReader.open(dir2, false));
107
 
        return pr;
108
 
      }
109
 
      
110
 
    });
111
 
    dir1.close();
112
 
    dir2.close();
113
 
    
114
 
    final Directory dir3 = newDirectory();
115
 
    createIndex(random, dir3, true);
116
 
    final Directory dir4 = newDirectory();
117
 
    createIndex(random, dir4, true);
118
 
 
119
 
    performTestsWithExceptionInReopen(new TestReopen() {
120
 
 
121
 
      @Override
122
 
      protected void modifyIndex(int i) throws IOException {
123
 
        TestIndexReaderReopen.modifyIndex(i, dir3);
124
 
        TestIndexReaderReopen.modifyIndex(i, dir4);
125
 
      }
126
 
 
127
 
      @Override
128
 
      protected IndexReader openReader() throws IOException {
129
 
        ParallelReader pr = new ParallelReader();
130
 
        pr.add(IndexReader.open(dir3, false));
131
 
        pr.add(IndexReader.open(dir4, false));
132
 
        // Does not implement reopen, so
133
 
        // hits exception:
134
 
        pr.add(new FilterIndexReader(IndexReader.open(dir3, false)));
135
 
        return pr;
136
 
      }
137
 
      
138
 
    });
139
 
    dir3.close();
140
 
    dir4.close();
141
 
  }
142
 
 
143
 
  // LUCENE-1228: IndexWriter.commit() does not update the index version
144
 
  // populate an index in iterations.
145
 
  // at the end of every iteration, commit the index and reopen/recreate the reader.
146
 
  // in each iteration verify the work of previous iteration. 
147
 
  // try this once with reopen once recreate, on both RAMDir and FSDir.
148
 
  public void testCommitReopen () throws IOException {
149
 
    Directory dir = newDirectory();
150
 
    doTestReopenWithCommit(random, dir, true);
151
 
    dir.close();
152
 
  }
153
 
  public void testCommitRecreate () throws IOException {
154
 
    Directory dir = newDirectory();
155
 
    doTestReopenWithCommit(random, dir, false);
156
 
    dir.close();
157
 
  }
158
 
 
159
 
  private void doTestReopenWithCommit (Random random, Directory dir, boolean withReopen) throws IOException {
160
 
    IndexWriter iwriter = new IndexWriter(dir, newIndexWriterConfig(
161
 
        TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(
162
 
                                                              OpenMode.CREATE).setMergeScheduler(new SerialMergeScheduler()).setMergePolicy(newLogMergePolicy()));
163
 
    iwriter.commit();
164
 
    IndexReader reader = IndexReader.open(dir, false);
165
 
    try {
166
 
      int M = 3;
167
 
      for (int i=0; i<4; i++) {
168
 
        for (int j=0; j<M; j++) {
169
 
          Document doc = new Document();
170
 
          doc.add(newField("id", i+"_"+j, Store.YES, Index.NOT_ANALYZED));
171
 
          doc.add(newField("id2", i+"_"+j, Store.YES, Index.NOT_ANALYZED_NO_NORMS));
172
 
          doc.add(newField("id3", i+"_"+j, Store.YES, Index.NO));
173
 
          iwriter.addDocument(doc);
174
 
          if (i>0) {
175
 
            int k = i-1;
176
 
            int n = j + k*M;
177
 
            Document prevItereationDoc = reader.document(n);
178
 
            assertNotNull(prevItereationDoc);
179
 
            String id = prevItereationDoc.get("id");
180
 
            assertEquals(k+"_"+j, id);
181
 
          }
182
 
        }
183
 
        iwriter.commit();
184
 
        if (withReopen) {
185
 
          // reopen
186
 
          IndexReader r2 = reader.reopen();
187
 
          if (reader != r2) {
188
 
            reader.close();
189
 
            reader = r2;
190
 
          }
191
 
        } else {
192
 
          // recreate
193
 
          reader.close();
194
 
          reader = IndexReader.open(dir, false);
195
 
        }
196
 
      }
197
 
    } finally {
198
 
      iwriter.close();
199
 
      reader.close();
200
 
    }
201
 
  }
202
 
  
203
 
  public void testMultiReaderReopen() throws Exception {
204
 
    final Directory dir1 = newDirectory();
205
 
    createIndex(random, dir1, true);
206
 
 
207
 
    final Directory dir2 = newDirectory();
208
 
    createIndex(random, dir2, true);
209
 
 
210
 
    performDefaultTests(new TestReopen() {
211
 
 
212
 
      @Override
213
 
      protected void modifyIndex(int i) throws IOException {
214
 
        TestIndexReaderReopen.modifyIndex(i, dir1);
215
 
        TestIndexReaderReopen.modifyIndex(i, dir2);
216
 
      }
217
 
 
218
 
      @Override
219
 
      protected IndexReader openReader() throws IOException {
220
 
        return new MultiReader(new IndexReader[] 
221
 
                        {IndexReader.open(dir1, false), 
222
 
                         IndexReader.open(dir2, false)});
223
 
      }
224
 
      
225
 
    });
226
 
 
227
 
    dir1.close();
228
 
    dir2.close();
229
 
    
230
 
    final Directory dir3 = newDirectory();
231
 
    createIndex(random, dir3, true);
232
 
 
233
 
    final Directory dir4 = newDirectory();
234
 
    createIndex(random, dir4, true);
235
 
 
236
 
    performTestsWithExceptionInReopen(new TestReopen() {
237
 
 
238
 
      @Override
239
 
      protected void modifyIndex(int i) throws IOException {
240
 
        TestIndexReaderReopen.modifyIndex(i, dir3);
241
 
        TestIndexReaderReopen.modifyIndex(i, dir4);
242
 
      }
243
 
 
244
 
      @Override
245
 
      protected IndexReader openReader() throws IOException {
246
 
        return new MultiReader(new IndexReader[] 
247
 
                        {IndexReader.open(dir3, false), 
248
 
                         IndexReader.open(dir4, false),
249
 
                         // Does not implement reopen, so
250
 
                         // hits exception:
251
 
                         new FilterIndexReader(IndexReader.open(dir3, false))});
252
 
      }
253
 
      
254
 
    });
255
 
    dir3.close();
256
 
    dir4.close();
257
 
  }
258
 
 
259
 
  public void testMixedReaders() throws Exception {
260
 
    final Directory dir1 = newDirectory();
261
 
    createIndex(random, dir1, true);
262
 
    final Directory dir2 = newDirectory();
263
 
    createIndex(random, dir2, true);
264
 
    final Directory dir3 = newDirectory();
265
 
    createIndex(random, dir3, false);
266
 
    final Directory dir4 = newDirectory();
267
 
    createIndex(random, dir4, true);
268
 
    final Directory dir5 = newDirectory();
269
 
    createIndex(random, dir5, false);
270
 
    
271
 
    performDefaultTests(new TestReopen() {
272
 
 
273
 
      @Override
274
 
      protected void modifyIndex(int i) throws IOException {
275
 
        // only change norms in this index to maintain the same number of docs for each of ParallelReader's subreaders
276
 
        if (i == 1) TestIndexReaderReopen.modifyIndex(i, dir1);  
277
 
        
278
 
        TestIndexReaderReopen.modifyIndex(i, dir4);
279
 
        TestIndexReaderReopen.modifyIndex(i, dir5);
280
 
      }
281
 
 
282
 
      @Override
283
 
      protected IndexReader openReader() throws IOException {
284
 
        ParallelReader pr = new ParallelReader();
285
 
        pr.add(IndexReader.open(dir1, false));
286
 
        pr.add(IndexReader.open(dir2, false));
287
 
        MultiReader mr = new MultiReader(new IndexReader[] {
288
 
            IndexReader.open(dir3, false), IndexReader.open(dir4, false)});
289
 
        return new MultiReader(new IndexReader[] {
290
 
           pr, mr, IndexReader.open(dir5, false)});
291
 
      }
292
 
    });
293
 
    dir1.close();
294
 
    dir2.close();
295
 
    dir3.close();
296
 
    dir4.close();
297
 
    dir5.close();
298
 
  }  
299
 
  
300
 
  private void performDefaultTests(TestReopen test) throws Exception {
301
 
 
302
 
    IndexReader index1 = test.openReader();
303
 
    IndexReader index2 = test.openReader();
304
 
        
305
 
    TestIndexReader.assertIndexEquals(index1, index2);
306
 
 
307
 
    // verify that reopen() does not return a new reader instance
308
 
    // in case the index has no changes
309
 
    ReaderCouple couple = refreshReader(index2, false);
310
 
    assertTrue(couple.refreshedReader == index2);
311
 
    
312
 
    couple = refreshReader(index2, test, 0, true);
313
 
    index1.close();
314
 
    index1 = couple.newReader;
315
 
 
316
 
    IndexReader index2_refreshed = couple.refreshedReader;
317
 
    index2.close();
318
 
    
319
 
    // test if refreshed reader and newly opened reader return equal results
320
 
    TestIndexReader.assertIndexEquals(index1, index2_refreshed);
321
 
 
322
 
    index2_refreshed.close();
323
 
    assertReaderClosed(index2, true, true);
324
 
    assertReaderClosed(index2_refreshed, true, true);
325
 
 
326
 
    index2 = test.openReader();
327
 
    
328
 
    for (int i = 1; i < 4; i++) {
329
 
      
330
 
      index1.close();
331
 
      couple = refreshReader(index2, test, i, true);
332
 
      // refresh IndexReader
333
 
      index2.close();
334
 
      
335
 
      index2 = couple.refreshedReader;
336
 
      index1 = couple.newReader;
337
 
      TestIndexReader.assertIndexEquals(index1, index2);
338
 
    }
339
 
    
340
 
    index1.close();
341
 
    index2.close();
342
 
    assertReaderClosed(index1, true, true);
343
 
    assertReaderClosed(index2, true, true);
344
 
  }
345
 
  
346
 
  public void testReferenceCounting() throws IOException {
347
 
    for (int mode = 0; mode < 4; mode++) {
348
 
      Directory dir1 = newDirectory();
349
 
      createIndex(random, dir1, true);
350
 
     
351
 
      IndexReader reader0 = IndexReader.open(dir1, false);
352
 
      assertRefCountEquals(1, reader0);
353
 
 
354
 
      assertTrue(reader0 instanceof DirectoryReader);
355
 
      IndexReader[] subReaders0 = reader0.getSequentialSubReaders();
356
 
      for (int i = 0; i < subReaders0.length; i++) {
357
 
        assertRefCountEquals(1, subReaders0[i]);
358
 
      }
359
 
      
360
 
      // delete first document, so that only one of the subReaders have to be re-opened
361
 
      IndexReader modifier = IndexReader.open(dir1, false);
362
 
      modifier.deleteDocument(0);
363
 
      modifier.close();
364
 
      
365
 
      IndexReader reader1 = refreshReader(reader0, true).refreshedReader;
366
 
      assertTrue(reader1 instanceof DirectoryReader);
367
 
      IndexReader[] subReaders1 = reader1.getSequentialSubReaders();
368
 
      assertEquals(subReaders0.length, subReaders1.length);
369
 
      
370
 
      for (int i = 0; i < subReaders0.length; i++) {
371
 
        if (subReaders0[i] != subReaders1[i]) {
372
 
          assertRefCountEquals(1, subReaders0[i]);
373
 
          assertRefCountEquals(1, subReaders1[i]);
374
 
        } else {
375
 
          assertRefCountEquals(2, subReaders0[i]);
376
 
        }
377
 
      }
378
 
 
379
 
      // delete first document, so that only one of the subReaders have to be re-opened
380
 
      modifier = IndexReader.open(dir1, false);
381
 
      modifier.deleteDocument(1);
382
 
      modifier.close();
383
 
 
384
 
      IndexReader reader2 = refreshReader(reader1, true).refreshedReader;
385
 
      assertTrue(reader2 instanceof DirectoryReader);
386
 
      IndexReader[] subReaders2 = reader2.getSequentialSubReaders();
387
 
      assertEquals(subReaders1.length, subReaders2.length);
388
 
      
389
 
      for (int i = 0; i < subReaders2.length; i++) {
390
 
        if (subReaders2[i] == subReaders1[i]) {
391
 
          if (subReaders1[i] == subReaders0[i]) {
392
 
            assertRefCountEquals(3, subReaders2[i]);
393
 
          } else {
394
 
            assertRefCountEquals(2, subReaders2[i]);
395
 
          }
396
 
        } else {
397
 
          assertRefCountEquals(1, subReaders2[i]);
398
 
          if (subReaders0[i] == subReaders1[i]) {
399
 
            assertRefCountEquals(2, subReaders2[i]);
400
 
            assertRefCountEquals(2, subReaders0[i]);
401
 
          } else {
402
 
            assertRefCountEquals(1, subReaders0[i]);
403
 
            assertRefCountEquals(1, subReaders1[i]);
404
 
          }
405
 
        }
406
 
      }
407
 
      
408
 
      IndexReader reader3 = refreshReader(reader0, true).refreshedReader;
409
 
      assertTrue(reader3 instanceof DirectoryReader);
410
 
      IndexReader[] subReaders3 = reader3.getSequentialSubReaders();
411
 
      assertEquals(subReaders3.length, subReaders0.length);
412
 
      
413
 
      // try some permutations
414
 
      switch (mode) {
415
 
      case 0:
416
 
        reader0.close();
417
 
        reader1.close();
418
 
        reader2.close();
419
 
        reader3.close();
420
 
        break;
421
 
      case 1:
422
 
        reader3.close();
423
 
        reader2.close();
424
 
        reader1.close();
425
 
        reader0.close();
426
 
        break;
427
 
      case 2:
428
 
        reader2.close();
429
 
        reader3.close();
430
 
        reader0.close();
431
 
        reader1.close();
432
 
        break;
433
 
      case 3:
434
 
        reader1.close();
435
 
        reader3.close();
436
 
        reader2.close();
437
 
        reader0.close();
438
 
        break;
439
 
      }      
440
 
      
441
 
      assertReaderClosed(reader0, true, true);
442
 
      assertReaderClosed(reader1, true, true);
443
 
      assertReaderClosed(reader2, true, true);
444
 
      assertReaderClosed(reader3, true, true);
445
 
 
446
 
      dir1.close();
447
 
    }
448
 
  }
449
 
 
450
 
 
451
 
  public void testReferenceCountingMultiReader() throws IOException {
452
 
    for (int mode = 0; mode <=1; mode++) {
453
 
      Directory dir1 = newDirectory();
454
 
      createIndex(random, dir1, false);
455
 
      Directory dir2 = newDirectory();
456
 
      createIndex(random, dir2, true);
457
 
      
458
 
      IndexReader reader1 = IndexReader.open(dir1, false);
459
 
      assertRefCountEquals(1, reader1);
460
 
 
461
 
      IndexReader initReader2 = IndexReader.open(dir2, false);
462
 
      IndexReader multiReader1 = new MultiReader(new IndexReader[] {reader1, initReader2}, (mode == 0));
463
 
      modifyIndex(0, dir2);
464
 
      assertRefCountEquals(1 + mode, reader1);
465
 
      
466
 
      IndexReader multiReader2 = multiReader1.reopen();
467
 
      // index1 hasn't changed, so multiReader2 should share reader1 now with multiReader1
468
 
      assertRefCountEquals(2 + mode, reader1);
469
 
      
470
 
      modifyIndex(0, dir1);
471
 
      IndexReader reader2 = reader1.reopen();
472
 
      assertRefCountEquals(2 + mode, reader1);
473
 
 
474
 
      if (mode == 1) {
475
 
        initReader2.close();
476
 
      }
477
 
      
478
 
      modifyIndex(1, dir1);
479
 
      IndexReader reader3 = reader2.reopen();
480
 
      assertRefCountEquals(2 + mode, reader1);
481
 
      assertRefCountEquals(1, reader2);
482
 
      
483
 
      multiReader1.close();
484
 
      assertRefCountEquals(1 + mode, reader1);
485
 
      
486
 
      multiReader1.close();
487
 
      assertRefCountEquals(1 + mode, reader1);
488
 
 
489
 
      if (mode == 1) {
490
 
        initReader2.close();
491
 
      }
492
 
      
493
 
      reader1.close();
494
 
      assertRefCountEquals(1, reader1);
495
 
      
496
 
      multiReader2.close();
497
 
      assertRefCountEquals(0, reader1);
498
 
      
499
 
      multiReader2.close();
500
 
      assertRefCountEquals(0, reader1);
501
 
      
502
 
      reader3.close();
503
 
      assertRefCountEquals(0, reader1);
504
 
      assertReaderClosed(reader1, true, false);
505
 
      
506
 
      reader2.close();
507
 
      assertRefCountEquals(0, reader1);
508
 
      assertReaderClosed(reader1, true, false);
509
 
      
510
 
      reader2.close();
511
 
      assertRefCountEquals(0, reader1);
512
 
      
513
 
      reader3.close();
514
 
      assertRefCountEquals(0, reader1);
515
 
      assertReaderClosed(reader1, true, true);
516
 
      dir1.close();
517
 
      dir2.close();
518
 
    }
519
 
 
520
 
  }
521
 
 
522
 
  public void testReferenceCountingParallelReader() throws IOException {
523
 
    for (int mode = 0; mode <=1; mode++) {
524
 
      Directory dir1 = newDirectory();
525
 
      createIndex(random, dir1, false);
526
 
      Directory dir2 = newDirectory();
527
 
      createIndex(random, dir2, true);
528
 
      
529
 
      IndexReader reader1 = IndexReader.open(dir1, false);
530
 
      assertRefCountEquals(1, reader1);
531
 
      
532
 
      ParallelReader parallelReader1 = new ParallelReader(mode == 0);
533
 
      parallelReader1.add(reader1);
534
 
      IndexReader initReader2 = IndexReader.open(dir2, false);
535
 
      parallelReader1.add(initReader2);
536
 
      modifyIndex(1, dir2);
537
 
      assertRefCountEquals(1 + mode, reader1);
538
 
      
539
 
      IndexReader parallelReader2 = parallelReader1.reopen();
540
 
      // index1 hasn't changed, so parallelReader2 should share reader1 now with multiReader1
541
 
      assertRefCountEquals(2 + mode, reader1);
542
 
      
543
 
      modifyIndex(0, dir1);
544
 
      modifyIndex(0, dir2);
545
 
      IndexReader reader2 = reader1.reopen();
546
 
      assertRefCountEquals(2 + mode, reader1);
547
 
 
548
 
      if (mode == 1) {
549
 
        initReader2.close();
550
 
      }
551
 
      
552
 
      modifyIndex(4, dir1);
553
 
      IndexReader reader3 = reader2.reopen();
554
 
      assertRefCountEquals(2 + mode, reader1);
555
 
      assertRefCountEquals(1, reader2);
556
 
      
557
 
      parallelReader1.close();
558
 
      assertRefCountEquals(1 + mode, reader1);
559
 
      
560
 
      parallelReader1.close();
561
 
      assertRefCountEquals(1 + mode, reader1);
562
 
 
563
 
      if (mode == 1) {
564
 
        initReader2.close();
565
 
      }
566
 
      
567
 
      reader1.close();
568
 
      assertRefCountEquals(1, reader1);
569
 
      
570
 
      parallelReader2.close();
571
 
      assertRefCountEquals(0, reader1);
572
 
      
573
 
      parallelReader2.close();
574
 
      assertRefCountEquals(0, reader1);
575
 
      
576
 
      reader3.close();
577
 
      assertRefCountEquals(0, reader1);
578
 
      assertReaderClosed(reader1, true, false);
579
 
      
580
 
      reader2.close();
581
 
      assertRefCountEquals(0, reader1);
582
 
      assertReaderClosed(reader1, true, false);
583
 
      
584
 
      reader2.close();
585
 
      assertRefCountEquals(0, reader1);
586
 
      
587
 
      reader3.close();
588
 
      assertRefCountEquals(0, reader1);
589
 
      assertReaderClosed(reader1, true, true);
590
 
 
591
 
      dir1.close();
592
 
      dir2.close();
593
 
    }
594
 
 
595
 
  }
596
 
  
597
 
  public void testNormsRefCounting() throws IOException {
598
 
    Directory dir1 = newDirectory();
599
 
    createIndex(random, dir1, false);
600
 
    
601
 
    IndexReader reader1 = IndexReader.open(dir1, false);
602
 
    SegmentReader segmentReader1 = SegmentReader.getOnlySegmentReader(reader1);
603
 
    IndexReader modifier = IndexReader.open(dir1, false);
604
 
    modifier.deleteDocument(0);
605
 
    modifier.close();
606
 
    
607
 
    IndexReader reader2 = reader1.reopen();
608
 
    modifier = IndexReader.open(dir1, false);
609
 
    modifier.setNorm(1, "field1", 50);
610
 
    modifier.setNorm(1, "field2", 50);
611
 
    modifier.close();
612
 
    
613
 
    IndexReader reader3 = reader2.reopen();
614
 
    SegmentReader segmentReader3 = SegmentReader.getOnlySegmentReader(reader3);
615
 
    modifier = IndexReader.open(dir1, false);
616
 
    modifier.deleteDocument(2);
617
 
    modifier.close();
618
 
 
619
 
    IndexReader reader4 = reader3.reopen();
620
 
    modifier = IndexReader.open(dir1, false);
621
 
    modifier.deleteDocument(3);
622
 
    modifier.close();
623
 
 
624
 
    IndexReader reader5 = reader3.reopen();
625
 
    
626
 
    // Now reader2-reader5 references reader1. reader1 and reader2
627
 
    // share the same norms. reader3, reader4, reader5 also share norms.
628
 
    assertRefCountEquals(1, reader1);
629
 
    assertFalse(segmentReader1.normsClosed());
630
 
 
631
 
    reader1.close();
632
 
 
633
 
    assertRefCountEquals(0, reader1);
634
 
    assertFalse(segmentReader1.normsClosed());
635
 
 
636
 
    reader2.close();
637
 
    assertRefCountEquals(0, reader1);
638
 
 
639
 
    // now the norms for field1 and field2 should be closed
640
 
    assertTrue(segmentReader1.normsClosed("field1"));
641
 
    assertTrue(segmentReader1.normsClosed("field2"));
642
 
 
643
 
    // but the norms for field3 and field4 should still be open
644
 
    assertFalse(segmentReader1.normsClosed("field3"));
645
 
    assertFalse(segmentReader1.normsClosed("field4"));
646
 
    
647
 
    reader3.close();
648
 
    assertRefCountEquals(0, reader1);
649
 
    assertFalse(segmentReader3.normsClosed());
650
 
    reader5.close();
651
 
    assertRefCountEquals(0, reader1);
652
 
    assertFalse(segmentReader3.normsClosed());
653
 
    reader4.close();
654
 
    assertRefCountEquals(0, reader1);
655
 
    
656
 
    // and now all norms that reader1 used should be closed
657
 
    assertTrue(segmentReader1.normsClosed());
658
 
    
659
 
    // now that reader3, reader4 and reader5 are closed,
660
 
    // the norms that those three readers shared should be
661
 
    // closed as well
662
 
    assertTrue(segmentReader3.normsClosed());
663
 
 
664
 
    dir1.close();
665
 
  }
666
 
  
667
 
  private void performTestsWithExceptionInReopen(TestReopen test) throws Exception {
668
 
    IndexReader index1 = test.openReader();
669
 
    IndexReader index2 = test.openReader();
670
 
 
671
 
    TestIndexReader.assertIndexEquals(index1, index2);
672
 
    
673
 
    try {
674
 
      refreshReader(index1, test, 0, true);
675
 
      fail("Expected exception not thrown.");
676
 
    } catch (Exception e) {
677
 
      // expected exception
678
 
    }
679
 
    
680
 
    // index2 should still be usable and unaffected by the failed reopen() call
681
 
    TestIndexReader.assertIndexEquals(index1, index2);
682
 
 
683
 
    index1.close();
684
 
    index2.close();
685
 
  }
686
 
  
687
 
  public void testThreadSafety() throws Exception {
688
 
    final Directory dir = newDirectory();
689
 
    // NOTE: this also controls the number of threads!
690
 
    final int n = _TestUtil.nextInt(random, 20, 40);
691
 
    IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
692
 
        TEST_VERSION_CURRENT, new MockAnalyzer(random)));
693
 
    for (int i = 0; i < n; i++) {
694
 
      writer.addDocument(createDocument(i, 3));
695
 
    }
696
 
    writer.optimize();
697
 
    writer.close();
698
 
 
699
 
    final TestReopen test = new TestReopen() {      
700
 
      @Override
701
 
      protected void modifyIndex(int i) throws IOException {
702
 
        if (i % 3 == 0) {
703
 
          IndexReader modifier = IndexReader.open(dir, false);
704
 
          modifier.setNorm(i, "field1", 50);
705
 
          modifier.close();
706
 
        } else if (i % 3 == 1) {
707
 
          IndexReader modifier = IndexReader.open(dir, false);
708
 
          modifier.deleteDocument(i % modifier.maxDoc());
709
 
          modifier.close();
710
 
        } else {
711
 
          IndexWriter modifier = new IndexWriter(dir, new IndexWriterConfig(
712
 
              TEST_VERSION_CURRENT, new MockAnalyzer(random)));
713
 
          modifier.addDocument(createDocument(n + i, 6));
714
 
          modifier.close();
715
 
        }
716
 
      }
717
 
 
718
 
      @Override
719
 
      protected IndexReader openReader() throws IOException {
720
 
        return IndexReader.open(dir, false);
721
 
      }      
722
 
    };
723
 
    
724
 
    final List<ReaderCouple> readers = Collections.synchronizedList(new ArrayList<ReaderCouple>());
725
 
    IndexReader firstReader = IndexReader.open(dir, false);
726
 
    IndexReader reader = firstReader;
727
 
    final Random rnd = random;
728
 
    
729
 
    ReaderThread[] threads = new ReaderThread[n];
730
 
    final Set<IndexReader> readersToClose = Collections.synchronizedSet(new HashSet<IndexReader>());
731
 
    
732
 
    for (int i = 0; i < n; i++) {
733
 
      if (i % 2 == 0) {
734
 
        IndexReader refreshed = reader.reopen();
735
 
        if (refreshed != reader) {
736
 
          readersToClose.add(reader);
737
 
        }
738
 
        reader = refreshed;
739
 
      }
740
 
      final IndexReader r = reader;
741
 
      
742
 
      final int index = i;    
743
 
      
744
 
      ReaderThreadTask task;
745
 
      
746
 
      if (i < 4 || (i >=10 && i < 14) || i > 18) {
747
 
        task = new ReaderThreadTask() {
748
 
          
749
 
          @Override
750
 
          public void run() throws Exception {
751
 
            while (!stopped) {
752
 
              if (index % 2 == 0) {
753
 
                // refresh reader synchronized
754
 
                ReaderCouple c = (refreshReader(r, test, index, true));
755
 
                readersToClose.add(c.newReader);
756
 
                readersToClose.add(c.refreshedReader);
757
 
                readers.add(c);
758
 
                // prevent too many readers
759
 
                break;
760
 
              } else {
761
 
                // not synchronized
762
 
                IndexReader refreshed = r.reopen();
763
 
                
764
 
                IndexSearcher searcher = newSearcher(refreshed);
765
 
                ScoreDoc[] hits = searcher.search(
766
 
                    new TermQuery(new Term("field1", "a" + rnd.nextInt(refreshed.maxDoc()))),
767
 
                    null, 1000).scoreDocs;
768
 
                if (hits.length > 0) {
769
 
                  searcher.doc(hits[0].doc);
770
 
                }
771
 
                searcher.close();
772
 
                if (refreshed != r) {
773
 
                  refreshed.close();
774
 
                }
775
 
              }
776
 
              synchronized(this) {
777
 
                wait(_TestUtil.nextInt(random, 1, 100));
778
 
              }
779
 
            }
780
 
          }
781
 
          
782
 
        };
783
 
      } else {
784
 
        task = new ReaderThreadTask() {
785
 
          @Override
786
 
          public void run() throws Exception {
787
 
            while (!stopped) {
788
 
              int numReaders = readers.size();
789
 
              if (numReaders > 0) {
790
 
                ReaderCouple c =  readers.get(rnd.nextInt(numReaders));
791
 
                TestIndexReader.assertIndexEquals(c.newReader, c.refreshedReader);
792
 
              }
793
 
              
794
 
              synchronized(this) {
795
 
                wait(_TestUtil.nextInt(random, 1, 100));
796
 
              }
797
 
            }
798
 
          }
799
 
        };
800
 
      }
801
 
      
802
 
      threads[i] = new ReaderThread(task);
803
 
      threads[i].start();
804
 
    }
805
 
    
806
 
    synchronized(this) {
807
 
      wait(1000);
808
 
    }
809
 
    
810
 
    for (int i = 0; i < n; i++) {
811
 
      if (threads[i] != null) {
812
 
        threads[i].stopThread();
813
 
      }
814
 
    }
815
 
    
816
 
    for (int i = 0; i < n; i++) {
817
 
      if (threads[i] != null) {
818
 
        threads[i].join();
819
 
        if (threads[i].error != null) {
820
 
          String msg = "Error occurred in thread " + threads[i].getName() + ":\n" + threads[i].error.getMessage();
821
 
          fail(msg);
822
 
        }
823
 
      }
824
 
      
825
 
    }
826
 
    
827
 
    for (final IndexReader readerToClose : readersToClose) {
828
 
      readerToClose.close();
829
 
    }
830
 
    
831
 
    firstReader.close();
832
 
    reader.close();
833
 
    
834
 
    for (final IndexReader readerToClose : readersToClose) {
835
 
      assertReaderClosed(readerToClose, true, true);
836
 
    }
837
 
 
838
 
    assertReaderClosed(reader, true, true);
839
 
    assertReaderClosed(firstReader, true, true);
840
 
 
841
 
    dir.close();
842
 
  }
843
 
  
844
 
  private static class ReaderCouple {
845
 
    ReaderCouple(IndexReader r1, IndexReader r2) {
846
 
      newReader = r1;
847
 
      refreshedReader = r2;
848
 
    }
849
 
    
850
 
    IndexReader newReader;
851
 
    IndexReader refreshedReader;
852
 
  }
853
 
  
854
 
  private abstract static class ReaderThreadTask {
855
 
    protected volatile boolean stopped;
856
 
    public void stop() {
857
 
      this.stopped = true;
858
 
    }
859
 
    
860
 
    public abstract void run() throws Exception;
861
 
  }
862
 
  
863
 
  private static class ReaderThread extends Thread {
864
 
    private ReaderThreadTask task;
865
 
    private Throwable error;
866
 
    
867
 
    
868
 
    ReaderThread(ReaderThreadTask task) {
869
 
      this.task = task;
870
 
    }
871
 
    
872
 
    public void stopThread() {
873
 
      this.task.stop();
874
 
    }
875
 
    
876
 
    @Override
877
 
    public void run() {
878
 
      try {
879
 
        this.task.run();
880
 
      } catch (Throwable r) {
881
 
        r.printStackTrace(System.out);
882
 
        this.error = r;
883
 
      }
884
 
    }
885
 
  }
886
 
  
887
 
  private Object createReaderMutex = new Object();
888
 
  
889
 
  private ReaderCouple refreshReader(IndexReader reader, boolean hasChanges) throws IOException {
890
 
    return refreshReader(reader, null, -1, hasChanges);
891
 
  }
892
 
  
893
 
  ReaderCouple refreshReader(IndexReader reader, TestReopen test, int modify, boolean hasChanges) throws IOException {
894
 
    synchronized (createReaderMutex) {
895
 
      IndexReader r = null;
896
 
      if (test != null) {
897
 
        test.modifyIndex(modify);
898
 
        r = test.openReader();
899
 
      }
900
 
      
901
 
      IndexReader refreshed = null;
902
 
      try {
903
 
        refreshed = reader.reopen();
904
 
      } finally {
905
 
        if (refreshed == null && r != null) {
906
 
          // Hit exception -- close opened reader
907
 
          r.close();
908
 
        }
909
 
      }
910
 
      
911
 
      if (hasChanges) {
912
 
        if (refreshed == reader) {
913
 
          fail("No new IndexReader instance created during refresh.");
914
 
        }
915
 
      } else {
916
 
        if (refreshed != reader) {
917
 
          fail("New IndexReader instance created during refresh even though index had no changes.");
918
 
        }
919
 
      }
920
 
      
921
 
      return new ReaderCouple(r, refreshed);
922
 
    }
923
 
  }
924
 
  
925
 
  public static void createIndex(Random random, Directory dir, boolean multiSegment) throws IOException {
926
 
    IndexWriter.unlock(dir);
927
 
    IndexWriter w = new IndexWriter(dir, LuceneTestCase.newIndexWriterConfig(random,
928
 
        TEST_VERSION_CURRENT, new MockAnalyzer(random))
929
 
        .setMergePolicy(new LogDocMergePolicy()));
930
 
    
931
 
    for (int i = 0; i < 100; i++) {
932
 
      w.addDocument(createDocument(i, 4));
933
 
      if (multiSegment && (i % 10) == 0) {
934
 
        w.commit();
935
 
      }
936
 
    }
937
 
    
938
 
    if (!multiSegment) {
939
 
      w.optimize();
940
 
    }
941
 
    
942
 
    w.close();
943
 
 
944
 
    IndexReader r = IndexReader.open(dir, false);
945
 
    if (multiSegment) {
946
 
      assertTrue(r.getSequentialSubReaders().length > 1);
947
 
    } else {
948
 
      assertTrue(r.getSequentialSubReaders().length == 1);
949
 
    }
950
 
    r.close();
951
 
  }
952
 
 
953
 
  public static Document createDocument(int n, int numFields) {
954
 
    StringBuilder sb = new StringBuilder();
955
 
    Document doc = new Document();
956
 
    sb.append("a");
957
 
    sb.append(n);
958
 
    doc.add(new Field("field1", sb.toString(), Store.YES, Index.ANALYZED));
959
 
    doc.add(new Field("fielda", sb.toString(), Store.YES, Index.NOT_ANALYZED_NO_NORMS));
960
 
    doc.add(new Field("fieldb", sb.toString(), Store.YES, Index.NO));
961
 
    sb.append(" b");
962
 
    sb.append(n);
963
 
    for (int i = 1; i < numFields; i++) {
964
 
      doc.add(new Field("field" + (i+1), sb.toString(), Store.YES, Index.ANALYZED));
965
 
    }
966
 
    return doc;
967
 
  }
968
 
 
969
 
  static void modifyIndex(int i, Directory dir) throws IOException {
970
 
    switch (i) {
971
 
      case 0: {
972
 
        if (VERBOSE) {
973
 
          System.out.println("TEST: modify index");
974
 
        }
975
 
        IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
976
 
        w.setInfoStream(VERBOSE ? System.out : null);
977
 
        w.deleteDocuments(new Term("field2", "a11"));
978
 
        w.deleteDocuments(new Term("field2", "b30"));
979
 
        w.close();
980
 
        break;
981
 
      }
982
 
      case 1: {
983
 
        IndexReader reader = IndexReader.open(dir, false);
984
 
        reader.setNorm(4, "field1", 123);
985
 
        reader.setNorm(44, "field2", 222);
986
 
        reader.setNorm(44, "field4", 22);
987
 
        reader.close();
988
 
        break;
989
 
      }
990
 
      case 2: {
991
 
        IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
992
 
        w.optimize();
993
 
        w.close();
994
 
        break;
995
 
      }
996
 
      case 3: {
997
 
        IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
998
 
        w.addDocument(createDocument(101, 4));
999
 
        w.optimize();
1000
 
        w.addDocument(createDocument(102, 4));
1001
 
        w.addDocument(createDocument(103, 4));
1002
 
        w.close();
1003
 
        break;
1004
 
      }
1005
 
      case 4: {
1006
 
        IndexReader reader = IndexReader.open(dir, false);
1007
 
        reader.setNorm(5, "field1", 123);
1008
 
        reader.setNorm(55, "field2", 222);
1009
 
        reader.close();
1010
 
        break;
1011
 
      }
1012
 
      case 5: {
1013
 
        IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
1014
 
        w.addDocument(createDocument(101, 4));
1015
 
        w.close();
1016
 
        break;
1017
 
      }
1018
 
    }
1019
 
  }  
1020
 
  
1021
 
  private void assertReaderClosed(IndexReader reader, boolean checkSubReaders, boolean checkNormsClosed) {
1022
 
    assertEquals(0, reader.getRefCount());
1023
 
    
1024
 
    if (checkNormsClosed && reader instanceof SegmentReader) {
1025
 
      assertTrue(((SegmentReader) reader).normsClosed());
1026
 
    }
1027
 
    
1028
 
    if (checkSubReaders) {
1029
 
      if (reader instanceof DirectoryReader) {
1030
 
        IndexReader[] subReaders = reader.getSequentialSubReaders();
1031
 
        for (int i = 0; i < subReaders.length; i++) {
1032
 
          assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed);
1033
 
        }
1034
 
      }
1035
 
      
1036
 
      if (reader instanceof MultiReader) {
1037
 
        IndexReader[] subReaders = reader.getSequentialSubReaders();
1038
 
        for (int i = 0; i < subReaders.length; i++) {
1039
 
          assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed);
1040
 
        }
1041
 
      }
1042
 
      
1043
 
      if (reader instanceof ParallelReader) {
1044
 
        IndexReader[] subReaders = ((ParallelReader) reader).getSubReaders();
1045
 
        for (int i = 0; i < subReaders.length; i++) {
1046
 
          assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed);
1047
 
        }
1048
 
      }
1049
 
    }
1050
 
  }
1051
 
 
1052
 
  /*
1053
 
  private void assertReaderOpen(IndexReader reader) {
1054
 
    reader.ensureOpen();
1055
 
    
1056
 
    if (reader instanceof DirectoryReader) {
1057
 
      IndexReader[] subReaders = reader.getSequentialSubReaders();
1058
 
      for (int i = 0; i < subReaders.length; i++) {
1059
 
        assertReaderOpen(subReaders[i]);
1060
 
      }
1061
 
    }
1062
 
  }
1063
 
  */
1064
 
 
1065
 
  private void assertRefCountEquals(int refCount, IndexReader reader) {
1066
 
    assertEquals("Reader has wrong refCount value.", refCount, reader.getRefCount());
1067
 
  }
1068
 
 
1069
 
 
1070
 
  private abstract static class TestReopen {
1071
 
    protected abstract IndexReader openReader() throws IOException;
1072
 
    protected abstract void modifyIndex(int i) throws IOException;
1073
 
  }
1074
 
  
1075
 
  public void testCloseOrig() throws Throwable {
1076
 
    Directory dir = newDirectory();
1077
 
    createIndex(random, dir, false);
1078
 
    IndexReader r1 = IndexReader.open(dir, false);
1079
 
    IndexReader r2 = IndexReader.open(dir, false);
1080
 
    r2.deleteDocument(0);
1081
 
    r2.close();
1082
 
 
1083
 
    IndexReader r3 = r1.reopen();
1084
 
    assertTrue(r1 != r3);
1085
 
    r1.close();
1086
 
    try {
1087
 
      r1.document(2);
1088
 
      fail("did not hit exception");
1089
 
    } catch (AlreadyClosedException ace) {
1090
 
      // expected
1091
 
    }
1092
 
    r3.close();
1093
 
    dir.close();
1094
 
  }
1095
 
 
1096
 
  public void testDeletes() throws Throwable {
1097
 
    Directory dir = newDirectory();
1098
 
    createIndex(random, dir, false); // Create an index with a bunch of docs (1 segment)
1099
 
 
1100
 
    modifyIndex(0, dir); // Get delete bitVector on 1st segment
1101
 
    modifyIndex(5, dir); // Add a doc (2 segments)
1102
 
 
1103
 
    IndexReader r1 = IndexReader.open(dir, false); // MSR
1104
 
 
1105
 
    modifyIndex(5, dir); // Add another doc (3 segments)
1106
 
 
1107
 
    IndexReader r2 = r1.reopen(); // MSR
1108
 
    assertTrue(r1 != r2);
1109
 
 
1110
 
    SegmentReader sr1 = (SegmentReader) r1.getSequentialSubReaders()[0]; // Get SRs for the first segment from original
1111
 
    SegmentReader sr2 = (SegmentReader) r2.getSequentialSubReaders()[0]; // and reopened IRs
1112
 
 
1113
 
    // At this point they share the same BitVector
1114
 
    assertTrue(sr1.deletedDocs==sr2.deletedDocs);
1115
 
 
1116
 
    r2.deleteDocument(0);
1117
 
 
1118
 
    // r1 should not see the delete
1119
 
    assertFalse(r1.isDeleted(0));
1120
 
 
1121
 
    // Now r2 should have made a private copy of deleted docs:
1122
 
    assertTrue(sr1.deletedDocs!=sr2.deletedDocs);
1123
 
 
1124
 
    r1.close();
1125
 
    r2.close();
1126
 
    dir.close();
1127
 
  }
1128
 
 
1129
 
  public void testDeletes2() throws Throwable {
1130
 
    Directory dir = newDirectory();
1131
 
    createIndex(random, dir, false);
1132
 
    // Get delete bitVector
1133
 
    modifyIndex(0, dir);
1134
 
    IndexReader r1 = IndexReader.open(dir, false);
1135
 
 
1136
 
    // Add doc:
1137
 
    modifyIndex(5, dir);
1138
 
 
1139
 
    IndexReader r2 = r1.reopen();
1140
 
    assertTrue(r1 != r2);
1141
 
 
1142
 
    IndexReader[] rs2 = r2.getSequentialSubReaders();
1143
 
 
1144
 
    SegmentReader sr1 = SegmentReader.getOnlySegmentReader(r1);
1145
 
    SegmentReader sr2 = (SegmentReader) rs2[0];
1146
 
 
1147
 
    // At this point they share the same BitVector
1148
 
    assertTrue(sr1.deletedDocs==sr2.deletedDocs);
1149
 
    final BitVector delDocs = sr1.deletedDocs;
1150
 
    r1.close();
1151
 
 
1152
 
    r2.deleteDocument(0);
1153
 
    assertTrue(delDocs==sr2.deletedDocs);
1154
 
    r2.close();
1155
 
    dir.close();
1156
 
  }
1157
 
 
1158
 
  private static class KeepAllCommits implements IndexDeletionPolicy {
1159
 
    public void onInit(List<? extends IndexCommit> commits) {
1160
 
    }
1161
 
    public void onCommit(List<? extends IndexCommit> commits) {
1162
 
    }
1163
 
  }
1164
 
 
1165
 
  public void testReopenOnCommit() throws Throwable {
1166
 
    Directory dir = newDirectory();
1167
 
    IndexWriter writer = new IndexWriter(
1168
 
        dir,
1169
 
        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
1170
 
            setIndexDeletionPolicy(new KeepAllCommits()).
1171
 
            setMaxBufferedDocs(-1).
1172
 
            setMergePolicy(newLogMergePolicy(10))
1173
 
    );
1174
 
    for(int i=0;i<4;i++) {
1175
 
      Document doc = new Document();
1176
 
      doc.add(newField("id", ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
1177
 
      writer.addDocument(doc);
1178
 
      Map<String,String> data = new HashMap<String,String>();
1179
 
      data.put("index", i+"");
1180
 
      writer.commit(data);
1181
 
    }
1182
 
    for(int i=0;i<4;i++) {
1183
 
      writer.deleteDocuments(new Term("id", ""+i));
1184
 
      Map<String,String> data = new HashMap<String,String>();
1185
 
      data.put("index", (4+i)+"");
1186
 
      writer.commit(data);
1187
 
    }
1188
 
    writer.close();
1189
 
 
1190
 
    IndexReader r = IndexReader.open(dir, false);
1191
 
    assertEquals(0, r.numDocs());
1192
 
 
1193
 
    Collection<IndexCommit> commits = IndexReader.listCommits(dir);
1194
 
    for (final IndexCommit commit : commits) {
1195
 
      IndexReader r2 = r.reopen(commit);
1196
 
      assertTrue(r2 != r);
1197
 
 
1198
 
      // Reader should be readOnly
1199
 
      try {
1200
 
        r2.deleteDocument(0);
1201
 
        fail("no exception hit");
1202
 
      } catch (UnsupportedOperationException uoe) {
1203
 
        // expected
1204
 
      }
1205
 
 
1206
 
      final Map<String,String> s = commit.getUserData();
1207
 
      final int v;
1208
 
      if (s.size() == 0) {
1209
 
        // First commit created by IW
1210
 
        v = -1;
1211
 
      } else {
1212
 
        v = Integer.parseInt(s.get("index"));
1213
 
      }
1214
 
      if (v < 4) {
1215
 
        assertEquals(1+v, r2.numDocs());
1216
 
      } else {
1217
 
        assertEquals(7-v, r2.numDocs());
1218
 
      }
1219
 
      r.close();
1220
 
      r = r2;
1221
 
    }
1222
 
    r.close();
1223
 
    dir.close();
1224
 
  }
1225
 
  
1226
 
  // LUCENE-1579: Make sure all SegmentReaders are new when
1227
 
  // reopen switches readOnly
1228
 
  public void testReopenChangeReadonly() throws Exception {
1229
 
    Directory dir = newDirectory();
1230
 
    IndexWriter writer = new IndexWriter(
1231
 
        dir,
1232
 
        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
1233
 
            setMaxBufferedDocs(-1).
1234
 
            setMergePolicy(newLogMergePolicy(10))
1235
 
    );
1236
 
    Document doc = new Document();
1237
 
    doc.add(newField("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
1238
 
    writer.addDocument(doc);
1239
 
    writer.commit();
1240
 
 
1241
 
    // Open reader1
1242
 
    IndexReader r = IndexReader.open(dir, false);
1243
 
    assertTrue(r instanceof DirectoryReader);
1244
 
    IndexReader r1 = SegmentReader.getOnlySegmentReader(r);
1245
 
    final int[] ints = FieldCache.DEFAULT.getInts(r1, "number");
1246
 
    assertEquals(1, ints.length);
1247
 
    assertEquals(17, ints[0]);
1248
 
 
1249
 
    // Reopen to readonly w/ no chnages
1250
 
    IndexReader r3 = r.reopen(true);
1251
 
    assertTrue(r3 instanceof ReadOnlyDirectoryReader);
1252
 
    r3.close();
1253
 
 
1254
 
    // Add new segment
1255
 
    writer.addDocument(doc);
1256
 
    writer.commit();
1257
 
 
1258
 
    // Reopen reader1 --> reader2
1259
 
    IndexReader r2 = r.reopen(true);
1260
 
    r.close();
1261
 
    assertTrue(r2 instanceof ReadOnlyDirectoryReader);
1262
 
    IndexReader[] subs = r2.getSequentialSubReaders();
1263
 
    final int[] ints2 = FieldCache.DEFAULT.getInts(subs[0], "number");
1264
 
    r2.close();
1265
 
 
1266
 
    assertTrue(subs[0] instanceof ReadOnlySegmentReader);
1267
 
    assertTrue(subs[1] instanceof ReadOnlySegmentReader);
1268
 
    assertTrue(ints == ints2);
1269
 
 
1270
 
    writer.close();
1271
 
    dir.close();
1272
 
  }
1273
 
}