add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / backwards / src / test / org / apache / lucene / index / TestAtomicUpdate.java
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 org.apache.lucene.util.*;
20 import org.apache.lucene.store.*;
21 import org.apache.lucene.document.*;
22 import org.apache.lucene.analysis.MockAnalyzer;
23
24 import java.util.Random;
25 import java.io.File;
26 import java.io.IOException;
27
28 public class TestAtomicUpdate extends LuceneTestCase {
29   
30   private static final class MockIndexWriter extends IndexWriter {
31
32     static Random RANDOM;
33
34     public MockIndexWriter(Directory dir, IndexWriterConfig conf) throws IOException {
35       super(dir, conf);
36     }
37
38     @Override
39     boolean testPoint(String name) {
40       //      if (name.equals("startCommit")) {
41       if (RANDOM.nextInt(4) == 2)
42         Thread.yield();
43       return true;
44     }
45   }
46
47   private static abstract class TimedThread extends Thread {
48     volatile boolean failed;
49     int count;
50     private static float RUN_TIME_MSEC = atLeast(500);
51     private TimedThread[] allThreads;
52
53     abstract public void doWork() throws Throwable;
54
55     TimedThread(TimedThread[] threads) {
56       this.allThreads = threads;
57     }
58
59     @Override
60     public void run() {
61       final long stopTime = System.currentTimeMillis() + (long) RUN_TIME_MSEC;
62
63       count = 0;
64
65       try {
66         do {
67           if (anyErrors()) break;
68           doWork();
69           count++;
70         } while(System.currentTimeMillis() < stopTime);
71       } catch (Throwable e) {
72         System.out.println(Thread.currentThread().getName() + ": exc");
73         e.printStackTrace(System.out);
74         failed = true;
75       }
76     }
77
78     private boolean anyErrors() {
79       for(int i=0;i<allThreads.length;i++)
80         if (allThreads[i] != null && allThreads[i].failed)
81           return true;
82       return false;
83     }
84   }
85
86   private static class IndexerThread extends TimedThread {
87     IndexWriter writer;
88     public IndexerThread(IndexWriter writer, TimedThread[] threads) {
89       super(threads);
90       this.writer = writer;
91     }
92
93     @Override
94     public void doWork() throws Exception {
95       // Update all 100 docs...
96       for(int i=0; i<100; i++) {
97         Document d = new Document();
98         d.add(new Field("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
99         d.add(new Field("contents", English.intToEnglish(i+10*count), Field.Store.NO, Field.Index.ANALYZED));
100         writer.updateDocument(new Term("id", Integer.toString(i)), d);
101       }
102     }
103   }
104
105   private static class SearcherThread extends TimedThread {
106     private Directory directory;
107
108     public SearcherThread(Directory directory, TimedThread[] threads) {
109       super(threads);
110       this.directory = directory;
111     }
112
113     @Override
114     public void doWork() throws Throwable {
115       IndexReader r = IndexReader.open(directory, true);
116       assertEquals(100, r.numDocs());
117       r.close();
118     }
119   }
120
121   /*
122     Run one indexer and 2 searchers against single index as
123     stress test.
124   */
125   public void runTest(Directory directory) throws Exception {
126
127     TimedThread[] threads = new TimedThread[4];
128
129     IndexWriterConfig conf = new IndexWriterConfig(
130         TEST_VERSION_CURRENT, new MockAnalyzer(random))
131         .setMaxBufferedDocs(7);
132     ((TieredMergePolicy) conf.getMergePolicy()).setMaxMergeAtOnce(3);
133     IndexWriter writer = new MockIndexWriter(directory, conf);
134     writer.setInfoStream(VERBOSE ? System.out : null);
135
136     // Establish a base index of 100 docs:
137     for(int i=0;i<100;i++) {
138       Document d = new Document();
139       d.add(newField("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
140       d.add(newField("contents", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED));
141       if ((i-1)%7 == 0) {
142         writer.commit();
143       }
144       writer.addDocument(d);
145     }
146     writer.commit();
147
148     IndexReader r = IndexReader.open(directory, true);
149     assertEquals(100, r.numDocs());
150     r.close();
151
152     IndexerThread indexerThread = new IndexerThread(writer, threads);
153     threads[0] = indexerThread;
154     indexerThread.start();
155     
156     IndexerThread indexerThread2 = new IndexerThread(writer, threads);
157     threads[1] = indexerThread2;
158     indexerThread2.start();
159       
160     SearcherThread searcherThread1 = new SearcherThread(directory, threads);
161     threads[2] = searcherThread1;
162     searcherThread1.start();
163
164     SearcherThread searcherThread2 = new SearcherThread(directory, threads);
165     threads[3] = searcherThread2;
166     searcherThread2.start();
167
168     indexerThread.join();
169     indexerThread2.join();
170     searcherThread1.join();
171     searcherThread2.join();
172
173     writer.close();
174
175     assertTrue("hit unexpected exception in indexer", !indexerThread.failed);
176     assertTrue("hit unexpected exception in indexer2", !indexerThread2.failed);
177     assertTrue("hit unexpected exception in search1", !searcherThread1.failed);
178     assertTrue("hit unexpected exception in search2", !searcherThread2.failed);
179     //System.out.println("    Writer: " + indexerThread.count + " iterations");
180     //System.out.println("Searcher 1: " + searcherThread1.count + " searchers created");
181     //System.out.println("Searcher 2: " + searcherThread2.count + " searchers created");
182   }
183
184   /*
185     Run above stress test against RAMDirectory and then
186     FSDirectory.
187   */
188   public void testAtomicUpdates() throws Exception {
189     MockIndexWriter.RANDOM = random;
190     Directory directory;
191
192     // First in a RAM directory:
193     directory = new MockDirectoryWrapper(random, new RAMDirectory());
194     runTest(directory);
195     directory.close();
196
197     // Second in an FSDirectory:
198     File dirPath = _TestUtil.getTempDir("lucene.test.atomic");
199     directory = newFSDirectory(dirPath);
200     runTest(directory);
201     directory.close();
202     _TestUtil.rmDir(dirPath);
203   }
204 }