mirror of https://github.com/apache/lucene.git
LUCENE-1262: fix issue that causes BufferedIndexInput to return incorrect bytes after exception was hit during refill
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@647639 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
360051ec49
commit
a6ff3c93df
|
@ -89,6 +89,11 @@ Bug fixes
|
|||
|
||||
6. LUCENE-1228: IndexWriter.commit() was not updating the index version and as
|
||||
result IndexReader.reopen() failed to sense index changes. (Doron Cohen)
|
||||
|
||||
7. LUCENE-1262: Fixed bug in BufferedIndexReader.refill whereby on
|
||||
hitting an exception in readInternal, the buffer is incorrectly
|
||||
filled with stale bytes such that subsequent calls to readByte()
|
||||
return incorrect results. (Trejkaz via Mike McCandless)
|
||||
|
||||
New features
|
||||
|
||||
|
|
|
@ -141,16 +141,16 @@ public abstract class BufferedIndexInput extends IndexInput {
|
|||
long end = start + bufferSize;
|
||||
if (end > length()) // don't read past EOF
|
||||
end = length();
|
||||
bufferLength = (int)(end - start);
|
||||
if (bufferLength <= 0)
|
||||
int newLength = (int)(end - start);
|
||||
if (newLength <= 0)
|
||||
throw new IOException("read past EOF");
|
||||
|
||||
if (buffer == null) {
|
||||
buffer = new byte[bufferSize]; // allocate buffer lazily
|
||||
seekInternal(bufferStart);
|
||||
}
|
||||
readInternal(buffer, 0, bufferLength);
|
||||
|
||||
readInternal(buffer, 0, newLength);
|
||||
bufferLength = newLength;
|
||||
bufferStart = start;
|
||||
bufferPosition = 0;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,10 @@ import org.apache.lucene.util.LuceneTestCase;
|
|||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.document.*;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.IndexInput;
|
||||
import org.apache.lucene.store.IndexOutput;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.BufferedIndexInput;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
import org.apache.lucene.util._TestUtil;
|
||||
|
@ -298,4 +302,114 @@ public class TestFieldsReader extends LuceneTestCase {
|
|||
assertEquals((byte) size , sizebytes[3]);
|
||||
}
|
||||
|
||||
public static class FaultyFSDirectory extends Directory {
|
||||
|
||||
FSDirectory fsDir;
|
||||
public FaultyFSDirectory(File dir) throws IOException {
|
||||
fsDir = FSDirectory.getDirectory(dir);
|
||||
lockFactory = fsDir.getLockFactory();
|
||||
}
|
||||
public IndexInput openInput(String name) throws IOException {
|
||||
return new FaultyIndexInput(fsDir.openInput(name));
|
||||
}
|
||||
public String[] list() throws IOException {
|
||||
return fsDir.list();
|
||||
}
|
||||
public boolean fileExists(String name) throws IOException {
|
||||
return fsDir.fileExists(name);
|
||||
}
|
||||
public long fileModified(String name) throws IOException {
|
||||
return fsDir.fileModified(name);
|
||||
}
|
||||
public void touchFile(String name) throws IOException {
|
||||
fsDir.touchFile(name);
|
||||
}
|
||||
public void deleteFile(String name) throws IOException {
|
||||
fsDir.deleteFile(name);
|
||||
}
|
||||
public void renameFile(String name, String newName) throws IOException {
|
||||
fsDir.renameFile(name, newName);
|
||||
}
|
||||
public long fileLength(String name) throws IOException {
|
||||
return fsDir.fileLength(name);
|
||||
}
|
||||
public IndexOutput createOutput(String name) throws IOException {
|
||||
return fsDir.createOutput(name);
|
||||
}
|
||||
public void close() throws IOException {
|
||||
fsDir.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FaultyIndexInput extends BufferedIndexInput {
|
||||
IndexInput delegate;
|
||||
static boolean doFail;
|
||||
int count;
|
||||
private FaultyIndexInput(IndexInput delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
private void simOutage() throws IOException {
|
||||
if (doFail && count++ % 2 == 1) {
|
||||
throw new IOException("Simulated network outage");
|
||||
}
|
||||
}
|
||||
public void readInternal(byte[] b, int offset, int length) throws IOException {
|
||||
simOutage();
|
||||
delegate.readBytes(b, offset, length);
|
||||
}
|
||||
public void seekInternal(long pos) throws IOException {
|
||||
//simOutage();
|
||||
delegate.seek(pos);
|
||||
}
|
||||
public long length() {
|
||||
return delegate.length();
|
||||
}
|
||||
public void close() throws IOException {
|
||||
delegate.close();
|
||||
}
|
||||
}
|
||||
|
||||
// LUCENE-1262
|
||||
public void testExceptions() throws Throwable {
|
||||
String tempDir = System.getProperty("java.io.tmpdir");
|
||||
if (tempDir == null)
|
||||
throw new IOException("java.io.tmpdir undefined, cannot run test");
|
||||
File indexDir = new File(tempDir, "testfieldswriterexceptions");
|
||||
|
||||
try {
|
||||
Directory dir = new FaultyFSDirectory(indexDir);
|
||||
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
|
||||
for(int i=0;i<2;i++)
|
||||
writer.addDocument(testDoc);
|
||||
writer.optimize();
|
||||
writer.close();
|
||||
|
||||
IndexReader reader = IndexReader.open(dir);
|
||||
|
||||
FaultyIndexInput.doFail = true;
|
||||
|
||||
boolean exc = false;
|
||||
|
||||
for(int i=0;i<2;i++) {
|
||||
try {
|
||||
reader.document(i);
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
exc = true;
|
||||
}
|
||||
try {
|
||||
reader.document(i);
|
||||
} catch (IOException ioe) {
|
||||
// expected
|
||||
exc = true;
|
||||
}
|
||||
}
|
||||
assertTrue(exc);
|
||||
reader.close();
|
||||
dir.close();
|
||||
} finally {
|
||||
_TestUtil.rmDir(indexDir);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue