~ubuntu-branches/ubuntu/trusty/pylucene/trusty

« back to all changes in this revision

Viewing changes to lucene-java-3.5.0/lucene/backwards/src/test/org/apache/lucene/index/TestStressIndexing2.java

  • Committer: Package Import Robot
  • Author(s): Dmitry Nezhevenko
  • Date: 2012-04-23 16:43:55 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120423164355-grqtepnwtecdjfk2
Tags: 3.5.0-1
* New maintainer (closes: 670179)
* New upstream release
* Switch to dpkg-source 3.0 (quilt) format
* Switch to machine-readable debian/copyright
* Bump debian/compat to 8, drop debian/pycompat
* Switch from cdbs to dh
* Add watch file
* Build for all supported versions of python2 (closes: 581198, 632240)
* Rename binary package to python-lucene (closes: 581197)
* Add -dbg package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.apache.lucene.index;
 
2
 
 
3
/**
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
import java.io.IOException;
 
18
import java.util.ArrayList;
 
19
import java.util.Arrays;
 
20
import java.util.Collections;
 
21
import java.util.Comparator;
 
22
import java.util.HashMap;
 
23
import java.util.Iterator;
 
24
import java.util.List;
 
25
import java.util.Map;
 
26
import java.util.Random;
 
27
 
 
28
import junit.framework.Assert;
 
29
 
 
30
import org.apache.lucene.analysis.WhitespaceAnalyzer;
 
31
import org.apache.lucene.document.Document;
 
32
import org.apache.lucene.document.Field;
 
33
import org.apache.lucene.document.Fieldable;
 
34
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 
35
import org.apache.lucene.search.TermQuery;
 
36
import org.apache.lucene.store.Directory;
 
37
import org.apache.lucene.util.LuceneTestCase;
 
38
import org.apache.lucene.util.StringHelper;
 
39
import org.apache.lucene.util._TestUtil;
 
40
 
 
41
public class TestStressIndexing2 extends LuceneTestCase {
 
42
  static int maxFields=4;
 
43
  static int bigFieldSize=10;
 
44
  static boolean sameFieldOrder=false;
 
45
  static int mergeFactor=3;
 
46
  static int maxBufferedDocs=3;
 
47
  static int seed=0;
 
48
 
 
49
  public class MockIndexWriter extends IndexWriter {
 
50
 
 
51
    public MockIndexWriter(Directory dir, IndexWriterConfig conf) throws IOException {
 
52
      super(dir, conf);
 
53
    }
 
54
 
 
55
    @Override
 
56
    boolean testPoint(String name) {
 
57
      //      if (name.equals("startCommit")) {
 
58
      if (random.nextInt(4) == 2)
 
59
        Thread.yield();
 
60
      return true;
 
61
    }
 
62
  }
 
63
  
 
64
  public void testRandomIWReader() throws Throwable {
 
65
    Directory dir = newDirectory();
 
66
    
 
67
    // TODO: verify equals using IW.getReader
 
68
    DocsAndWriter dw = indexRandomIWReader(5, 3, 100, dir);
 
69
    IndexReader reader = dw.writer.getReader();
 
70
    dw.writer.commit();
 
71
    verifyEquals(random, reader, dir, "id");
 
72
    reader.close();
 
73
    dw.writer.close();
 
74
    dir.close();
 
75
  }
 
76
  
 
77
  public void testRandom() throws Throwable {
 
78
    Directory dir1 = newDirectory();
 
79
    Directory dir2 = newDirectory();
 
80
    // mergeFactor=2; maxBufferedDocs=2; Map docs = indexRandom(1, 3, 2, dir1);
 
81
    int maxThreadStates = 1+random.nextInt(10);
 
82
    boolean doReaderPooling = random.nextBoolean();
 
83
    Map<String,Document> docs = indexRandom(5, 3, 100, dir1, maxThreadStates, doReaderPooling);
 
84
    indexSerial(random, docs, dir2);
 
85
 
 
86
    // verifying verify
 
87
    // verifyEquals(dir1, dir1, "id");
 
88
    // verifyEquals(dir2, dir2, "id");
 
89
 
 
90
    verifyEquals(dir1, dir2, "id");
 
91
    dir1.close();
 
92
    dir2.close();
 
93
  }
 
94
 
 
95
  public void testMultiConfig() throws Throwable {
 
96
    // test lots of smaller different params together
 
97
    int num = atLeast(3);
 
98
    for (int i = 0; i < num; i++) { // increase iterations for better testing
 
99
      if (VERBOSE) {
 
100
        System.out.println("\n\nTEST: top iter=" + i);
 
101
      }
 
102
      sameFieldOrder=random.nextBoolean();
 
103
      mergeFactor=random.nextInt(3)+2;
 
104
      maxBufferedDocs=random.nextInt(3)+2;
 
105
      int maxThreadStates = 1+random.nextInt(10);
 
106
      boolean doReaderPooling = random.nextBoolean();
 
107
      seed++;
 
108
 
 
109
      int nThreads=random.nextInt(5)+1;
 
110
      int iter=random.nextInt(5)+1;
 
111
      int range=random.nextInt(20)+1;
 
112
      Directory dir1 = newDirectory();
 
113
      Directory dir2 = newDirectory();
 
114
      if (VERBOSE) {
 
115
        System.out.println("  nThreads=" + nThreads + " iter=" + iter + " range=" + range + " doPooling=" + doReaderPooling + " maxThreadStates=" + maxThreadStates + " sameFieldOrder=" + sameFieldOrder + " mergeFactor=" + mergeFactor);
 
116
      }
 
117
      Map<String,Document> docs = indexRandom(nThreads, iter, range, dir1, maxThreadStates, doReaderPooling);
 
118
      if (VERBOSE) {
 
119
        System.out.println("TEST: index serial");
 
120
      }
 
121
      indexSerial(random, docs, dir2);
 
122
      if (VERBOSE) {
 
123
        System.out.println("TEST: verify");
 
124
      }
 
125
      verifyEquals(dir1, dir2, "id");
 
126
      dir1.close();
 
127
      dir2.close();
 
128
    }
 
129
  }
 
130
 
 
131
 
 
132
  static Term idTerm = new Term("id","");
 
133
  IndexingThread[] threads;
 
134
  static Comparator<Fieldable> fieldNameComparator = new Comparator<Fieldable>() {
 
135
        public int compare(Fieldable o1, Fieldable o2) {
 
136
          return o1.name().compareTo(o2.name());
 
137
        }
 
138
  };
 
139
 
 
140
  // This test avoids using any extra synchronization in the multiple
 
141
  // indexing threads to test that IndexWriter does correctly synchronize
 
142
  // everything.
 
143
  
 
144
  public static class DocsAndWriter {
 
145
    Map<String,Document> docs;
 
146
    IndexWriter writer;
 
147
  }
 
148
  
 
149
  public DocsAndWriter indexRandomIWReader(int nThreads, int iterations, int range, Directory dir) throws IOException, InterruptedException {
 
150
    Map<String,Document> docs = new HashMap<String,Document>();
 
151
    IndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig(
 
152
        TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).setOpenMode(OpenMode.CREATE).setRAMBufferSizeMB(
 
153
                                                                                                  0.1).setMaxBufferedDocs(maxBufferedDocs).setMergePolicy(newLogMergePolicy()));
 
154
    w.setInfoStream(VERBOSE ? System.out : null);
 
155
    w.commit();
 
156
    setUseCompoundFile(w.getConfig().getMergePolicy(), false);
 
157
    setMergeFactor(w.getConfig().getMergePolicy(), mergeFactor);
 
158
    /***
 
159
        w.setMaxMergeDocs(Integer.MAX_VALUE);
 
160
        w.setMaxFieldLength(10000);
 
161
        w.setRAMBufferSizeMB(1);
 
162
        w.setMergeFactor(10);
 
163
    ***/
 
