mirror of https://github.com/apache/lucene.git
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:
parent
0beb6bd966
commit
72e94add53
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue