pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / backwards / src / test / org / apache / lucene / index / TestIndexReaderOnDiskFull.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.IOException;
21
22 import org.apache.lucene.analysis.MockAnalyzer;
23 import org.apache.lucene.document.Document;
24 import org.apache.lucene.document.Field;
25 import org.apache.lucene.search.DefaultSimilarity;
26 import org.apache.lucene.search.IndexSearcher;
27 import org.apache.lucene.search.ScoreDoc;
28 import org.apache.lucene.search.Similarity;
29 import org.apache.lucene.search.TermQuery;
30 import org.apache.lucene.store.MockDirectoryWrapper;
31 import org.apache.lucene.store.RAMDirectory;
32 import org.apache.lucene.util.LuceneTestCase;
33 import org.apache.lucene.util._TestUtil;
34
35 public class TestIndexReaderOnDiskFull extends LuceneTestCase {
36   /**
37    * Make sure if reader tries to commit but hits disk
38    * full that reader remains consistent and usable.
39    */
40   public void testDiskFull() throws IOException {
41
42     Term searchTerm = new Term("content", "aaa");
43     int START_COUNT = 157;
44     int END_COUNT = 144;
45     
46     // First build up a starting index:
47     MockDirectoryWrapper startDir = newDirectory();
48     IndexWriter writer = new IndexWriter(startDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
49     if (VERBOSE) {
50       System.out.println("TEST: create initial index");
51       writer.setInfoStream(System.out);
52     }
53     for(int i=0;i<157;i++) {
54       Document d = new Document();
55       d.add(newField("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
56       d.add(newField("content", "aaa " + i, Field.Store.NO, Field.Index.ANALYZED));
57       writer.addDocument(d);
58       if (0==i%10)
59         writer.commit();
60     }
61     writer.close();
62
63     {
64       IndexReader r = IndexReader.open(startDir);
65       IndexSearcher searcher = newSearcher(r);
66       ScoreDoc[] hits = null;
67       try {
68         hits = searcher.search(new TermQuery(searchTerm), null, 1000).scoreDocs;
69       } catch (IOException e) {
70         e.printStackTrace();
71         fail("exception when init searching: " + e);
72       }
73       searcher.close();
74       r.close();
75     }
76
77     long diskUsage = startDir.getRecomputedActualSizeInBytes();
78     long diskFree = diskUsage+_TestUtil.nextInt(random, 50, 200);
79
80     IOException err = null;
81
82     boolean done = false;
83     boolean gotExc = false;
84
85     // Iterate w/ ever increasing free disk space:
86     while(!done) {
87       MockDirectoryWrapper dir = new MockDirectoryWrapper(random, new RAMDirectory(startDir));
88
89       // If IndexReader hits disk full, it can write to
90       // the same files again.
91       dir.setPreventDoubleWrite(false);
92
93       IndexReader reader = IndexReader.open(dir, false);
94
95       // For each disk size, first try to commit against
96       // dir that will hit random IOExceptions & disk
97       // full; after, give it infinite disk space & turn
98       // off random IOExceptions & retry w/ same reader:
99       boolean success = false;
100
101       for(int x=0;x<2;x++) {
102
103         double rate = 0.05;
104         double diskRatio = ((double) diskFree)/diskUsage;
105         long thisDiskFree;
106         String testName;
107
108         if (0 == x) {
109           thisDiskFree = diskFree;
110           if (diskRatio >= 2.0) {
111             rate /= 2;
112           }
113           if (diskRatio >= 4.0) {
114             rate /= 2;
115           }
116           if (diskRatio >= 6.0) {
117             rate = 0.0;
118           }
119           if (VERBOSE) {
120             System.out.println("\ncycle: " + diskFree + " bytes");
121           }
122           testName = "disk full during reader.close() @ " + thisDiskFree + " bytes";
123         } else {
124           thisDiskFree = 0;
125           rate = 0.0;
126           if (VERBOSE) {
127             System.out.println("\ncycle: same writer: unlimited disk space");
128           }
129           testName = "reader re-use after disk full";
130         }
131
132         dir.setMaxSizeInBytes(thisDiskFree);
133         dir.setRandomIOExceptionRate(rate);
134         Similarity sim = new DefaultSimilarity();
135         try {
136           if (0 == x) {
137             int docId = 12;
138             for(int i=0;i<13;i++) {
139               reader.deleteDocument(docId);
140               reader.setNorm(docId, "content", sim.encodeNormValue(2.0f));
141               docId += 12;
142             }
143           }
144           reader.close();
145           success = true;
146           if (0 == x) {
147             done = true;
148           }
149         } catch (IOException e) {
150           if (VERBOSE) {
151             System.out.println("  hit IOException: " + e);
152             e.printStackTrace(System.out);
153           }
154           err = e;
155           gotExc = true;
156           if (1 == x) {
157             e.printStackTrace();
158             fail(testName + " hit IOException after disk space was freed up");
159           }
160         }
161
162         // Finally, verify index is not corrupt, and, if
163         // we succeeded, we see all docs changed, and if
164         // we failed, we see either all docs or no docs
165         // changed (transactional semantics):
166         IndexReader newReader = null;
167         try {
168           newReader = IndexReader.open(dir, false);
169         } catch (IOException e) {
170           e.printStackTrace();
171           fail(testName + ":exception when creating IndexReader after disk full during close: " + e);
172         }
173         /*
174         int result = newReader.docFreq(searchTerm);
175         if (success) {
176           if (result != END_COUNT) {
177             fail(testName + ": method did not throw exception but docFreq('aaa') is " + result + " instead of expected " + END_COUNT);
178           }
179         } else {
180           // On hitting exception we still may have added
181           // all docs:
182           if (result != START_COUNT && result != END_COUNT) {
183             err.printStackTrace();
184             fail(testName + ": method did throw exception but docFreq('aaa') is " + result + " instead of expected " + START_COUNT + " or " + END_COUNT);
185           }
186         }
187         */
188
189         IndexSearcher searcher = newSearcher(newReader);
190         ScoreDoc[] hits = null;
191         try {
192           hits = searcher.search(new TermQuery(searchTerm), null, 1000).scoreDocs;
193         } catch (IOException e) {
194           e.printStackTrace();
195           fail(testName + ": exception when searching: " + e);
196         }
197         int result2 = hits.length;
198         if (success) {
199           if (result2 != END_COUNT) {
200             fail(testName + ": method did not throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + END_COUNT);
201           }
202         } else {
203           // On hitting exception we still may have added
204           // all docs:
205           if (result2 != START_COUNT && result2 != END_COUNT) {
206             err.printStackTrace();
207             fail(testName + ": method did throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + START_COUNT);
208           }
209         }
210
211         searcher.close();
212         newReader.close();
213
214         if (result2 == END_COUNT) {
215           if (!gotExc)
216             fail("never hit disk full");
217           break;
218         }
219       }
220
221       dir.close();
222
223       // Try again with more bytes of free space:
224       diskFree += TEST_NIGHTLY ? _TestUtil.nextInt(random, 5, 20) : _TestUtil.nextInt(random, 50, 200);
225     }
226
227     startDir.close();
228   }
229 }