164
 
 
165
    threads = new IndexingThread[nThreads];
 
166
    for (int i=0; i<threads.length; i++) {
 
167
      IndexingThread th = new IndexingThread();
 
168
      th.w = w;
 
169
      th.base = 1000000*i;
 
170
      th.range = range;
 
171
      th.iterations = iterations;
 
172
      threads[i] = th;
 
173
    }
 
174
 
 
175
    for (int i=0; i<threads.length; i++) {
 
176
      threads[i].start();
 
177
    }
 
178
    for (int i=0; i<threads.length; i++) {
 
179
      threads[i].join();
 
180
    }
 
181
 
 
182
    // w.optimize();
 
183
    //w.close();    
 
184
 
 
185
    for (int i=0; i<threads.length; i++) {
 
186
      IndexingThread th = threads[i];
 
187
      synchronized(th) {
 
188
        docs.putAll(th.docs);
 
189
      }
 
190
    }
 
191
 
 
192
    _TestUtil.checkIndex(dir);
 
193
    DocsAndWriter dw = new DocsAndWriter();
 
194
    dw.docs = docs;
 
195
    dw.writer = w;
 
196
    return dw;
 
197
  }
 
198
  
 
199
  public Map<String,Document> indexRandom(int nThreads, int iterations, int range, Directory dir, int maxThreadStates,
 
200
                                          boolean doReaderPooling) throws IOException, InterruptedException {
 
201
    Map<String,Document> docs = new HashMap<String,Document>();
 
202
    for(int iter=0;iter<3;iter++) {
 
203
      if (VERBOSE) {
 
204
        System.out.println("TEST: iter=" + iter);
 
205
      }
 
206
      IndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig(
 
207
          TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).setOpenMode(OpenMode.CREATE)
 
208
               .setRAMBufferSizeMB(0.1).setMaxBufferedDocs(maxBufferedDocs).setMaxThreadStates(maxThreadStates)
 
209
               .setReaderPooling(doReaderPooling).setMergePolicy(newLogMergePolicy()));
 
210
      w.setInfoStream(VERBOSE ? System.out : null);
 
211
      setUseCompoundFile(w.getConfig().getMergePolicy(), false);
 
212
      setMergeFactor(w.getConfig().getMergePolicy(), mergeFactor);
 
213
 
 
214
      threads = new IndexingThread[nThreads];
 
215
      for (int i=0; i<threads.length; i++) {
 
216
        IndexingThread th = new IndexingThread();
 
217
        th.w = w;
 
218
        th.base = 1000000*i;
 
219
        th.range = range;
 
220
        th.iterations = iterations;
 
221
        threads[i] = th;
 
222
      }
 
223
 
 
224
      for (int i=0; i<threads.length; i++) {
 
225
        threads[i].start();
 
226
      }
 
227
      for (int i=0; i<threads.length; i++) {
 
228
        threads[i].join();
 
229
      }
 
230
 
 
231
      // w.optimize();
 
232
      w.close();    
 
233
 
 
234
      for (int i=0; i<threads.length; i++) {
 
235
        IndexingThread th = threads[i];
 
236
        synchronized(th) {
 
237
          docs.putAll(th.docs);
 
238
        }
 
239
      }
 
240
    }
 
