add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / test-framework / org / apache / lucene / index / RandomIndexWriter.java
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.Closeable;
21 import java.io.IOException;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Random;
25
26 import org.apache.lucene.analysis.Analyzer;
27 import org.apache.lucene.analysis.MockAnalyzer;
28 import org.apache.lucene.document.Document;
29 import org.apache.lucene.index.IndexWriter; // javadoc
30 import org.apache.lucene.search.Query;
31 import org.apache.lucene.store.Directory;
32 import org.apache.lucene.util.LuceneTestCase;
33 import org.apache.lucene.util.Version;
34 import org.apache.lucene.util._TestUtil;
35
36 /** Silly class that randomizes the indexing experience.  EG
37  *  it may swap in a different merge policy/scheduler; may
38  *  commit periodically; may or may not optimize in the end,
39  *  may flush by doc count instead of RAM, etc. 
40  */
41
42 public class RandomIndexWriter implements Closeable {
43
44   public IndexWriter w;
45   private final Random r;
46   int docCount;
47   int flushAt;
48   private double flushAtFactor = 1.0;
49   private boolean getReaderCalled;
50
51   // Randomly calls Thread.yield so we mixup thread scheduling
52   private static final class MockIndexWriter extends IndexWriter {
53
54     private final Random r;
55
56     public MockIndexWriter(Random r,Directory dir, IndexWriterConfig conf) throws IOException {
57       super(dir, conf);
58       // must make a private random since our methods are
59       // called from different threads; else test failures may
60       // not be reproducible from the original seed
61       this.r = new Random(r.nextInt());
62     }
63
64     @Override
65     boolean testPoint(String name) {
66       if (r.nextInt(4) == 2)
67         Thread.yield();
68       return true;
69     }
70   }
71
72   /** create a RandomIndexWriter with a random config: Uses TEST_VERSION_CURRENT and Whitespace+LowercasingAnalyzer */
73   public RandomIndexWriter(Random r, Directory dir) throws IOException {
74     this(r, dir, LuceneTestCase.newIndexWriterConfig(r, LuceneTestCase.TEST_VERSION_CURRENT, new MockAnalyzer(r)));
75   }
76   
77   /** create a RandomIndexWriter with a random config: Uses TEST_VERSION_CURRENT */
78   public RandomIndexWriter(Random r, Directory dir, Analyzer a) throws IOException {
79     this(r, dir, LuceneTestCase.newIndexWriterConfig(r, LuceneTestCase.TEST_VERSION_CURRENT, a));
80   }
81   
82   /** create a RandomIndexWriter with a random config */
83   public RandomIndexWriter(Random r, Directory dir, Version v, Analyzer a) throws IOException {
84     this(r, dir, LuceneTestCase.newIndexWriterConfig(r, v, a));
85   }
86   
87   /** create a RandomIndexWriter with the provided config */
88   public RandomIndexWriter(Random r, Directory dir, IndexWriterConfig c) throws IOException {
89     this.r = r;
90     w = new MockIndexWriter(r, dir, c);
91     flushAt = _TestUtil.nextInt(r, 10, 1000);
92     if (LuceneTestCase.VERBOSE) {
93       System.out.println("RIW config=" + w.getConfig());
94     }
95   } 
96
97   /**
98    * Adds a Document.
99    * @see IndexWriter#addDocument(Document)
100    */
101   public void addDocument(final Document doc) throws IOException {
102     if (r.nextInt(5) == 3) {
103       // TODO: maybe, we should simply buffer up added docs
104       // (but we need to clone them), and only when
105       // getReader, commit, etc. are called, we do an
106       // addDocuments?  Would be better testing.
107       w.addDocuments(Collections.singletonList(doc));
108     } else {
109       w.addDocument(doc);
110     }
111     maybeCommit();
112   }
113   
114   public void addDocuments(Collection<Document> docs) throws IOException {
115     w.addDocuments(docs);
116     maybeCommit();
117   }
118
119   public void updateDocuments(Term delTerm, Collection<Document> docs) throws IOException {
120     w.updateDocuments(delTerm, docs);
121     maybeCommit();
122   }
123
124   private void maybeCommit() throws IOException {
125     if (docCount++ == flushAt) {
126       if (LuceneTestCase.VERBOSE) {
127         System.out.println("RIW.add/updateDocument: now doing a commit at docCount=" + docCount);
128       }
129       w.commit();
130       flushAt += _TestUtil.nextInt(r, (int) (flushAtFactor * 10), (int) (flushAtFactor * 1000));
131       if (flushAtFactor < 2e6) {
132         // gradually but exponentially increase time b/w flushes
133         flushAtFactor *= 1.05;
134       }
135     }
136   }
137
138   /**
139    * Updates a document.
140    * @see IndexWriter#updateDocument(Term, Document)
141    */
142   public void updateDocument(Term t, final Document doc) throws IOException {
143     if (r.nextInt(5) == 3) {
144       w.updateDocuments(t, Collections.singletonList(doc));
145     } else {
146       w.updateDocument(t, doc);
147     }
148     maybeCommit();
149   }
150   
151   public void addIndexes(Directory... dirs) throws CorruptIndexException, IOException {
152     w.addIndexes(dirs);
153   }
154   
155   public void deleteDocuments(Term term) throws CorruptIndexException, IOException {
156     w.deleteDocuments(term);
157   }
158
159   public void deleteDocuments(Query q) throws CorruptIndexException, IOException {
160     w.deleteDocuments(q);
161   }
162   
163   public void commit() throws CorruptIndexException, IOException {
164     w.commit();
165   }
166   
167   public int numDocs() throws IOException {
168     return w.numDocs();
169   }
170
171   public int maxDoc() {
172     return w.maxDoc();
173   }
174
175   public void deleteAll() throws IOException {
176     w.deleteAll();
177   }
178
179   private boolean doRandomOptimize = true;
180   private boolean doRandomOptimizeAssert = true;
181
182   public void setDoRandomOptimize(boolean v) {
183     doRandomOptimize = v;
184   }
185
186   public void setDoRandomOptimizeAssert(boolean v) {
187     doRandomOptimizeAssert = v;
188   }
189
190   private void doRandomOptimize() throws IOException {
191     if (doRandomOptimize) {
192       final int segCount = w.getSegmentCount();
193       if (r.nextBoolean() || segCount == 0) {
194         // full optimize
195         w.optimize();
196       } else {
197         // partial optimize
198         final int limit = _TestUtil.nextInt(r, 1, segCount);
199         w.optimize(limit);
200         assert !doRandomOptimizeAssert || w.getSegmentCount() <= limit: "limit=" + limit + " actual=" + w.getSegmentCount();
201       }
202     }
203   }
204
205   public IndexReader getReader() throws IOException {
206     return getReader(true);
207   }
208
209   public IndexReader getReader(boolean applyDeletions) throws IOException {
210     getReaderCalled = true;
211     if (r.nextInt(4) == 2) {
212       doRandomOptimize();
213     }
214     if (r.nextBoolean()) {
215       if (LuceneTestCase.VERBOSE) {
216         System.out.println("RIW.getReader: use NRT reader");
217       }
218       if (r.nextInt(5) == 1) {
219         w.commit();
220       }
221       return w.getReader(applyDeletions);
222     } else {
223       if (LuceneTestCase.VERBOSE) {
224         System.out.println("RIW.getReader: open new reader");
225       }
226       w.commit();
227       if (r.nextBoolean()) {
228         return IndexReader.open(w.getDirectory(), new KeepOnlyLastCommitDeletionPolicy(), r.nextBoolean(), _TestUtil.nextInt(r, 1, 10));
229       } else {
230         return w.getReader(applyDeletions);
231       }
232     }
233   }
234
235   /**
236    * Close this writer.
237    * @see IndexWriter#close()
238    */
239   public void close() throws IOException {
240     // if someone isn't using getReader() API, we want to be sure to
241     // maybeOptimize since presumably they might open a reader on the dir.
242     if (getReaderCalled == false && r.nextInt(8) == 2) {
243       doRandomOptimize();
244     }
245     w.close();
246   }
247
248   /**
249    * Forces an optimize.
250    * <p>
251    * NOTE: this should be avoided in tests unless absolutely necessary,
252    * as it will result in less test coverage.
253    * @see IndexWriter#optimize()
254    */
255   public void optimize() throws IOException {
256     w.optimize();
257   }
258 }