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

« back to all changes in this revision

Viewing changes to lucene/src/test/org/apache/lucene/store/TestBufferedIndexInput.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.store;
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.FileOutputStream;
22
 
import java.io.IOException;
23
 
import java.io.OutputStream;
24
 
import java.util.ArrayList;
25
 
import java.util.List;
26
 
import java.util.Random;
27
 
 
28
 
import org.apache.lucene.analysis.MockAnalyzer;
29
 
import org.apache.lucene.document.Document;
30
 
import org.apache.lucene.document.Field;
31
 
import org.apache.lucene.index.IndexReader;
32
 
import org.apache.lucene.index.IndexWriter;
33
 
import org.apache.lucene.index.IndexWriterConfig;
34
 
import org.apache.lucene.index.Term;
35
 
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
36
 
import org.apache.lucene.search.IndexSearcher;
37
 
import org.apache.lucene.search.ScoreDoc;
38
 
import org.apache.lucene.search.TermQuery;
39
 
import org.apache.lucene.store.NIOFSDirectory.NIOFSIndexInput;
40
 
import org.apache.lucene.store.SimpleFSDirectory.SimpleFSIndexInput;
41
 
import org.apache.lucene.util.LuceneTestCase;
42
 
import org.apache.lucene.util._TestUtil;
43
 
import org.apache.lucene.util.ArrayUtil;
44
 
 
45
 
public class TestBufferedIndexInput extends LuceneTestCase {
46
 
  
47
 
  private static void writeBytes(File aFile, long size) throws IOException{
48
 
    OutputStream stream = null;
49
 
    try {
50
 
      stream = new FileOutputStream(aFile);
51
 
      for (int i = 0; i < size; i++) {
52
 
        stream.write(byten(i));  
53
 
      }
54
 
      stream.flush();
55
 
    } finally {
56
 
      if (stream != null) {
57
 
        stream.close();
58
 
      }
59
 
    }
60
 
  }
61
 
 
62
 
  private static final long TEST_FILE_LENGTH = 100*1024;
63
 
 
64
 
  // Call readByte() repeatedly, past the buffer boundary, and see that it
65
 
  // is working as expected.
66
 
  // Our input comes from a dynamically generated/ "file" - see
67
 
  // MyBufferedIndexInput below.
68
 
  public void testReadByte() throws Exception {
69
 
    MyBufferedIndexInput input = new MyBufferedIndexInput();
70
 
    for (int i = 0; i < BufferedIndexInput.BUFFER_SIZE * 10; i++) {
71
 
      assertEquals(input.readByte(), byten(i));
72
 
    }
73
 
  }
74
 
 
75
 
  // Call readBytes() repeatedly, with various chunk sizes (from 1 byte to
76
 
  // larger than the buffer size), and see that it returns the bytes we expect.
77
 
  // Our input comes from a dynamically generated "file" -
78
 
  // see MyBufferedIndexInput below.
79
 
  public void testReadBytes() throws Exception {
80
 
    MyBufferedIndexInput input = new MyBufferedIndexInput();
81
 
    runReadBytes(input, BufferedIndexInput.BUFFER_SIZE, random);
82
 
 
83
 
    // This tests the workaround code for LUCENE-1566 where readBytesInternal
84
 
    // provides a workaround for a JVM Bug that incorrectly raises a OOM Error
85
 
    // when a large byte buffer is passed to a file read.
86
 
    // NOTE: this does only test the chunked reads and NOT if the Bug is triggered.
87
 
    //final int tmpFileSize = 1024 * 1024 * 5;
88
 
    final int inputBufferSize = 128;
89
 
    File tmpInputFile = _TestUtil.createTempFile("IndexInput", "tmpFile", TEMP_DIR);
90
 
    tmpInputFile.deleteOnExit();
91
 
    writeBytes(tmpInputFile, TEST_FILE_LENGTH);
92
 
 
93
 
    // run test with chunk size of 10 bytes
94
 
    runReadBytesAndClose(new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + tmpInputFile + "\")", tmpInputFile,
95
 
                                                inputBufferSize, 10), inputBufferSize, random);
96
 
 
97
 