241
 
 
242
    _TestUtil.checkIndex(dir);
 
243
 
 
244
    return docs;
 
245
  }
 
246
 
 
247
  
 
248
  public static void indexSerial(Random random, Map<String,Document> docs, Directory dir) throws IOException {
 
249
    IndexWriter w = new IndexWriter(dir, LuceneTestCase.newIndexWriterConfig(random, TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).setMergePolicy(newLogMergePolicy()));
 
250
 
 
251
    // index all docs in a single thread
 
252
    Iterator<Document> iter = docs.values().iterator();
 
253
    while (iter.hasNext()) {
 
254
      Document d = iter.next();
 
255
      ArrayList<Fieldable> fields = new ArrayList<Fieldable>();
 
256
      fields.addAll(d.getFields());
 
257
      // put fields in same order each time
 
258
      Collections.sort(fields, fieldNameComparator);
 
259
      
 
260
      Document d1 = new Document();
 
261
      d1.setBoost(d.getBoost());
 
262
      for (int i=0; i<fields.size(); i++) {
 
263
        d1.add(fields.get(i));
 
264
      }
 
265
      w.addDocument(d1);
 
266
      // System.out.println("indexing "+d1);
 
267
    }
 
268
    
 
269
    w.close();
 
270
  }
 
271
  
 
272
  public static void verifyEquals(Random r, IndexReader r1, Directory dir2, String idField) throws Throwable {
 
273
    IndexReader r2 = IndexReader.open(dir2);
 
274
    verifyEquals(r1, r2, idField);
 
275
    r2.close();
 
276
  }
 
