Index: lucene/core/src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (revision 1564833) +++ lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -4643,6 +4643,14 @@ } + synchronized void incRefDeleter(SegmentInfos segmentInfos) throws IOException { + deleter.incRef(segmentInfos, false); + } + + synchronized void decRefDeleter(SegmentInfos segmentInfos) throws IOException { + deleter.decRef(segmentInfos); + } + private boolean processEvents(boolean triggerMerge, boolean forcePurge) throws IOException { return processEvents(eventQueue, triggerMerge, forcePurge); } @@ -4680,4 +4688,5 @@ */ void process(IndexWriter writer, boolean triggerMerge, boolean clearBuffers) throws IOException; } + } Index: lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java (revision 1564833) +++ lucene/core/src/java/org/apache/lucene/index/StandardDirectoryReader.java (working copy) @@ -107,6 +107,9 @@ writer.readerPool.release(rld); } } + + writer.incRefDeleter(segmentInfos); + StandardDirectoryReader result = new StandardDirectoryReader(dir, readers.toArray(new SegmentReader[readers.size()]), writer, segmentInfos, applyAllDeletes); @@ -362,6 +365,8 @@ } if (writer != null) { + writer.decRefDeleter(segmentInfos); + // Since we just closed, writer may now be able to // delete unused files: writer.deletePendingFiles(); Index: lucene/core/src/test/org/apache/lucene/index/TestNRTReaderWithThreads.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestNRTReaderWithThreads.java (revision 1564833) +++ lucene/core/src/test/org/apache/lucene/index/TestNRTReaderWithThreads.java (working copy) @@ -23,6 +23,7 @@ import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.store.Directory; +import org.apache.lucene.store.MockDirectoryWrapper; import org.apache.lucene.util.LuceneTestCase; public class TestNRTReaderWithThreads extends LuceneTestCase { @@ -30,6 +31,9 @@ public void testIndexing() throws Exception { Directory mainDir = newDirectory(); + if (mainDir instanceof MockDirectoryWrapper) { + ((MockDirectoryWrapper)mainDir).setAssertNoDeleteOpenFile(true); + } IndexWriter writer = new IndexWriter( mainDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())). Index: lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java (revision 1564833) +++ lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java (working copy) @@ -70,6 +70,7 @@ double randomIOExceptionRateOnOpen; Random randomState; boolean noDeleteOpenFile = true; + boolean assertNoDeleteOpenFile = false; boolean preventDoubleWrite = true; boolean trackDiskUsage = false; boolean wrapLockFactory = true; @@ -316,9 +317,22 @@ public void setNoDeleteOpenFile(boolean value) { this.noDeleteOpenFile = value; } + public boolean getNoDeleteOpenFile() { return noDeleteOpenFile; } + + /** + * Trip a test assert if there is an attempt + * to delete an open file. + */ + public void setAssertNoDeleteOpenFile(boolean value) { + this.assertNoDeleteOpenFile = value; + } + + public boolean getAssertNoDeleteOpenFile() { + return assertNoDeleteOpenFile; + } /** * If 0.0, no exceptions will be thrown. Else this should @@ -410,10 +424,16 @@ if (unSyncedFiles.contains(name)) unSyncedFiles.remove(name); - if (!forced && noDeleteOpenFile) { + if (!forced && (noDeleteOpenFile || assertNoDeleteOpenFile)) { if (openFiles.containsKey(name)) { openFilesDeleted.add(name); - throw fillOpenTrace(new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot delete"), name, true); + IOException ex = fillOpenTrace(new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot delete"), name, true); + if (!assertNoDeleteOpenFile) { + throw ex; + } else { + ex.printStackTrace(); + assert false : "MockDirectoryWrapper: file \"" + name + "\" is still open: cannot delete"; + } } else { openFilesDeleted.remove(name); } @@ -448,8 +468,12 @@ throw new IOException("file \"" + name + "\" was already written to"); } } - if (noDeleteOpenFile && openFiles.containsKey(name)) { - throw new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot overwrite"); + if ((noDeleteOpenFile || assertNoDeleteOpenFile) && openFiles.containsKey(name)) { + if (!assertNoDeleteOpenFile) { + throw new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot overwrite"); + } else { + assert false : "MockDirectoryWrapper: file \"" + name + "\" is still open: cannot overwrite"; + } } if (crashed) { @@ -612,7 +636,7 @@ openFiles = new HashMap(); openFilesDeleted = new HashSet(); } - if (noDeleteOpenFile && openFiles.size() > 0) { + if ((noDeleteOpenFile || assertNoDeleteOpenFile) && openFiles.size() > 0) { // print the first one as its very verbose otherwise Exception cause = null; Iterator stacktraces = openFileHandles.values().iterator(); @@ -620,10 +644,19 @@ cause = stacktraces.next(); // RuntimeException instead of IOException because // super() does not throw IOException currently: - throw new RuntimeException("MockDirectoryWrapper: cannot close: there are still open files: " + openFiles, cause); + if (!assertNoDeleteOpenFile) { + throw new RuntimeException("MockDirectoryWrapper: cannot close: there are still open files: " + openFiles, cause); + } else { + cause.printStackTrace(); + assert false : "MockDirectoryWrapper: cannot close: there are still open files: " + openFiles; + } } - if (noDeleteOpenFile && openLocks.size() > 0) { - throw new RuntimeException("MockDirectoryWrapper: cannot close: there are still open locks: " + openLocks); + if ((noDeleteOpenFile || assertNoDeleteOpenFile) && openLocks.size() > 0) { + if (!assertNoDeleteOpenFile) { + throw new RuntimeException("MockDirectoryWrapper: cannot close: there are still open locks: " + openLocks); + } else { + assert false : "MockDirectoryWrapper: cannot close: there are still open locks: " + openLocks; + } } isOpen = false;