Author: xedin Date: Mon Dec 19 09:20:18 2011 New Revision: 1220663 URL: http://svn.apache.org/viewvc?rev=1220663&view=rev Log: fsync the directory after new sstable or commitlog segment are created patch by Pavel Yaskevich; reviewed by Jonathan Ellis for CASSANDRA-3250
Modified: cassandra/branches/cassandra-1.0/CHANGES.txt cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/util/SequentialWriter.java cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/utils/CLibrary.java Modified: cassandra/branches/cassandra-1.0/CHANGES.txt URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/CHANGES.txt?rev=1220663&r1=1220662&r2=1220663&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/CHANGES.txt (original) +++ cassandra/branches/cassandra-1.0/CHANGES.txt Mon Dec 19 09:20:18 2011 @@ -4,6 +4,8 @@ * CLibrary.createHardLinkWithExec() to check for errors (CASSANDRA-3101) Merged from 0.8: * prevent new nodes from thinking down nodes are up forever (CASSANDRA-3626) + * fsync the directory after new sstable or commitlog segment are created (CASSANDRA-3250) + 1.0.6 * (CQL) fix cqlsh support for replicate_on_write (CASSANDRA-3596) Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/util/SequentialWriter.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/util/SequentialWriter.java?rev=1220663&r1=1220662&r2=1220663&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/util/SequentialWriter.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/io/util/SequentialWriter.java Mon Dec 19 09:20:18 2011 @@ -39,6 +39,9 @@ public class SequentialWriter extends Ou protected byte[] buffer; private final boolean skipIOCache; private final int fd; + private final int directoryFD; + // directory should be synced only after first file sync, in other words, only once per file + private boolean directorySynced = false; protected long current = 0, bufferOffset; protected int validBufferBytes; @@ -60,6 +63,7 @@ public class SequentialWriter extends Ou buffer = new byte[bufferSize]; this.skipIOCache = skipIOCache; fd = CLibrary.getfd(out.getFD()); + directoryFD = CLibrary.tryOpenDirectory(file.getParent()); stream = new DataOutputStream(this); } @@ -148,6 +152,12 @@ public class SequentialWriter extends Ou flushInternal(); out.getFD().sync(); + if (!directorySynced) + { + CLibrary.trySync(directoryFD); + directorySynced = true; + } + syncNeeded = false; } } @@ -288,6 +298,7 @@ public class SequentialWriter extends Ou CLibrary.trySkipCache(fd, 0, 0); out.close(); + CLibrary.tryCloseFD(directoryFD); } /** Modified: cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/utils/CLibrary.java URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/utils/CLibrary.java?rev=1220663&r1=1220662&r2=1220663&view=diff ============================================================================== --- cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/utils/CLibrary.java (original) +++ cassandra/branches/cassandra-1.0/src/java/org/apache/cassandra/utils/CLibrary.java Mon Dec 19 09:20:18 2011 @@ -46,6 +46,7 @@ public final class CLibrary private static final int F_SETFL = 4; /* set file status flags */ private static final int F_NOCACHE = 48; /* Mac OS X specific flag, turns cache on/off */ private static final int O_DIRECT = 040000; /* fcntl.h */ + private static final int O_RDONLY = 00000000; /* fcntl.h */ private static final int POSIX_FADV_NORMAL = 0; /* fadvise.h */ private static final int POSIX_FADV_RANDOM = 1; /* fadvise.h */ @@ -84,7 +85,11 @@ public final class CLibrary // fadvice public static native int posix_fadvise(int fd, long offset, int len, int flag) throws LastErrorException; - + + public static native int open(String path, int flags) throws LastErrorException; + public static native int fsync(int fd) throws LastErrorException; + public static native int close(int fd) throws LastErrorException; + private static int errno(RuntimeException e) { assert e instanceof LastErrorException; @@ -261,6 +266,73 @@ public final class CLibrary return result; } + public static int tryOpenDirectory(String path) + { + int fd = -1; + + try + { + return open(path, O_RDONLY); + } + catch (UnsatisfiedLinkError e) + { + // JNA is unavailable just skipping Direct I/O + } + catch (RuntimeException e) + { + if (!(e instanceof LastErrorException)) + throw e; + + logger.warn(String.format("open(%s, O_RDONLY) failed, errno (%d).", path, CLibrary.errno(e))); + } + + return fd; + } + + public static void trySync(int fd) + { + if (fd == -1) + return; + + try + { + fsync(fd); + } + catch (UnsatisfiedLinkError e) + { + // JNA is unavailable just skipping Direct I/O + } + catch (RuntimeException e) + { + if (!(e instanceof LastErrorException)) + throw e; + + logger.warn(String.format("fsync(%d) failed, errno (%d).", fd, CLibrary.errno(e))); + } + } + + public static void tryCloseFD(int fd) + { + if (fd == -1) + return; + + try + { + close(fd); + } + catch (UnsatisfiedLinkError e) + { + // JNA is unavailable just skipping Direct I/O + } + catch (RuntimeException e) + { + if (!(e instanceof LastErrorException)) + throw e; + + logger.warn(String.format("close(%d) failed, errno (%d).", fd, CLibrary.errno(e))); + } + } + /** * Get system file descriptor from FileDescriptor object. * @param descriptor - FileDescriptor objec to get fd from