Index: lucene/core/src/test/org/apache/lucene/TestDemo.java =================================================================== --- lucene/core/src/test/org/apache/lucene/TestDemo.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/TestDemo.java (working copy) @@ -53,6 +53,7 @@ String text = "This is the text to be indexed. " + longTerm; doc.add(newTextField("fieldname", text, Field.Store.YES)); iwriter.addDocument(doc); + System.out.println("TEST: now shutdown"); iwriter.shutdown(); // Now search the index: Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOutOfFileDescriptors.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOutOfFileDescriptors.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOutOfFileDescriptors.java (working copy) @@ -138,7 +138,10 @@ dir.copy(dirCopy, file, file, IOContext.DEFAULT); files.add(file); } - dirCopy.sync(files); + + // nocommit fixme! + //dirCopy.sync(files); + // Have IW kiss the dir so we remove any leftover // files ... we can easily have leftover files at // the time we take a copy because we are holding Index: lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java =================================================================== --- lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java (working copy) @@ -133,10 +133,6 @@ return fsDir.createOutput(name, context); } @Override - public void sync(Collection names) throws IOException { - fsDir.sync(names); - } - @Override public void close() throws IOException { fsDir.close(); } Index: lucene/core/src/test/org/apache/lucene/util/junitcompat/TestFailIfUnreferencedFiles.java =================================================================== --- lucene/core/src/test/org/apache/lucene/util/junitcompat/TestFailIfUnreferencedFiles.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/util/junitcompat/TestFailIfUnreferencedFiles.java (working copy) @@ -47,8 +47,8 @@ iw.shutdown(); IndexOutput output = dir.createOutput("_hello.world", IOContext.DEFAULT); output.writeString("i am unreferenced!"); + output.sync(); output.close(); - dir.sync(Collections.singleton("_hello.world")); dir.close(); } } Index: lucene/core/src/test/org/apache/lucene/store/TestDirectory.java =================================================================== --- lucene/core/src/test/org/apache/lucene/store/TestDirectory.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/store/TestDirectory.java (working copy) @@ -289,35 +289,5 @@ TestUtil.rm(path); } } - - public void testFsyncDoesntCreateNewFiles() throws Exception { - File path = createTempDir("nocreate"); - System.out.println(path.getAbsolutePath()); - Directory fsdir = new SimpleFSDirectory(path); - - // write a file - IndexOutput out = fsdir.createOutput("afile", newIOContext(random())); - out.writeString("boo"); - out.close(); - - // delete it - assertTrue(new File(path, "afile").delete()); - - // directory is empty - assertEquals(0, fsdir.listAll().length); - - // fsync it - try { - fsdir.sync(Collections.singleton("afile")); - fail("didn't get expected exception, instead fsync created new files: " + Arrays.asList(fsdir.listAll())); - } catch (FileNotFoundException | NoSuchFileException expected) { - // ok - } - - // directory is still empty - assertEquals(0, fsdir.listAll().length); - - fsdir.close(); - } } Index: lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java =================================================================== --- lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java (revision 1586145) +++ lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java (working copy) @@ -335,10 +335,6 @@ return dir.listAll(); } @Override - public void sync(Collection names) throws IOException { - dir.sync(names); - } - @Override public long fileLength(String name) throws IOException { return dir.fileLength(name); } Index: lucene/core/src/java/org/apache/lucene/util/IOUtils.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/IOUtils.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/util/IOUtils.java (working copy) @@ -368,34 +368,4 @@ throw new RuntimeException(th); } } - - /** - * Ensure that any writes to the given file is written to the storage device that contains it. - * @param fileToSync the file to fsync - */ - public static void fsync(File fileToSync) throws IOException { - IOException exc = null; - for (int retry = 0; retry < 5; retry++) { - try { - try (FileChannel file = FileChannel.open(fileToSync.toPath(), StandardOpenOption.WRITE)) { - file.force(true); // TODO: we probably dont care about metadata, but this is what we did before... - return; - } - } catch (IOException ioe) { - if (exc == null) { - exc = ioe; - } - try { - // Pause 5 msec - Thread.sleep(5); - } catch (InterruptedException ie) { - ThreadInterruptedException ex = new ThreadInterruptedException(ie); - ex.addSuppressed(exc); - throw ex; - } - } - } - // Throw original exception - throw exc; - } } Index: lucene/core/src/java/org/apache/lucene/store/RAMDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/RAMDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/RAMDirectory.java (working copy) @@ -183,10 +183,6 @@ return new RAMFile(this); } - @Override - public void sync(Collection names) throws IOException { - } - /** Returns a stream reading an existing file. */ @Override public IndexInput openInput(String name, IOContext context) throws IOException { Index: lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/CompoundFileDirectory.java (working copy) @@ -244,11 +244,6 @@ return writer.createOutput(name, context); } - @Override - public void sync(Collection names) { - throw new UnsupportedOperationException(); - } - /** Not implemented * @throws UnsupportedOperationException always: not supported by CFS */ @Override Index: lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/NRTCachingDirectory.java (working copy) @@ -176,6 +176,10 @@ return cache.listAll(); } + // nocommit this is now totally broken: we must make a + // wrapper (we need FilterIndexOutput!) that moves file + // from cache to real directory & syncs: + @Override public IndexOutput createOutput(String name, IOContext context) throws IOException { if (VERBOSE) { @@ -202,17 +206,6 @@ } @Override - public void sync(Collection fileNames) throws IOException { - if (VERBOSE) { - System.out.println("nrtdir.sync files=" + fileNames); - } - for(String fileName : fileNames) { - unCache(fileName); - } - delegate.sync(fileNames); - } - - @Override public synchronized IndexInput openInput(String name, IOContext context) throws IOException { if (VERBOSE) { System.out.println("nrtdir.openInput name=" + name); Index: lucene/core/src/java/org/apache/lucene/store/RAMOutputStream.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/RAMOutputStream.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/RAMOutputStream.java (working copy) @@ -108,6 +108,10 @@ } @Override + public void sync() { + } + + @Override public long length() { return file.length; } Index: lucene/core/src/java/org/apache/lucene/store/CompoundFileWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/CompoundFileWriter.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/CompoundFileWriter.java (working copy) @@ -304,6 +304,12 @@ } @Override + public void sync() throws IOException { + // nocommit? + delegate.sync(); + } + + @Override public void close() throws IOException { if (!closed) { closed = true; Index: lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/FileSwitchDirectory.java (working copy) @@ -148,21 +148,6 @@ } @Override - public void sync(Collection names) throws IOException { - List primaryNames = new ArrayList<>(); - List secondaryNames = new ArrayList<>(); - - for (String name : names) - if (primaryExtensions.contains(getExtension(name))) - primaryNames.add(name); - else - secondaryNames.add(name); - - primaryDir.sync(primaryNames); - secondaryDir.sync(secondaryNames); - } - - @Override public IndexInput openInput(String name, IOContext context) throws IOException { return getDirectory(name).openInput(name, context); } Index: lucene/core/src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -30,8 +30,6 @@ import java.util.Set; import java.util.concurrent.Future; -import static java.util.Collections.synchronizedSet; - /** * Base class for Directory implementations that store index * files in the file system. @@ -112,7 +110,6 @@ public abstract class FSDirectory extends BaseDirectory { protected final File directory; // The underlying filesystem directory - protected final Set staleFiles = synchronizedSet(new HashSet()); // Files written, but not yet sync'ed // returns the canonical version of the directory, creating it if it doesn't exist. private static File getCanonicalPath(File file) throws IOException { @@ -253,7 +250,6 @@ File file = new File(directory, name); if (!file.delete()) throw new IOException("Cannot delete " + file); - staleFiles.remove(name); } /** Creates an IndexOutput for the file with the given name. */ @@ -275,27 +271,7 @@ throw new IOException("Cannot overwrite: " + file); } - /** - * Sub classes should call this method on closing an open {@link IndexOutput}, reporting the name of the file - * that was closed. {@code FSDirectory} needs this information to take care of syncing stale files. - */ - protected void onIndexOutputClosed(String name) { - staleFiles.add(name); - } - @Override - public void sync(Collection names) throws IOException { - ensureOpen(); - Set toSync = new HashSet<>(names); - toSync.retainAll(staleFiles); - - for (String name : toSync) - fsync(name); - - staleFiles.removeAll(toSync); - } - - @Override public String getLockID() { ensureOpen(); String dirName; // name to be hashed @@ -355,6 +331,13 @@ } @Override + public void sync() throws IOException { + // nocommit ensureOpen (not assert)? + assert isOpen; + file.getFD().sync(); + } + + @Override protected void flushBuffer(byte[] b, int offset, int size) throws IOException { assert isOpen; while (size > 0) { @@ -368,7 +351,6 @@ @Override public void close() throws IOException { - parent.onIndexOutputClosed(name); // only close the file if it has not been closed yet if (isOpen) { IOException priorE = null; @@ -393,8 +375,4 @@ file.setLength(length); } } - - protected void fsync(String name) throws IOException { - IOUtils.fsync(new File(directory, name)); - } } Index: lucene/core/src/java/org/apache/lucene/store/IndexOutput.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/IndexOutput.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/IndexOutput.java (working copy) @@ -38,6 +38,13 @@ @Override public abstract void close() throws IOException; + // nocommit data vs metadata + // nocommit fsync the directory too? maybe add Directory.fsync()? + + /** Ensures all writes made in this IndexOutput are + * moved to durable storage. */ + public abstract void sync() throws IOException; + /** Returns the current position in this file, where the next write will * occur. */ Index: lucene/core/src/java/org/apache/lucene/store/SyncDirectoryWrapper.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/SyncDirectoryWrapper.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/store/SyncDirectoryWrapper.java (working copy) @@ -0,0 +1,128 @@ +package org.apache.lucene.store; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.lucene.util.IOUtils; + +/** Hangs onto all IndexOutputs, blocking close() when caller + * tries to, until they are later sync'd or deleted. */ + +public class SyncDirectoryWrapper extends FilterDirectory { + + private final Map pendingOutputs = Collections.synchronizedMap(new HashMap()); + + public SyncDirectoryWrapper(Directory in) { + super(in); + } + + @Override + public IndexOutput createOutput(final String fileName, IOContext context) throws IOException { + final IndexOutput out = super.createOutput(fileName, context); + pendingOutputs.put(fileName, out); + + // Just blocks close: + return new IndexOutput() { + + @Override + public void writeByte(byte b) throws IOException { + out.writeByte(b); + } + + @Override + public void writeBytes(byte[] b, int offset, int length) throws IOException { + out.writeBytes(b, offset, length); + } + + @Override + public void flush() throws IOException { + out.flush(); + } + + @Override + public void close() throws IOException { + // nocommit we could do some asserting based on + // this, e.g. that we don't try to sync nor delete + // the file until it was really closed + flush(); + } + + @Override + public void sync() throws IOException { + // nocommit try/finally? make sure tests throw + // exceptions here: + out.sync(); + } + + @Override + public long getFilePointer() { + return out.getFilePointer(); + } + + @Override + public long getChecksum() throws IOException { + return out.getChecksum(); + } + + @Override + public long length() throws IOException { + return out.length(); + } + + @Override + public void setLength(long length) throws IOException { + out.setLength(length); + } + }; + } + + @Override + public void deleteFile(String fileName) throws IOException { + // nocommit try/finally + IndexOutput out = pendingOutputs.remove(fileName); + if (out != null) { + System.out.println("SYNC: drop " + fileName + " during delete: " + out); + out.close(); + } + super.deleteFile(fileName); + } + + public void syncIfStillOpen(String fileName) throws IOException { + System.out.println("SYNC: syncIfStillOpen " + fileName); + IndexOutput out = pendingOutputs.get(fileName); + if (out != null) { + System.out.println(" now sync " + fileName); + out.sync(); + out.close(); + pendingOutputs.remove(fileName); + } + } + + @Override + public void close() throws IOException { + // NOTE: does not super.close() + // nocommit try/finally + // nocommit assert that this is empty...? + IOUtils.close(pendingOutputs.values()); + pendingOutputs.clear(); + } +} Property changes on: lucene/core/src/java/org/apache/lucene/store/SyncDirectoryWrapper.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/core/src/java/org/apache/lucene/store/Directory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/Directory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/Directory.java (working copy) @@ -78,19 +78,6 @@ public abstract IndexOutput createOutput(String name, IOContext context) throws IOException; - /** - * Ensure that any writes to these files are moved to - * stable storage. Lucene uses this to properly commit - * changes to the index, to prevent a machine/OS crash - * from corrupting the index.
- *
- * NOTE: Clients may call this method for same files over - * and over again, so some impls might optimize for that. - * For other impls the operation can be a noop, for various - * reasons. - */ - public abstract void sync(Collection names) throws IOException; - /** Returns a stream reading an existing file, with the * specified read buffer size. The particular Directory * implementation may ignore the buffer size. Currently Index: lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java (working copy) @@ -65,11 +65,6 @@ } @Override - public void sync(Collection names) throws IOException { - in.sync(names); - } - - @Override public IndexInput openInput(String name, IOContext context) throws IOException { return in.openInput(name, context); Index: lucene/core/src/java/org/apache/lucene/store/RateLimitedIndexOutput.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/RateLimitedIndexOutput.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/store/RateLimitedIndexOutput.java (working copy) @@ -39,6 +39,12 @@ } this.rateLimiter = rateLimiter; } + + @Override + public void sync() throws IOException { + flush(); + delegate.sync(); + } @Override protected void flushBuffer(byte[] b, int offset, int len) throws IOException { Index: lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java (working copy) @@ -198,12 +198,11 @@ // Suppress so we keep throwing original exception } } else { + out.sync(); IOUtils.close(out); } } - dir.sync(Collections.singletonList(fileName)); - if (nextWriteGen > 0) { String lastSaveFile = SNAPSHOTS_PREFIX + (nextWriteGen-1); try { Index: lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -271,8 +271,8 @@ genOutput.writeLong(generation); CodecUtil.writeFooter(genOutput); } finally { + genOutput.sync(); genOutput.close(); - dir.sync(Collections.singleton(IndexFileNames.SEGMENTS_GEN)); } } catch (Throwable t) { // It's OK if we fail to write this file since it's @@ -886,6 +886,16 @@ } else { success = false; try { + // NOTE: if we crash here, we have left a segments_N + // file in the directory in a possibly corrupt state (if + // some bytes made it to stable storage and others + // didn't). But, the segments_N file includes checksum + // at the end, which should catch this case. So when a + // reader tries to read it, it will throw a + // CorruptIndexException, which should cause the retry + // logic in SegmentInfos to kick in and load the last + // good (previous) segments_N-1 file. + pendingSegnOutput.sync(); pendingSegnOutput.close(); success = true; } finally { @@ -899,31 +909,6 @@ } } - // NOTE: if we crash here, we have left a segments_N - // file in the directory in a possibly corrupt state (if - // some bytes made it to stable storage and others - // didn't). But, the segments_N file includes checksum - // at the end, which should catch this case. So when a - // reader tries to read it, it will throw a - // CorruptIndexException, which should cause the retry - // logic in SegmentInfos to kick in and load the last - // good (previous) segments_N-1 file. - - final String fileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS, "", generation); - success = false; - try { - dir.sync(Collections.singleton(fileName)); - success = true; - } finally { - if (!success) { - try { - dir.deleteFile(fileName); - } catch (Throwable t) { - // Suppress so we keep throwing the original exception - } - } - } - lastGeneration = generation; writeSegmentsGen(dir, generation); } Index: lucene/core/src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (revision 1586145) +++ lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -52,6 +52,7 @@ import org.apache.lucene.store.Lock; import org.apache.lucene.store.LockObtainFailedException; import org.apache.lucene.store.MergeInfo; +import org.apache.lucene.store.SyncDirectoryWrapper; import org.apache.lucene.store.TrackingDirectoryWrapper; import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; @@ -218,7 +219,7 @@ public final static int MAX_TERM_LENGTH = DocumentsWriterPerThread.MAX_TERM_LENGTH_UTF8; volatile private boolean hitOOM; - private final Directory directory; // where this index resides + private final SyncDirectoryWrapper directory; // where this index resides private final Analyzer analyzer; // how to analyze text private volatile long changeCount; // increments every time a change is completed @@ -694,7 +695,7 @@ public IndexWriter(Directory d, IndexWriterConfig conf) throws IOException { conf.setIndexWriter(this); // prevent reuse by other instances config = new LiveIndexWriterConfig(conf); - directory = d; + directory = new SyncDirectoryWrapper(d); analyzer = config.getAnalyzer(); infoStream = config.getInfoStream(); mergePolicy = config.getMergePolicy(); @@ -2042,6 +2043,8 @@ deleter.refresh(); deleter.close(); + directory.close(); + IOUtils.close(writeLock); // release write lock writeLock = null; @@ -2071,7 +2074,7 @@ } // close all the closeables we can (but important is readerPool and writeLock to prevent leaks) - IOUtils.closeWhileHandlingException(readerPool, deleter, writeLock); + IOUtils.closeWhileHandlingException(readerPool, deleter, directory, writeLock); writeLock = null; } closed = true; @@ -4213,6 +4216,7 @@ Collection files = toSync.files(directory, false); for(final String fileName: files) { + System.out.println("check file exists: " + fileName); assert slowFileExists(directory, fileName): "file " + fileName + " does not exist; files=" + Arrays.toString(directory.listAll()); // If this trips it means we are missing a call to // .checkpoint somewhere, because by the time we @@ -4308,11 +4312,14 @@ // This call can take a long time -- 10s of seconds // or more. We do it without syncing on this: + Collection filesToSync; boolean success = false; - final Collection filesToSync; try { filesToSync = toSync.files(directory, false); - directory.sync(filesToSync); + System.out.println("TO SYNC: " + filesToSync); + for (String fileName : filesToSync) { + directory.syncIfStillOpen(fileName); + } success = true; } finally { if (!success) { Index: lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java (revision 1586145) +++ lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java (working copy) @@ -75,7 +75,8 @@ boolean trackDiskUsage = false; boolean wrapLockFactory = true; boolean allowRandomFileNotFoundException = true; - boolean allowReadingFilesStillOpenForWrite = false; + // nocommit + boolean allowReadingFilesStillOpenForWrite = true; private Set unSyncedFiles; private Set createdFiles; private Set openFilesForWrite = new HashSet<>(); @@ -187,26 +188,6 @@ return delegate instanceof NRTCachingDirectory; } - @Override - public synchronized void sync(Collection names) throws IOException { - maybeYield(); - maybeThrowDeterministicException(); - if (crashed) { - throw new IOException("cannot sync after crash"); - } - // 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); - in.sync(Collections.singleton(name)); - unSyncedFiles.remove(name); - } - } else { - unSyncedFiles.removeAll(names); - } - } - public synchronized final long sizeInBytes() throws IOException { if (in instanceof RAMDirectory) return ((RAMDirectory) in).sizeInBytes(); @@ -465,7 +446,11 @@ public void setFailOnCreateOutput(boolean v) { failOnCreateOutput = v; } - + + // nocommit must return a wrapper (need + // FilterIndexOutput!) that on sync, clears the file from + // unsyncedFiles + @Override public synchronized IndexOutput createOutput(String name, IOContext context) throws IOException { maybeThrowDeterministicException(); @@ -674,7 +659,8 @@ if (LuceneTestCase.VERBOSE) { System.out.println("\nNOTE: MockDirectoryWrapper: now crush"); } - crash(); // corrupt any unsynced-files + // nocommit put back!! + // crash(); // corrupt any unsynced-files if (LuceneTestCase.VERBOSE) { System.out.println("\nNOTE: MockDirectoryWrapper: now run CheckIndex"); } @@ -1006,6 +992,12 @@ io.close(); } } + + @Override + public void sync() throws IOException { + flush(); + io.sync(); + } } /** Use this when throwing fake {@code IOException}, Index: lucene/test-framework/src/java/org/apache/lucene/store/MockIndexOutputWrapper.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/store/MockIndexOutputWrapper.java (revision 1586145) +++ lucene/test-framework/src/java/org/apache/lucene/store/MockIndexOutputWrapper.java (working copy) @@ -112,6 +112,12 @@ } @Override + public void sync() throws IOException { + dir.maybeThrowDeterministicException(); + delegate.sync(); + } + + @Override public void writeByte(byte b) throws IOException { singleByte[0] = b; writeBytes(singleByte, 0, 1); Index: lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java =================================================================== --- lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java (revision 1586145) +++ lucene/test-framework/src/java/org/apache/lucene/util/ThrottledIndexOutput.java (working copy) @@ -75,6 +75,12 @@ } @Override + public void sync() throws IOException { + flush(); + delegate.sync(); + } + + @Override public void close() throws IOException { try { sleep(closeDelayMillis + getDelay(true));