277
 
 
278
  public static void verifyEquals(Directory dir1, Directory dir2, String idField) throws Throwable {
 
279
    IndexReader r1 = IndexReader.open(dir1, true);
 
280
    IndexReader r2 = IndexReader.open(dir2, true);
 
281
    verifyEquals(r1, r2, idField);
 
282
    r1.close();
 
283
    r2.close();
 
284
  }
 
285
 
 
286
  private static void printDocs(IndexReader r) throws Throwable {
 
287
    IndexReader[] subs = r.getSequentialSubReaders();
 
288
    for(IndexReader sub : subs) {
 
289
      System.out.println("  " + ((SegmentReader) sub).getSegmentInfo());
 
290
      for(int docID=0;docID<sub.maxDoc();docID++) {
 
291
        Document doc = sub.document(docID);
 
292
        if (!sub.isDeleted(docID)) {
 
293
          System.out.println("    docID=" + docID + " id:" + doc.get("id"));
 
294
        } else {
 
295
          System.out.println("    DEL docID=" + docID + " id:" + doc.get("id"));
 
296
        }
 
297
      }
 
298
    }
 
299
  }
 
300
 
 
301
 
 
302
  public static void verifyEquals(IndexReader r1, IndexReader r2, String idField) throws Throwable {
 
303
    if (VERBOSE) {
 
304
      System.out.println("\nr1 docs:");
 
305
      printDocs(r1);
 
306
      System.out.println("\nr2 docs:");
 
307
      printDocs(r2);
 
308
    }
 
309
    if (r1.numDocs() != r2.numDocs()) {
 
310
      assert false: "r1.numDocs()=" + r1.numDocs() + " vs r2.numDocs()=" + r2.numDocs();
 
311
    }
 
312
    boolean hasDeletes = !(r1.maxDoc()==r2.maxDoc() && r1.numDocs()==r1.maxDoc());
 
313
 
 
314
    int[] r2r1 = new int[r2.maxDoc()];   // r2 id to r1 id mapping
 
315
 
 
316
    TermDocs termDocs1 = r1.termDocs();
 
317
    TermDocs termDocs2 = r2.termDocs();
 
318
 
 
319
    // create mapping from id2 space to id2 based on idField
 
320
    idField = StringHelper.intern(idField);
 
321
    TermEnum termEnum = r1.terms (new Term (idField, ""));
 
322
    do {
 
323
      Term term = termEnum.term();
 
324
      if (term==null || term.field() != idField) break;
 
325
 
 
326
      termDocs1.seek (termEnum);
 
327
      if (!termDocs1.next()) {
 
328
        // This doc is deleted and wasn't replaced
 
329
        termDocs2.seek(termEnum);
 
330
        assertFalse(termDocs2.next());
 
331
        continue;
 
332
      }
 
333
 
 
334
      int id1 = termDocs1.doc();
 
335
      assertFalse(termDocs1.next());
 
336
 
 
337
      termDocs2.seek(termEnum);
 
338
      assertTrue(termDocs2.next());
 
339
      int id2 = termDocs2.doc();
 
340
      assertFalse(termDocs2.next());
 
341
 
 
342
      r2r1[id2] = id1;
 
343
 
 
344
      // verify stored fields are equivalent
 
345
      try {
 
346
        verifyEquals(r1.document(id1), r2.document(id2));
 
347
      } catch (Throwable t) {
 
348
        System.out.println("FAILED id=" + term + " id1=" + id1 + " id2=" + id2 + " term="+ term);
 
349
        System.out.println("  d1=" + r1.document(id1));
 
350
        System.out.println("  d2=" + r2.document(id2));
 
351
        throw t;
 
352
      }
 
353
 
 
354
      try {
 
355
        // verify term vectors are equivalent        
 
356
        verifyEquals(r1.getTermFreqVectors(id1), r2.getTermFreqVectors(id2));
 
357
      } catch (Throwable e) {
 
358
        System.out.println("FAILED id=" + term + " id1=" + id1 + " id2=" + id2);
 
359
        TermFreqVector[] tv1 = r1.getTermFreqVectors(id1);
 
360
        System.out.println("  d1=" + tv1);
 
361
        if (tv1 != null)
 
362
          for(int i=0;i<tv1.length;i++)
 
363
            System.out.println("    " + i + ": " + tv1[i]);
 
364
        
 
365
        TermFreqVector[] tv2 = r2.getTermFreqVectors(id2);
 
366
        System.out.println("  d2=" + tv2);
 
367
        if (tv2 != null)
 
368
          for(int i=0;i<tv2.length;i++)
 
369
            System.out.println("    " + i + ": " + tv2[i]);
 
370
        
 
371
        throw e;
 
372
      }
 
373
 
 
374
    } while (termEnum.next());
 
375
 
 
376
    termEnum.close();
 
377
 
 
378
    // Verify postings
 
379
    TermEnum termEnum1 = r1.terms (new Term ("", ""));
 
380
    TermEnum termEnum2 = r2.terms (new Term ("", ""));
 
381
 
 
382
    // pack both doc and freq into single element for easy sorting
 
383
    long[] info1 = new long[r1.numDocs()];
 
384
    long[] info2 = new long[r2.numDocs()];
 
385
 
 
386
    for(;;) {
 
387
      Term term1,term2;
 
388
 
 
389
      // iterate until we get some docs
 
390
      int len1;
 
391
      for(;;) {
 
392
        len1=0;
 
393
        term1 = termEnum1.term();
 
394
        if (term1==null) break;
 
395
        termDocs1.seek(termEnum1);
 
396
        while (termDocs1.next()) {
 
397
          int d1 = termDocs1.doc();
 
398
          int f1 = termDocs1.freq();
 
399
          info1[len1] = (((long)d1)<<32) | f1;
 
400
          len1++;
 
401
        }
 
402
        if (len1>0) break;
 
403
        if (!termEnum1.next()) break;
 
404
      }
 
405
 
 
406
       // iterate until we get some docs
 
407
      int len2;
 
408
      for(;;) {
 
409
        len2=0;
 
410
        term2 = termEnum2.term();
 
411
        if (term2==null) break;
 
412
        termDocs2.seek(termEnum2);
 
413
        while (termDocs2.next()) {
 
414
          int d2 = termDocs2.doc();
 
415
          int f2 = termDocs2.freq();
 
416
          info2[len2] = (((long)r2r1[d2])<<32) | f2;
 
417
          len2++;
 
418
        }
 
419
        if (len2>0) break;
 
420
        if (!termEnum2.next()) break;
 
421
      }
 
422
 
 
423
      if (!hasDeletes)
 
424
        assertEquals(termEnum1.docFreq(), termEnum2.docFreq());
 
425
 
 
426
      assertEquals(len1, len2);
 
427
      if (len1==0) break;  // no more terms
 
428
 
 
429
      assertEquals(term1, term2);
 
430
 
 
431
      // sort info2 to get it into ascending docid
 
432
      Arrays.sort(info2, 0, len2);
 
433
 
 
434
      // now compare
 
435
      for (int i=0; i<len1; i++) {
 
436
        assertEquals(info1[i], info2[i]);
 
437
      }
 
438
 
 
439
      termEnum1.next();
 
440
      termEnum2.next();
 
441
    }
 
442
  }
 
