You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2014/04/10 20:46:34 UTC
svn commit: r1586407 - in /lucene/dev/trunk/lucene: CHANGES.txt
core/src/java/org/apache/lucene/store/FSDirectory.java
core/src/java/org/apache/lucene/util/IOUtils.java
Author: uschindler
Date: Thu Apr 10 18:46:33 2014
New Revision: 1586407
URL: http://svn.apache.org/r1586407
Log:
LUCENE-5588: Lucene now calls fsync() on the index directory, ensuring that all file metadata is persisted on disk in case of power failure.
Modified:
lucene/dev/trunk/lucene/CHANGES.txt
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/IOUtils.java
Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1586407&r1=1586406&r2=1586407&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Thu Apr 10 18:46:33 2014
@@ -166,6 +166,12 @@ New Features
* LUCENE-5583: Added DataInput.skipBytes. ChecksumIndexInput can now seek, but
only forward. (Adrien Grand, Mike McCandless, Simon Willnauer, Uwe Schindler)
+* LUCENE-5588: Lucene now calls fsync() on the index directory, ensuring
+ that all file metadata is persisted on disk in case of power failure.
+ This does not work on all file systems and operating systems, but Linux
+ and MacOSX are known to work. On Windows, fsyncing a directory is not
+ possible with Java APIs. (Mike McCandless, Uwe Schindler)
+
API Changes
* LUCENE-5454: Add RandomAccessOrds, an optional extension of SortedSetDocValues
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java?rev=1586407&r1=1586406&r2=1586407&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java Thu Apr 10 18:46:33 2014
@@ -291,7 +291,9 @@ public abstract class FSDirectory extend
for (String name : toSync)
fsync(name);
-
+
+ IOUtils.fsync(directory, true);
+
staleFiles.removeAll(toSync);
}
@@ -395,6 +397,6 @@ public abstract class FSDirectory extend
}
protected void fsync(String name) throws IOException {
- IOUtils.fsync(new File(directory, name));
+ IOUtils.fsync(new File(directory, name), false);
}
}
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/IOUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/IOUtils.java?rev=1586407&r1=1586406&r2=1586407&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/IOUtils.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/IOUtils.java Thu Apr 10 18:46:33 2014
@@ -372,29 +372,47 @@ public final class IOUtils {
/**
* Ensure that any writes to the given file is written to the storage device that contains it.
* @param fileToSync the file to fsync
+ * @param isDir if true, the given file is a directory (we open for read and ignore IOExceptions,
+ * because not all file systems and operating systems allow to fsync on a directory)
*/
- public static void fsync(File fileToSync) throws IOException {
+ public static void fsync(File fileToSync, boolean isDir) 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;
- }
+
+ // If the file is a directory we have to open read-only, for regular files we must open r/w for the fsync to have an effect.
+ // See http://blog.httrack.com/blog/2013/11/15/everything-you-always-wanted-to-know-about-fsync/
+ try (final FileChannel file = FileChannel.open(fileToSync.toPath(), isDir ? StandardOpenOption.READ : StandardOpenOption.WRITE)) {
+ for (int retry = 0; retry < 5; retry++) {
try {
- // Pause 5 msec
- Thread.sleep(5);
- } catch (InterruptedException ie) {
- ThreadInterruptedException ex = new ThreadInterruptedException(ie);
- ex.addSuppressed(exc);
- throw ex;
+ file.force(true);
+ return;
+ } catch (IOException ioe) {
+ if (exc == null) {
+ exc = ioe;
+ }
+ try {
+ // Pause 5 msec
+ Thread.sleep(5L);
+ } catch (InterruptedException ie) {
+ ThreadInterruptedException ex = new ThreadInterruptedException(ie);
+ ex.addSuppressed(exc);
+ throw ex;
+ }
}
}
+ } catch (IOException ioe) {
+ if (exc == null) {
+ exc = ioe;
+ }
+ }
+
+ if (isDir) {
+ assert (Constants.LINUX || Constants.MAC_OS_X) == false :
+ "On Linux and MacOSX fsyncing a directory should not throw IOException, "+
+ "we just don't want to rely on that in production (undocumented). Got: " + exc;
+ // Ignore exception if it is a directory
+ return;
}
+
// Throw original exception
throw exc;
}