Index: lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java (revision 1530072) +++ lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java (working copy) @@ -102,11 +102,13 @@ @Override public void writeBytes(byte[] b, int offset, int length) throws IOException { final long before = System.nanoTime(); + // TODO: sometimes, write only half the bytes, then + // sleep, then 2nd half, then sleep, so we sometimes + // interrupt having only written not all bytes delegate.writeBytes(b, offset, length); timeElapsed += System.nanoTime() - before; pendingBytes += length; sleep(getDelay(false)); - } protected long getDelay(boolean closing) { Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java (revision 1530072) +++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java (working copy) @@ -322,7 +322,7 @@ int value = 100; try { latch.await(); - for (int i = 0; i < 1000; i++) { + for (int j = 0; j < 1000; j++) { Document doc = new Document(); doc.add(newTextField("content", "aaa", Field.Store.NO)); doc.add(newStringField("id", String.valueOf(id++), Field.Store.YES)); @@ -1221,10 +1221,11 @@ private static class FakeIOException extends IOException { } - // Make sure if we hit disk full, and then later disk - // frees up, and we successfully close IW or open an NRT + // Make sure if we hit a transient IOException (e.g., disk + // full), and then the exception stops (e.g., disk frees + // up), so we successfully close IW or open an NRT // reader, we don't lose any deletes: - public void testNoLostDeletesOnDiskFull() throws Exception { + public void testNoLostDeletesOnIOException() throws Exception { int deleteCount = 0; int docBase = 0; @@ -1237,35 +1238,60 @@ @Override public void eval(MockDirectoryWrapper dir) throws IOException { StackTraceElement[] trace = new Exception().getStackTrace(); - if (shouldFail.get()) { - for (int i = 0; i < trace.length; i++) { - if ("writeLiveDocs".equals(trace[i].getMethodName())) { - // Only sometimes throw the exc, so we get - // it sometimes on creating the file, on - // flushing buffer, on closing the file: - if (random().nextInt(3) == 2) { - if (VERBOSE) { - System.out.println("TEST: now fail; exc:"); - new Throwable().printStackTrace(System.out); - } - shouldFail.set(false); - throw new FakeIOException(); - } else { - break; - } - } + if (shouldFail.get() == false) { + return; + } + + boolean sawSeal = false; + boolean sawWrite = false; + for (int i = 0; i < trace.length; i++) { + if ("sealFlushedSegment".equals(trace[i].getMethodName())) { + sawSeal = true; + break; } + if ("writeLiveDocs".equals(trace[i].getMethodName())) { + sawWrite = true; + } } + + // Don't throw exc if we are "flushing", else + // the segment is aborted and docs are lost: + if (sawWrite && sawSeal == false && random().nextInt(3) == 2) { + // Only sometimes throw the exc, so we get + // it sometimes on creating the file, on + // flushing buffer, on closing the file: + if (VERBOSE) { + System.out.println("TEST: now fail; thread=" + Thread.currentThread().getName() + " exc:"); + new Throwable().printStackTrace(System.out); + } + shouldFail.set(false); + throw new FakeIOException(); + } } }); + RandomIndexWriter w = null; + for(int iter=0;iter<10*RANDOM_MULTIPLIER;iter++) { int numDocs = atLeast(100); if (VERBOSE) { - System.out.println("\nTEST: iter=" + iter + " numDocs=" + numDocs + " docBase=" + docBase); + System.out.println("\nTEST: iter=" + iter + " numDocs=" + numDocs + " docBase=" + docBase + " delCount=" + deleteCount); } IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())); - IndexWriter w = new IndexWriter(dir, iwc); + MergeScheduler ms = iwc.getMergeScheduler(); + if (ms instanceof ConcurrentMergeScheduler) { + // TODO: better to subclass CMS, carry over all + // settigns that newIWC set, and ONLY suppress + // FakeIOExc: + ((ConcurrentMergeScheduler) ms).setSuppressExceptions(); + } + if (w == null) { + w = new RandomIndexWriter(random(), dir, iwc); + // Since we hit exc during merging, a partial + // forceMerge can easily return when there are still + // too many segments in the index: + w.setDoRandomForceMergeAssert(false); + } for(int i=0;i