Add support for wal_fsync_writethrough for Darwin, and restructure the
authorBruce Momjian <[email protected]>
Fri, 20 May 2005 14:53:26 +0000 (14:53 +0000)
committerBruce Momjian <[email protected]>
Fri, 20 May 2005 14:53:26 +0000 (14:53 +0000)
code to better handle writethrough.

Chris Campbell

doc/src/sgml/runtime.sgml
src/backend/access/transam/xlog.c
src/backend/storage/file/fd.c
src/include/access/xlog.h
src/include/port/darwin.h
src/include/port/win32.h
src/include/storage/fd.h

index b5e7ed067f11525edaa75b568954db04baf00b4f..4e6c3300063f3a1815f152b95497531c1ba61950 100644 (file)
@@ -1595,7 +1595,7 @@ SET ENABLE_SEQSCAN TO OFF;
         values are
         <literal>fsync</> (call <function>fsync()</> at each commit),
         <literal>fdatasync</> (call <function>fdatasync()</> at each commit),
-        <literal>fsync_writethrough</> (call <function>_commit()</> at each commit on Windows),
+        <literal>fsync_writethrough</> (force write-through of any disk write cache),
         <literal>open_sync</> (write WAL files with <function>open()</> option <symbol>O_SYNC</>), and
         <literal>open_datasync</> (write WAL files with <function>open()</> option <symbol>O_DSYNC</>).
         Not all of these choices are available on all platforms.
index e766ffd17149c02706121728b814531870f02b63..b4451ce25c93854ae88195d1d59d93dd3ceee6b5 100644 (file)
  * default method.     We assume that fsync() is always available, and that
  * configure determined whether fdatasync() is.
  */
-#define SYNC_METHOD_FSYNC              0
-#define SYNC_METHOD_FDATASYNC  1
-#define SYNC_METHOD_OPEN               2               /* used for both O_SYNC and
-                                                                                * O_DSYNC */
-
 #if defined(O_SYNC)
 #define OPEN_SYNC_FLAG    O_SYNC
 #else
 #define DEFAULT_SYNC_METHOD_STR    "open_datasync"
 #define DEFAULT_SYNC_METHOD               SYNC_METHOD_OPEN
 #define DEFAULT_SYNC_FLAGBIT      OPEN_DATASYNC_FLAG
-#else
-#if defined(HAVE_FDATASYNC)
+#elif defined(HAVE_FDATASYNC)
 #define DEFAULT_SYNC_METHOD_STR   "fdatasync"
 #define DEFAULT_SYNC_METHOD              SYNC_METHOD_FDATASYNC
 #define DEFAULT_SYNC_FLAGBIT     0
-#else
-#ifndef FSYNC_IS_WRITE_THROUGH
+#elif !defined(HAVE_FSYNC_WRITETHROUGH_ONLY)
 #define DEFAULT_SYNC_METHOD_STR   "fsync"
+#define DEFAULT_SYNC_METHOD              SYNC_METHOD_FSYNC
+#define DEFAULT_SYNC_FLAGBIT     0
 #else
 #define DEFAULT_SYNC_METHOD_STR   "fsync_writethrough"
-#endif
-#define DEFAULT_SYNC_METHOD              SYNC_METHOD_FSYNC
+#define DEFAULT_SYNC_METHOD              SYNC_METHOD_FSYNC_WRITETHROUGH
 #define DEFAULT_SYNC_FLAGBIT     0
 #endif
-#endif
 
 
 /* User-settable parameters */
@@ -122,7 +115,7 @@ bool                XLOG_DEBUG = false;
 
 
 /* these are derived from XLOG_sync_method by assign_xlog_sync_method */
-static int     sync_method = DEFAULT_SYNC_METHOD;
+int    sync_method = DEFAULT_SYNC_METHOD;
 static int     open_sync_bit = DEFAULT_SYNC_FLAGBIT;
 
 #define XLOG_SYNC_BIT  (enableFsync ? open_sync_bit : 0)
@@ -5249,16 +5242,18 @@ assign_xlog_sync_method(const char *method, bool doit, GucSource source)
        int                     new_sync_method;
        int                     new_sync_bit;
 
-#ifndef FSYNC_IS_WRITE_THROUGH
        if (pg_strcasecmp(method, "fsync") == 0)
-#else
-       /* Win32 fsync() == _commit(), which writes through a write cache */
-       if (pg_strcasecmp(method, "fsync_writethrough") == 0)
-#endif
        {
                new_sync_method = SYNC_METHOD_FSYNC;
                new_sync_bit = 0;
        }