443
 
 
444
  public static void verifyEquals(Document d1, Document d2) {
 
445
    List<Fieldable> ff1 = d1.getFields();
 
446
    List<Fieldable> ff2 = d2.getFields();
 
447
 
 
448
    Collections.sort(ff1, fieldNameComparator);
 
449
    Collections.sort(ff2, fieldNameComparator);
 
450
 
 
451
    assertEquals(ff1 + " : " + ff2, ff1.size(), ff2.size());
 
452
 
 
453
    for (int i=0; i<ff1.size(); i++) {
 
454
      Fieldable f1 = ff1.get(i);
 
455
      Fieldable f2 = ff2.get(i);
 
456
      if (f1.isBinary()) {
 
457
        assert(f2.isBinary());
 
458
      } else {
 
459
        String s1 = f1.stringValue();
 
460
        String s2 = f2.stringValue();
 
461
        assertEquals(ff1 + " : " + ff2, s1,s2);
 
462
      }
 
463
    }
 
464
  }
 
465
 
 
466
  public static void verifyEquals(TermFreqVector[] d1, TermFreqVector[] d2) {
 
467
    if (d1 == null) {
 
468
      assertTrue(d2 == null);
 
469
      return;
 
470
    }
 
471
    assertTrue(d2 != null);
 
472
 
 
473
    assertEquals(d1.length, d2.length);
 
474
    for(int i=0;i<d1.length;i++) {
 
475
      TermFreqVector v1 = d1[i];
 
476
      TermFreqVector v2 = d2[i];
 
477
      if (v1 == null || v2 == null)
 
478
        System.out.println("v1=" + v1 + " v2=" + v2 + " i=" + i + " of " + d1.length);
 
479
      assertEquals(v1.size(), v2.size());
 
480
      int numTerms = v1.size();
 
481
      String[] terms1 = v1.getTerms();
 
482
      String[] terms2 = v2.getTerms();
 
483
      int[] freq1 = v1.getTermFrequencies();
 
484
      int[] freq2 = v2.getTermFrequencies();
 
485
      for(int j=0;j<numTerms;j++) {
 
486
        if (!terms1[j].equals(terms2[j]))
 
487
          assertEquals(terms1[j], terms2[j]);
 
488
        assertEquals(freq1[j], freq2[j]);
 
489
      }
 
490
      if (v1 instanceof TermPositionVector) {
 
491
        assertTrue(v2 instanceof TermPositionVector);
 
492
        TermPositionVector tpv1 = (TermPositionVector) v1;
 
493
        TermPositionVector tpv2 = (TermPositionVector) v2;
 
494
        for(int j=0;j<numTerms;j++) {
 
495
          int[] pos1 = tpv1.getTermPositions(j);
 
496
          int[] pos2 = tpv2.getTermPositions(j);
 
497
          if (pos1 == null) {
 
498
            assertNull(pos2);
 
499
          } else {
 
500
            assertNotNull(pos1);
 
501
            assertNotNull(pos2);
 
502
            assertEquals(pos1.length, pos2.length);
 
503
            TermVectorOffsetInfo[] offsets1 = tpv1.getOffsets(j);
 
504
            TermVectorOffsetInfo[] offsets2 = tpv2.getOffsets(j);
 
505
            if (offsets1 == null)
 
506
              assertTrue(offsets2 == null);
 
507
            else
 
508
              assertTrue(offsets2 != null);
 
509
            for(int k=0;k<pos1.length;k++) {
 
510
              assertEquals(pos1[k], pos2[k]);
 
511
              if (offsets1 != null) {
 
512
                assertEquals(offsets1[k].getStartOffset(),
 
513
                             offsets2[k].getStartOffset());
 
514
                assertEquals(offsets1[k].getEndOffset(),
 
515
                             offsets2[k].getEndOffset());
 
516
              }
 
517
            }
 
518
          }
 
519
        }
 
520
      }
 
521
    }
 
522
  }
 