    // run test with chunk size of 10 bytes
98
 
    runReadBytesAndClose(new NIOFSIndexInput(tmpInputFile,
99
 
                                             inputBufferSize, 10), inputBufferSize, random);
100
 
  }
101
 
 
102
 
  private void runReadBytesAndClose(IndexInput input, int bufferSize, Random r)
103
 
      throws IOException {
104
 
    try {
105
 
      runReadBytes(input, bufferSize, r);
106
 
    } finally {
107
 
      input.close();
108
 
    }
109
 
  }
110
 
  
111
 
  private void runReadBytes(IndexInput input, int bufferSize, Random r)
112
 
      throws IOException {
113
 
 
114
 
    int pos = 0;
115
 
    // gradually increasing size:
116
 
    for (int size = 1; size < bufferSize * 10; size = size + size / 200 + 1) {
117
 
      checkReadBytes(input, size, pos);
118
 
      pos += size;
119
 
      if (pos >= TEST_FILE_LENGTH) {
120
 
        // wrap
121
 
        pos = 0;
122
 
        input.seek(0L);
123
 
      }
124
 
    }
125
 
    // wildly fluctuating size:
126
 
    for (long i = 0; i < 100; i++) {
127
 
      final int size = r.nextInt(10000);
128
 
      checkReadBytes(input, 1+size, pos);
129
 
      pos += 1+size;
130
 
      if (pos >= TEST_FILE_LENGTH) {
131
 
        // wrap
132
 
        pos = 0;
133
 
        input.seek(0L);
134
 
      }
135
 
    }
136
 
    // constant small size (7 bytes):
137
 
    for (int i = 0; i < bufferSize; i++) {
138
 
      checkReadBytes(input, 7, pos);
139
 
      pos += 7;
140
 
      if (pos >= TEST_FILE_LENGTH) {
141
 
        // wrap
142
 
        pos = 0;
143
 
        input.seek(0L);
144
 
      }
145
 
    }
146
 
  }
147
 
 
148
 
  private byte[] buffer = new byte[10];
149
 
    
150
 
  private void checkReadBytes(IndexInput input, int size, int pos) throws IOException{
151
 
    // Just to see that "offset" is treated properly in readBytes(), we
152
 
    // add an arbitrary offset at the beginning of the array
153
 
    int offset = size % 10; // arbitrary
154
 
    buffer = ArrayUtil.grow(buffer, offset+size);
155
 
    assertEquals(pos, input.getFilePointer());
156
 
    long left = TEST_FILE_LENGTH - input.getFilePointer();
157
 
    if (left <= 0) {
158
 
      return;
159
 
    } else if (left < size) {
160
 
      size = (int) left;
161
 
    }
162
 
    input.readBytes(buffer, offset, size);
163
 
    assertEquals(pos+size, input.getFilePointer());
164
 
    for(int i=0; i<size; i++) {
165
 
      assertEquals("pos=" + i + " filepos=" + (pos+i), byten(pos+i), buffer[offset+i]);
166
 
    }
167
 
  }
168
 
   
169
 
  // This tests that attempts to readBytes() past an EOF will fail, while
170
 
  // reads up to the EOF will succeed. The EOF is determined by the
171
 
  // BufferedIndexInput's arbitrary length() value.
