LUCENE-1453: make sure reopen of IndexReaders that own the directory don't close the directory too soon

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@718540 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2008-11-18 09:57:51 +00:00
parent 0beb6bd966
commit 72e94add53
3 changed files with 98 additions and 8 deletions

View File

@ -28,6 +28,7 @@ import java.util.List;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.FSDirectory;
/**
* IndexReader implementation that has access to a Directory.
@ -147,7 +148,7 @@ abstract class DirectoryIndexReader extends IndexReader {
return this;
}
return (DirectoryIndexReader) new SegmentInfos.FindSegmentsFile(directory) {
final SegmentInfos.FindSegmentsFile finder = new SegmentInfos.FindSegmentsFile(directory) {
protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
SegmentInfos infos = new SegmentInfos();
@ -162,7 +163,35 @@ abstract class DirectoryIndexReader extends IndexReader {
return newReader;
}
}.run();
};
DirectoryIndexReader reader = null;
// While trying to reopen, we temporarily mark our
// closeDirectory as false. This way any exceptions hit
// partway while opening the reader, which is expected
// eg if writer is committing, won't close our
// directory. We restore this value below:
final boolean myCloseDirectory = closeDirectory;
closeDirectory = false;
try {
reader = (DirectoryIndexReader) finder.run();
} finally {
if (myCloseDirectory) {
assert directory instanceof FSDirectory;
// Restore my closeDirectory
closeDirectory = true;
if (reader != null && reader != this) {
// Success, and a new reader was actually opened
reader.closeDirectory = true;
// Clone the directory
reader.directory = FSDirectory.getDirectory(((FSDirectory) directory).getFile());
}
}
}
return reader;
}
/**

View File

@ -660,10 +660,13 @@ class SegmentReader extends DirectoryIndexReader {
if (storeCFSReader != null)
storeCFSReader.close();
// maybe close directory
super.doClose();
}
// In DirectoryIndexReader.reopen, our directory
// instance was made private to us (cloned), so we
// always call super.doClose to possibly close the
// directory:
super.doClose();
}
static boolean hasDeletions(SegmentInfo si) throws IOException {

View File

@ -27,8 +27,6 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import junit.framework.TestCase;
import org.apache.lucene.analysis.KeywordAnalyzer;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
@ -43,6 +41,7 @@ import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.util.LuceneTestCase;
public class TestIndexReaderReopen extends LuceneTestCase {
@ -603,7 +602,7 @@ public class TestIndexReaderReopen extends LuceneTestCase {
TestIndexReader.assertIndexEquals(index1, index2);
try {
ReaderCouple couple = refreshReader(index1, test, 0, true);
refreshReader(index1, test, 0, true);
fail("Expected exception not thrown.");
} catch (Exception e) {
// expected exception
@ -999,4 +998,63 @@ public class TestIndexReaderReopen extends LuceneTestCase {
indexDir = new File(tempDir, "IndexReaderReopen");
}
// LUCENE-1453
public void testFSDirectoryReopen() throws CorruptIndexException, IOException {
Directory dir1 = FSDirectory.getDirectory(indexDir);
createIndex(dir1, false);
dir1.close();
IndexReader ir = IndexReader.open(indexDir);
modifyIndex(3, ir.directory());
IndexReader newIr = ir.reopen();
modifyIndex(3, newIr.directory());
IndexReader newIr2 = newIr.reopen();
modifyIndex(3, newIr2.directory());
IndexReader newIr3 = newIr2.reopen();
ir.close();
newIr.close();
newIr2.close();
// shouldn't throw Directory AlreadyClosedException
modifyIndex(3, newIr3.directory());
newIr3.close();
}
// LUCENE-1453
public void testFSDirectoryReopen2() throws CorruptIndexException, IOException {
String tempDir = System.getProperty("java.io.tmpdir");
if (tempDir == null)
throw new IOException("java.io.tmpdir undefined, cannot run test");
File indexDir2 = new File(tempDir, "IndexReaderReopen2");
Directory dir1 = FSDirectory.getDirectory(indexDir2);
createIndex(dir1, false);
IndexReader lastReader = IndexReader.open(indexDir2);
Random r = new Random(42);
for(int i=0;i<10;i++) {
int mod = r.nextInt(5);
modifyIndex(mod, lastReader.directory());
IndexReader reader = lastReader.reopen();
if (reader != lastReader) {
lastReader.close();
lastReader = reader;
}
}
lastReader.close();
// Make sure we didn't pick up too many incRef's along
// the way -- this close should be the final close:
dir1.close();
try {
dir1.list();
fail("did not hit AlreadyClosedException");
} catch (AlreadyClosedException ace) {
// expected
}
}
}