523
 
 
524
  private class IndexingThread extends Thread {
 
525
    IndexWriter w;
 
526
    int base;
 
527
    int range;
 
528
    int iterations;
 
529
    Map<String,Document> docs = new HashMap<String,Document>();  
 
530
    Random r;
 
531
 
 
532
    public int nextInt(int lim) {
 
533
      return r.nextInt(lim);
 
534
    }
 
535
 
 
536
    // start is inclusive and end is exclusive
 
537
    public int nextInt(int start, int end) {
 
538
      return start + r.nextInt(end-start);
 
539
    }
 
540
 
 
541
    char[] buffer = new char[100];
 
542
 
 
543
    private int addUTF8Token(int start) {
 
544
      final int end = start + nextInt(20);
 
545
      if (buffer.length < 1+end) {
 
546
        char[] newBuffer = new char[(int) ((1+end)*1.25)];
 
547
        System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
 
548
        buffer = newBuffer;
 
549
      }
 
550
 
 
551
      for(int i=start;i<end;i++) {
 
552
        int t = nextInt(6);
 
553
        if (0 == t && i < end-1) {
 
554
          // Make a surrogate pair
 
555
          // High surrogate
 
556
          buffer[i++] = (char) nextInt(0xd800, 0xdc00);
 
557
          // Low surrogate
 
558
          buffer[i] = (char) nextInt(0xdc00, 0xe000);
 
559
        } else if (t <= 1)
 
560
          buffer[i] = (char) nextInt(0x80);
 
561
        else if (2 == t)
 
562
          buffer[i] = (char) nextInt(0x80, 0x800);
 
563
        else if (3 == t)
 
564
          buffer[i] = (char) nextInt(0x800, 0xd800);
 
565
        else if (4 == t)
 
566
          buffer[i] = (char) nextInt(0xe000, 0xffff);
 
567
        else if (5 == t) {
 
568
          // Illegal unpaired surrogate
 
569
          if (r.nextBoolean())
 
570
            buffer[i] = (char) nextInt(0xd800, 0xdc00);
 
571
          else
 
572
            buffer[i] = (char) nextInt(0xdc00, 0xe000);
 
573
        }
 
574
      }
 
575
      buffer[end] = ' ';
 
576
      return 1+end;
 
577
    }
 
578
 
 
579
    public String getString(int nTokens) {
 
580
      nTokens = nTokens!=0 ? nTokens : r.nextInt(4)+1;
 
581
 
 
582
      // Half the time make a random UTF8 string
 
583
      if (r.nextBoolean())
 
584
        return getUTF8String(nTokens);
 
585
 
 
586
      // avoid StringBuffer because it adds extra synchronization.
 
587
      char[] arr = new char[nTokens*2];
 
588
      for (int i=0; i<nTokens; i++) {
 
589
        arr[i*2] = (char)('A' + r.nextInt(10));
 
590
        arr[i*2+1] = ' ';
 
591
      }
 
592
      return new String(arr);
 
593
    }
 
594
    
 
595
    public String getUTF8String(int nTokens) {
 
596
      int upto = 0;
 
597
      Arrays.fill(buffer, (char) 0);
 
598
      for(int i=0;i<nTokens;i++)
 
599
        upto = addUTF8Token(upto);
 
600
      return new String(buffer, 0, upto);
 
601
    }
 
602
 
 
603
    public String getIdString() {
 
604
      return Integer.toString(base + nextInt(range));
 
605
    }
 
606
 
 
607
    public void indexDoc() throws IOException {
 
608
      Document d = new Document();
 
609
 
 
610
      ArrayList<Field> fields = new ArrayList<Field>();      
 
611
      String idString = getIdString();
 
612
      Field idField =  newField(idTerm.field(), idString, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
 
613
      fields.add(idField);
 
614
 
 
615
      int nFields = nextInt(maxFields);
 
616
      for (int i=0; i<nFields; i++) {
 
617
 
 
618
        Field.TermVector tvVal = Field.TermVector.NO;
 
619
        switch (nextInt(4)) {
 
620
        case 0:
 
621
          tvVal = Field.TermVector.NO;
 
622
          break;
 
623
        case 1:
 
624
          tvVal = Field.TermVector.YES;
 
625
          break;
 
626
        case 2:
 
627
          tvVal = Field.TermVector.WITH_POSITIONS;
 
628
          break;
 
629
        case 3:
 
630
          tvVal = Field.TermVector.WITH_POSITIONS_OFFSETS;
 
631
          break;
 
632
        }
 
633
        
 
634
        switch (nextInt(4)) {
 
635
          case 0:
 
636
            fields.add(newField("f" + nextInt(100), getString(1), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, tvVal));
 
637
            break;
 
638
          case 1:
 
639
            fields.add(newField("f" + nextInt(100), getString(0), Field.Store.NO, Field.Index.ANALYZED, tvVal));
 
640
            break;
 
641
          case 2:
 
642
            fields.add(newField("f" + nextInt(100), getString(0), Field.Store.YES, Field.Index.NO, Field.TermVector.NO));
 
643
            break;
 
644
          case 3:
 
645
            fields.add(newField("f" + nextInt(100), getString(bigFieldSize), Field.Store.YES, Field.Index.ANALYZED, tvVal));
 
646
            break;          
 
647
        }
 
648
      }
 
649
 
 
650
      if (sameFieldOrder) {
 
651
        Collections.sort(fields, fieldNameComparator);
 
652
      } else {
 
653
        // random placement of id field also
 
654
        Collections.swap(fields,nextInt(fields.size()), 0);
 
655
      }
 
656
 
 
657
      for (int i=0; i<fields.size(); i++) {
 
658
        d.add(fields.get(i));
 
659
      }
 
660
      if (VERBOSE) {
 
661
        System.out.println(Thread.currentThread().getName() + ": indexing id:" + idString);
 
662
      }
 
663
      w.updateDocument(idTerm.createTerm(idString), d);
 
664
      //System.out.println(Thread.currentThread().getName() + ": indexing "+d);
 
665
      docs.put(idString, d);
 
666
    }
 
667
 
 
668
    public void deleteDoc() throws IOException {
 
669
      String idString = getIdString();
 
670
      if (VERBOSE) {
 
671
        System.out.println(Thread.currentThread().getName() + ": del id:" + idString);
 
672
      }
 
673
      w.deleteDocuments(idTerm.createTerm(idString));
 
674
      docs.remove(idString);
 
675
    }
 
676
 
 
677
    public void deleteByQuery() throws IOException {
 
678
      String idString = getIdString();
 
679
      if (VERBOSE) {
 
680
        System.out.println(Thread.currentThread().getName() + ": del query id:" + idString);
 
681
      }
 
682
      w.deleteDocuments(new TermQuery(idTerm.createTerm(idString)));
 
683
      docs.remove(idString);
 
684
    }
 
685
 
 
686
    @Override
 
687
    public void run() {
 
688
      try {
 
689
        r = new Random(base+range+seed);
 
690
        for (int i=0; i<iterations; i++) {
 
691
          int what = nextInt(100);
 
692
          if (what < 5) {
 
693
            deleteDoc();
 
694
          } else if (what < 10) {
 
695
            deleteByQuery();
 
696
          } else {
 
697
            indexDoc();
 
698
          }
 
699
        }
 
700
      } catch (Throwable e) {
 
701
        e.printStackTrace();
 
702
        Assert.fail(e.toString());
 
703
      }
 
704
 
 
705
      synchronized (this) {
 
706
        docs.size();
 
707
      }
 
708
    }
 
709
  }
 
710
 
 
711
}