+#ifdef HAVE_FSYNC_WRITETHROUGH
+       else if (pg_strcasecmp(method, "fsync_writethrough") == 0)
+       {
+               new_sync_method = SYNC_METHOD_FSYNC_WRITETHROUGH;
+               new_sync_bit = 0;
+       }
+#endif
 #ifdef HAVE_FDATASYNC
        else if (pg_strcasecmp(method, "fdatasync") == 0)
        {
@@ -5328,12 +5323,21 @@ issue_xlog_fsync(void)
        switch (sync_method)
        {
                case SYNC_METHOD_FSYNC:
-                       if (pg_fsync(openLogFile) != 0)
+                       if (pg_fsync_no_writethrough(openLogFile) != 0)
                                ereport(PANIC,
                                                (errcode_for_file_access(),
                                        errmsg("could not fsync log file %u, segment %u: %m",
                                                   openLogId, openLogSeg)));
                        break;
+#ifdef HAVE_FSYNC_WRITETHROUGH
+               case SYNC_METHOD_FSYNC_WRITETHROUGH:
+                       if (pg_fsync_writethrough(openLogFile) != 0)
+                               ereport(PANIC,
+                                               (errcode_for_file_access(),
+                                       errmsg("could not fsync write-through log file %u, segment %u: %m",
+                                                  openLogId, openLogSeg)));
+                       break;
+#endif
 #ifdef HAVE_FDATASYNC
                case SYNC_METHOD_FDATASYNC:
                        if (pg_fdatasync(openLogFile) != 0)
index e1326328a8d7e6a94e6950d568298416b6472971..1b5d6bebfdc7f7536e311f0d983259c6ef011893 100644 (file)
@@ -232,10 +232,26 @@ static void RemovePgTempFilesInDir(const char *tmpdirname);
 
 
 /*
- * pg_fsync --- same as fsync except does nothing if enableFsync is off
+ * pg_fsync --- do fsync with or without writethrough
  */
 int
 pg_fsync(int fd)
+{
+#ifndef HAVE_FSYNC_WRITETHROUGH_ONLY
+       if (sync_method != SYNC_METHOD_FSYNC_WRITETHROUGH)
+               return pg_fsync_no_writethrough(fd);
+       else
+#endif
+               return pg_fsync_writethrough(fd);
+}
+
+
+/*
+ * pg_fsync_no_writethrough --- same as fsync except does nothing if
+ *     enableFsync is off
+ */
+int
+pg_fsync_no_writethrough(int fd)
 {
        if (enableFsync)
                return fsync(fd);
@@ -243,6 +259,24 @@ pg_fsync(int fd)
                return 0;
 }
 
+/*
+ * pg_fsync_writethrough
+ */
+int
+pg_fsync_writethrough(int fd)
+{
+       if (enableFsync)
+#ifdef WIN32
+               return _commit(fd);
+#elif defined(__darwin__)
+               return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
+#else
+               return -1;
+#endif
+       else
+               return 0;
+}
+
 /*
  * pg_fdatasync --- same as fdatasync except does nothing if enableFsync is off
  *
index 0c6b5bcd7dc00cfb43aa2796b8a1f5fb80d5ef8d..71a22180a3e44b5c6d555d178f73d577be81de9f 100644 (file)
@@ -75,6 +75,13 @@ typedef struct XLogRecord
  */
 #define XLOG_NO_TRAN                   XLR_INFO_MASK
 
+/* Sync methods */
+#define SYNC_METHOD_FSYNC              0
+#define SYNC_METHOD_FDATASYNC  1
+#define SYNC_METHOD_OPEN               2                       /* for O_SYNC and O_DSYNC */
+#define SYNC_METHOD_FSYNC_WRITETHROUGH 3
+extern int     sync_method;
+
 /*
  * List of these structs is used to pass data to XLogInsert().
  *
index 06c559d2ba8dee749677616dee7c84616d8e013f..0a802e5abbb2af321e1f2cc4d02deda011a55c79 100644 (file)
@@ -1 +1,4 @@
 #define __darwin__     1
+
+#define HAVE_FSYNC_WRITETHROUGH
+
index 3a3dc1eda4d3d9597e7c273b3d71c9458bb98abd..58453e3508849031da39f7a09a99f3822e002b2f 100644 (file)
@@ -16,8 +16,8 @@
 #define mkdir(a,b)     mkdir(a)
 
 
-#define fsync(a)       _commit(a)
-#define FSYNC_IS_WRITE_THROUGH
+#define HAVE_FSYNC_WRITETHROUGH
+#define HAVE_FSYNC_WRITETHROUGH_ONLY
 #define ftruncate(a,b) chsize(a,b)
 
 #define USES_WINSOCK
index ed47d1ad9739ca7e358f2408620563b0bf038928..a6d3c8cb89defb59a954d2a6f278caf603ab342f 100644 (file)
@@ -89,6 +89,8 @@ extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
                                                          SubTransactionId parentSubid);
 extern void RemovePgTempFiles(void);
 extern int     pg_fsync(int fd);
+extern int     pg_fsync_no_writethrough(int fd);
+extern int     pg_fsync_writethrough(int fd);
 extern int     pg_fdatasync(int fd);
 
 /* Filename components for OpenTemporaryFile */