172
 
  public void testEOF() throws Exception {
173
 
     MyBufferedIndexInput input = new MyBufferedIndexInput(1024);
174
 
     // see that we can read all the bytes at one go:
175
 
     checkReadBytes(input, (int)input.length(), 0);  
176
 
     // go back and see that we can't read more than that, for small and
177
 
     // large overflows:
178
 
     int pos = (int)input.length()-10;
179
 
     input.seek(pos);
180
 
     checkReadBytes(input, 10, pos);  
181
 
     input.seek(pos);
182
 
     try {
183
 
       checkReadBytes(input, 11, pos);
184
 
           fail("Block read past end of file");
185
 
       } catch (IOException e) {
186
 
           /* success */
187
 
       }
188
 
     input.seek(pos);
189
 
     try {
190
 
       checkReadBytes(input, 50, pos);
191
 
           fail("Block read past end of file");
192
 
       } catch (IOException e) {
193
 
           /* success */
194
 
       }
195
 
     input.seek(pos);
196
 
     try {
197
 
       checkReadBytes(input, 100000, pos);
198
 
           fail("Block read past end of file");
199
 
       } catch (IOException e) {
200
 
           /* success */
201
 
       }
202
 
  }
203
 
 
204
 
    // byten emulates a file - byten(n) returns the n'th byte in that file.
205
 
    // MyBufferedIndexInput reads this "file".
206
 
    private static byte byten(long n){
207
 
      return (byte)(n*n%256);
208
 
    }
209
 
    private static class MyBufferedIndexInput extends BufferedIndexInput {
210
 
      private long pos;
211
 
      private long len;
212
 
      public MyBufferedIndexInput(long len){
213
 
        super("MyBufferedIndexInput(len=" + len + ")", BufferedIndexInput.BUFFER_SIZE);
214
 
        this.len = len;
215
 
        this.pos = 0;
216
 
      }
217
 
      public MyBufferedIndexInput(){
218
 
        // an infinite file
219
 
        this(Long.MAX_VALUE);
220
 
      }
221
 
      @Override
222
 
      protected void readInternal(byte[] b, int offset, int length) throws IOException {
223
 
        for(int i=offset; i<offset+length; i++)
224
 
          b[i] = byten(pos++);
225
 
      }
226
 
 
227
 
      @Override
228
 
      protected void seekInternal(long pos) throws IOException {
229
 
        this.pos = pos;
230
 
      }
231
 
 
232
 
      @Override
233
 
      public void close() throws IOException {
234
 
      }
235
 
 
236
 
      @Override
237
 
      public long length() {
238
 
        return len;
239
 
      }
240
 
    }
241
 
 
242
 
    public void testSetBufferSize() throws IOException {
243
 
      File indexDir = _TestUtil.getTempDir("testSetBufferSize");
244
 
      MockFSDirectory dir = new MockFSDirectory(indexDir, random);
245
 
      try {
246
 
        IndexWriter writer = new IndexWriter(
247
 
            dir,
248
 
            new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).
249
 
                setOpenMode(OpenMode.CREATE).
250
 
                setMergePolicy(newLogMergePolicy(false))
251
 
        );
252
 
        for(int i=0;i<37;i++) {
253
 
          Document doc = new Document();
254
 
          doc.add(newField("content", "aaa bbb ccc ddd" + i, Field.Store.YES, Field.Index.ANALYZED));
255
 
          doc.add(newField("id", "" + i, Field.Store.YES, Field.Index.ANALYZED));
256
 
          writer.addDocument(doc);
257
 
        }
258
 
        writer.close();
259
 
 
260
 
        dir.allIndexInputs.clear();
261
 
 
262
 
        IndexReader reader = IndexReader.open(dir, false);
263
 
        Term aaa = new Term("content", "aaa");
264
 
        Term bbb = new Term("content", "bbb");
265
 
        Term ccc = new Term("content", "ccc");
266
 
        assertEquals(37, reader.docFreq(ccc));
267
 
        reader.deleteDocument(0);
268
 
        assertEquals(37, reader.docFreq(aaa));
269
 
        dir.tweakBufferSizes();
270
 
        reader.deleteDocument(4);
271
 
        assertEquals(reader.docFreq(bbb), 37);
272
 
        dir.tweakBufferSizes();
273
 
 
274
 
        IndexSearcher searcher = newSearcher(reader);
275
 
        ScoreDoc[] hits = searcher.search(new TermQuery(bbb), null, 1000).scoreDocs;
276
 
        dir.tweakBufferSizes();
277
 
        assertEquals(35, hits.length);
278
 
        dir.tweakBufferSizes();
279
 
        hits = searcher.search(new TermQuery(new Term("id", "33")), null, 1000).scoreDocs;
280
 
        dir.tweakBufferSizes();
281
 
        assertEquals(1, hits.length);
282
 
        hits = searcher.search(new TermQuery(aaa), null, 1000).scoreDocs;
283
 
        dir.tweakBufferSizes();
284
 
        assertEquals(35, hits.length);
285
 
        searcher.close();
286
 
        reader.close();
287
 
      } finally {
288
 
        _TestUtil.rmDir(indexDir);
289
 
      }
