diff --git a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java index 3ae59280a68..bc0890747c0 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java +++ b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java @@ -60,7 +60,6 @@ import org.apache.lucene.util._TestUtil; * refusing to write/delete to open files. * */ - public class MockDirectoryWrapper extends BaseDirectoryWrapper { long maxSize; @@ -159,6 +158,26 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { this.throttling = throttling; } + /** + * Returns true if {@link #getDelegate() delegate} must sync its files. + * Currently, only {@link NRTCachingDirectory} requires sync'ing its files + * because otherwise they are cached in an internal {@link RAMDirectory}. If + * other directories require that too, they should be added to this method. + */ + private boolean mustSync() { + Directory delegate = this.delegate; + while (true) { + if (delegate instanceof RateLimitedDirectoryWrapper) { + delegate = ((RateLimitedDirectoryWrapper) delegate).getDelegate(); + } else if (delegate instanceof TrackingDirectoryWrapper) { + delegate = ((TrackingDirectoryWrapper) delegate).getDelegate(); + } else { + break; + } + } + return delegate instanceof NRTCachingDirectory; + } + @Override public synchronized void sync(Collection names) throws IOException { maybeYield(); @@ -166,12 +185,16 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { if (crashed) { throw new IOException("cannot sync after crash"); } - unSyncedFiles.removeAll(names); - // TODO: need to improve hack to be OK w/ - // RateLimitingDirWrapper in between... - if (true || LuceneTestCase.rarely(randomState) || delegate instanceof NRTCachingDirectory) { - // don't wear out our hardware so much in tests. - delegate.sync(names); + // don't wear out our hardware so much in tests. + if (LuceneTestCase.rarely(randomState) || mustSync()) { + for (String name : names) { + // randomly fail with IOE on any file + maybeThrowIOException(name); + delegate.sync(Collections.singleton(name)); + unSyncedFiles.remove(name); + } + } else { + unSyncedFiles.removeAll(names); } } @@ -343,10 +366,6 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { return randomIOExceptionRateOnOpen; } - void maybeThrowIOException() throws IOException { - maybeThrowIOException(null); - } - void maybeThrowIOException(String message) throws IOException { if (randomState.nextDouble() < randomIOExceptionRate) { if (LuceneTestCase.VERBOSE) { @@ -357,10 +376,10 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { } } - void maybeThrowIOExceptionOnOpen() throws IOException { + void maybeThrowIOExceptionOnOpen(String name) throws IOException { if (randomState.nextDouble() < randomIOExceptionRateOnOpen) { if (LuceneTestCase.VERBOSE) { - System.out.println(Thread.currentThread().getName() + ": MockDirectoryWrapper: now throw random exception during open"); + System.out.println(Thread.currentThread().getName() + ": MockDirectoryWrapper: now throw random exception during open file=" + name); new Throwable().printStackTrace(System.out); } if (randomState.nextBoolean()) { @@ -432,7 +451,7 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { @Override public synchronized IndexOutput createOutput(String name, IOContext context) throws IOException { maybeThrowDeterministicException(); - maybeThrowIOExceptionOnOpen(); + maybeThrowIOExceptionOnOpen(name); maybeYield(); if (failOnCreateOutput) { maybeThrowDeterministicException(); @@ -519,7 +538,7 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { @Override public synchronized IndexInput openInput(String name, IOContext context) throws IOException { maybeThrowDeterministicException(); - maybeThrowIOExceptionOnOpen(); + maybeThrowIOExceptionOnOpen(name); maybeYield(); if (failOnOpenInput) { maybeThrowDeterministicException(); @@ -632,7 +651,7 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper { if (LuceneTestCase.VERBOSE) { System.out.println("\nNOTE: MockDirectoryWrapper: now crash"); } - crash(); // corrumpt any unsynced-files + crash(); // corrupt any unsynced-files if (LuceneTestCase.VERBOSE) { System.out.println("\nNOTE: MockDirectoryWrapper: now run CheckIndex"); }