Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java (revision 1458959) +++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java (working copy) @@ -17,6 +17,7 @@ * limitations under the License. */ +import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.StringReader; @@ -1627,4 +1628,75 @@ iw.close(); dir.close(); } + + public void testTooManyFileException() throws Exception { + + // Create failure that throws Too many open files exception randomly + MockDirectoryWrapper.Failure failure = new MockDirectoryWrapper.Failure() { + + @Override + public MockDirectoryWrapper.Failure reset() { + doFail = false; + return this; + } + + @Override + public void eval(MockDirectoryWrapper dir) throws IOException { + if (doFail) { + if (random().nextBoolean()) { + throw new FileNotFoundException("some/file/name.ext (Too many open files)"); + } + } + } + }; + + MockDirectoryWrapper dir = newMockDirectory(); + // The exception is only thrown on open input + dir.setFailOnOpenInput(true); + dir.failOn(failure); + + // Create an index with one document + IndexWriterConfig iwc = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())); + IndexWriter iw = new IndexWriter(dir, iwc); + Document doc = new Document(); + doc.add(new StringField("foo", "bar", Field.Store.NO)); + iw.addDocument(doc); // add a document + iw.commit(); + DirectoryReader ir = DirectoryReader.open(dir); + assertEquals(1, ir.numDocs()); + ir.close(); + iw.close(); + + // Open and close the index a few times + for (int i = 0; i < 1000; i++) { + failure.setDoFail(); + iwc = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())); +// iwc.setOpenMode(OpenMode.APPEND); // the test passes with APPEND!! + //iwc.setInfoStream(System.out); + try { + iw = new IndexWriter(dir, iwc); + } catch (CorruptIndexException ex) { + // Exceptions are fine - we are running out of file handlers here + continue; + } catch (FileNotFoundException ex) { + continue; + } + failure.clearDoFail(); + iw.close(); + ir = DirectoryReader.open(dir); + assertEquals("lost document after iteration: " + i, 1, ir.numDocs()); + ir.close(); + } + + // Check if document is still there + failure.clearDoFail(); + ir = DirectoryReader.open(dir); + assertEquals(1, ir.numDocs()); + ir.close(); + + dir.close(); + } + + + } Index: lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java (revision 1458959) +++ lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java (working copy) @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; +import org.apache.lucene.index.SegmentInfos.FindSegmentsFile; import org.apache.lucene.search.SearcherManager; // javadocs import org.apache.lucene.store.Directory; @@ -319,7 +320,20 @@ */ public static boolean indexExists(Directory directory) { try { - new SegmentInfos().read(directory); + new FindSegmentsFile(directory) { + @Override + protected Object doBody(String segmentFileName) throws IOException { + try { + new SegmentInfos().read(directory, segmentFileName); + } catch (FileNotFoundException ex) { + if (!directory.fileExists(segmentFileName)) { + throw ex; + } + // this is ok - we might have run into a access exception here. + } + return null; + } + }.run(); return true; } catch (IOException ioe) { return false; Index: lucene/CHANGES.txt =================================================================== --- lucene/CHANGES.txt (revision 1458959) +++ lucene/CHANGES.txt (working copy) @@ -155,6 +155,11 @@ * SOLR-4589: Fixed CPU spikes and poor performance in lazy field loading of multivalued fields. (hossman) +* LUCENE-4870: Fix bug where an entire index might be deleted by the IndexWriter + due to false detection if an index exists in the directory when + OpenMode.CREATE_OR_APPEND is used. This might also affect application that set + the open mode manually using DirectoryReader#indexExists. (Simon Willnauer) + Optimizations * LUCENE-4819: Added Sorted[Set]DocValues.termsEnum(), and optimized the