290
 
    }
291
 
 
292
 
    private static class MockFSDirectory extends Directory {
293
 
 
294
 
      List<IndexInput> allIndexInputs = new ArrayList<IndexInput>();
295
 
 
296
 
      Random rand;
297
 
 
298
 
      private Directory dir;
299
 
 
300
 
      public MockFSDirectory(File path, Random rand) throws IOException {
301
 
        this.rand = rand;
302
 
        lockFactory = NoLockFactory.getNoLockFactory();
303
 
        dir = new SimpleFSDirectory(path, null);
304
 
      }
305
 
 
306
 
      @Override
307
 
      public IndexInput openInput(String name) throws IOException {
308
 
        return openInput(name, BufferedIndexInput.BUFFER_SIZE);
309
 
      }
310
 
 
311
 
      public void tweakBufferSizes() {
312
 
        //int count = 0;
313
 
        for (final IndexInput ip : allIndexInputs) {
314
 
          BufferedIndexInput bii = (BufferedIndexInput) ip;
315
 
          int bufferSize = 1024+Math.abs(rand.nextInt() % 32768);
316
 
          bii.setBufferSize(bufferSize);
317
 
          //count++;
318
 
        }
319
 
        //System.out.println("tweak'd " + count + " buffer sizes");
320
 
      }
321
 
      
322
 
      @Override
323
 
      public IndexInput openInput(String name, int bufferSize) throws IOException {
324
 
        // Make random changes to buffer size
325
 
        bufferSize = 1+Math.abs(rand.nextInt() % 10);
326
 
        IndexInput f = dir.openInput(name, bufferSize);
327
 
        allIndexInputs.add(f);
328
 
        return f;
329
 
      }
330
 
 
331
 
      @Override
332
 
      public IndexOutput createOutput(String name) throws IOException {
333
 
        return dir.createOutput(name);
334
 
      }
335
 
 
336
 
      @Override
337
 
      public void close() throws IOException {
338
 
        dir.close();
339
 
      }
340
 
 
341
 
      @Override
342
 
      public void deleteFile(String name)
343
 
        throws IOException
344
 
      {
345
 
        dir.deleteFile(name);
346
 
      }
347
 
      @Override
348
 
      @Deprecated
349
 
      /*  @deprecated Lucene never uses this API; it will be
350
 
       *  removed in 4.0. */
351
 
      public void touchFile(String name)
352
 
        throws IOException
353
 
      {
354
 
        dir.touchFile(name);
355
 
      }
356
 
      @Override
357
 
      public long fileModified(String name)
358
 
        throws IOException
359
 
      {
360
 
        return dir.fileModified(name);
361
 
      }
362
 
      @Override
363
 
      public boolean fileExists(String name)
364
 
        throws IOException
365
 
      {
366
 
        return dir.fileExists(name);
367
 
      }
368
 
      @Override
369
 
      public String[] listAll()
370
 
        throws IOException
371
 
      {
372
 
        return dir.listAll();
373
 
      }
374
 
 
375
 
      @Override
376
 
      public long fileLength(String name) throws IOException {
377
 
        return dir.fileLength(name);
378
 
      }
379
 
 
380
 
 
381
 
    }
382
 
}