mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Support syncing WAL log to disk using either fsync(), fdatasync(),
O_SYNC, or O_DSYNC (as available on a given platform). Add GUC parameter to control sync method. Also, add defense to XLogWrite to prevent it from going nuts if passed a target write position that's past the end of the buffers so far filled by XLogInsert.
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.56 2001/03/13 01:17:05 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.57 2001/03/16 05:44:33 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<Chapter Id="runtime">
|
<Chapter Id="runtime">
|
||||||
@ -1224,8 +1224,8 @@ env PGOPTIONS='-c geqo=off' psql
|
|||||||
<term>WAL_BUFFERS (<type>integer</type>)</term>
|
<term>WAL_BUFFERS (<type>integer</type>)</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Number of disk-page buffers for WAL log. This option can only be set
|
Number of disk-page buffers in shared memory for WAL log.
|
||||||
at server start.
|
This option can only be set at server start.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -1250,6 +1250,23 @@ env PGOPTIONS='-c geqo=off' psql
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>WAL_SYNC_METHOD (<type>string</type>)</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Method used for forcing WAL updates out to disk. Possible
|
||||||
|
values are
|
||||||
|
<literal>FSYNC</> (call fsync() at each commit),
|
||||||
|
<literal>FDATASYNC</> (call fdatasync() at each commit),
|
||||||
|
<literal>OPEN_SYNC</> (write WAL files with open() option O_SYNC), or
|
||||||
|
<literal>OPEN_DATASYNC</> (write WAL files with open() option O_DSYNC).
|
||||||
|
Not all of these choices are available on all platforms.
|
||||||
|
This option can only be set at server start or in the
|
||||||
|
<filename>postgresql.conf</filename> file.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.4 2001/03/13 01:17:05 tgl Exp $ -->
|
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/wal.sgml,v 1.5 2001/03/16 05:44:33 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="wal">
|
<chapter id="wal">
|
||||||
<title>Write-Ahead Logging (<acronym>WAL</acronym>)</title>
|
<title>Write-Ahead Logging (<acronym>WAL</acronym>)</title>
|
||||||
@ -281,15 +281,6 @@
|
|||||||
<command>CHECKPOINT</command>.
|
<command>CHECKPOINT</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
Setting the <varname>WAL_DEBUG</varname> parameter to any non-zero
|
|
||||||
value will result in each <function>LogInsert</function> and
|
|
||||||
<function>LogFlush</function> <acronym>WAL</acronym> call being
|
|
||||||
logged to standard error. At present, it makes no difference what
|
|
||||||
the non-zero value is. This option may be replaced by a more
|
|
||||||
general mechanism in the future.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <varname>COMMIT_DELAY</varname> parameter defines for how many
|
The <varname>COMMIT_DELAY</varname> parameter defines for how many
|
||||||
microseconds the backend will sleep after writing a commit
|
microseconds the backend will sleep after writing a commit
|
||||||
@ -304,6 +295,24 @@
|
|||||||
ten milliseconds, so that any nonzero <varname>COMMIT_DELAY</varname>
|
ten milliseconds, so that any nonzero <varname>COMMIT_DELAY</varname>
|
||||||
setting between 1 and 10000 microseconds will have the same effect.
|
setting between 1 and 10000 microseconds will have the same effect.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <varname>WAL_SYNC_METHOD</varname> parameter determines how
|
||||||
|
Postgres will ask the kernel to force WAL updates out to disk.
|
||||||
|
All the options should be the same as far as reliability goes,
|
||||||
|
but it's quite platform-specific which one will be the fastest.
|
||||||
|
Note that this parameter is irrelevant if <varname>FSYNC</varname>
|
||||||
|
has been turned off.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Setting the <varname>WAL_DEBUG</varname> parameter to any non-zero
|
||||||
|
value will result in each <function>LogInsert</function> and
|
||||||
|
<function>LogFlush</function> <acronym>WAL</acronym> call being
|
||||||
|
logged to standard error. At present, it makes no difference what
|
||||||
|
the non-zero value is. This option may be replaced by a more
|
||||||
|
general mechanism in the future.
|
||||||
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.58 2001/03/14 20:23:04 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.59 2001/03/16 05:44:33 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -42,6 +42,47 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This chunk of hackery attempts to determine which file sync methods
|
||||||
|
* are available on the current platform, and to choose an appropriate
|
||||||
|
* 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
|
||||||
|
# if defined(O_FSYNC)
|
||||||
|
# define OPEN_SYNC_FLAG O_FSYNC
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OPEN_SYNC_FLAG)
|
||||||
|
# if defined(O_DSYNC) && (O_DSYNC != OPEN_SYNC_FLAG)
|
||||||
|
# define OPEN_DATASYNC_FLAG O_DSYNC
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OPEN_DATASYNC_FLAG)
|
||||||
|
# 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)
|
||||||
|
# define DEFAULT_SYNC_METHOD_STR "fdatasync"
|
||||||
|
# define DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
|
||||||
|
# define DEFAULT_SYNC_FLAGBIT 0
|
||||||
|
# else
|
||||||
|
# define DEFAULT_SYNC_METHOD_STR "fsync"
|
||||||
|
# define DEFAULT_SYNC_METHOD SYNC_METHOD_FSYNC
|
||||||
|
# define DEFAULT_SYNC_FLAGBIT 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Max time to wait to acquire XLog activity locks */
|
/* Max time to wait to acquire XLog activity locks */
|
||||||
#define XLOG_LOCK_TIMEOUT (5*60*1000000) /* 5 minutes */
|
#define XLOG_LOCK_TIMEOUT (5*60*1000000) /* 5 minutes */
|
||||||
/* Max time to wait to acquire checkpoint lock */
|
/* Max time to wait to acquire checkpoint lock */
|
||||||
@ -52,10 +93,18 @@ int CheckPointSegments = 3;
|
|||||||
int XLOGbuffers = 8;
|
int XLOGbuffers = 8;
|
||||||
int XLOGfiles = 0; /* how many files to pre-allocate during ckpt */
|
int XLOGfiles = 0; /* how many files to pre-allocate during ckpt */
|
||||||
int XLOG_DEBUG = 0;
|
int XLOG_DEBUG = 0;
|
||||||
|
char *XLOG_sync_method = NULL;
|
||||||
|
const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;
|
||||||
char XLOG_archive_dir[MAXPGPATH]; /* null string means delete 'em */
|
char XLOG_archive_dir[MAXPGPATH]; /* null string means delete 'em */
|
||||||
|
|
||||||
|
/* these are derived from XLOG_sync_method by assign_xlog_sync_method */
|
||||||
|
static int sync_method = DEFAULT_SYNC_METHOD;
|
||||||
|
static int open_sync_bit = DEFAULT_SYNC_FLAGBIT;
|
||||||
|
|
||||||
#define MinXLOGbuffers 4
|
#define MinXLOGbuffers 4
|
||||||
|
|
||||||
|
#define XLOG_SYNC_BIT (enableFsync ? open_sync_bit : 0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ThisStartUpID will be same in all backends --- it identifies current
|
* ThisStartUpID will be same in all backends --- it identifies current
|
||||||
@ -365,6 +414,7 @@ static void WriteControlFile(void);
|
|||||||
static void ReadControlFile(void);
|
static void ReadControlFile(void);
|
||||||
static char *str_time(time_t tnow);
|
static char *str_time(time_t tnow);
|
||||||
static void xlog_outrec(char *buf, XLogRecord *record);
|
static void xlog_outrec(char *buf, XLogRecord *record);
|
||||||
|
static void issue_xlog_fsync(void);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -917,6 +967,15 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
|||||||
|
|
||||||
while (XLByteLT(LogwrtResult.Write, WriteRqst.Write))
|
while (XLByteLT(LogwrtResult.Write, WriteRqst.Write))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Make sure we're not ahead of the insert process. This could
|
||||||
|
* happen if we're passed a bogus WriteRqst.Write that is past the
|
||||||
|
* end of the last page that's been initialized by
|
||||||
|
* AdvanceXLInsertBuffer.
|
||||||
|
*/
|
||||||
|
if (!XLByteLT(LogwrtResult.Write, XLogCtl->xlblocks[Write->curridx]))
|
||||||
|
elog(STOP, "XLogWrite: write request is past end of log");
|
||||||
|
|
||||||
/* Advance LogwrtResult.Write to end of current buffer page */
|
/* Advance LogwrtResult.Write to end of current buffer page */
|
||||||
LogwrtResult.Write = XLogCtl->xlblocks[Write->curridx];
|
LogwrtResult.Write = XLogCtl->xlblocks[Write->curridx];
|
||||||
ispartialpage = XLByteLT(WriteRqst.Write, LogwrtResult.Write);
|
ispartialpage = XLByteLT(WriteRqst.Write, LogwrtResult.Write);
|
||||||
@ -1004,9 +1063,7 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
|||||||
*/
|
*/
|
||||||
if (openLogOff >= XLogSegSize && !ispartialpage)
|
if (openLogOff >= XLogSegSize && !ispartialpage)
|
||||||
{
|
{
|
||||||
if (pg_fdatasync(openLogFile) != 0)
|
issue_xlog_fsync();
|
||||||
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
|
|
||||||
openLogId, openLogSeg);
|
|
||||||
LogwrtResult.Flush = LogwrtResult.Write; /* end of current page */
|
LogwrtResult.Flush = LogwrtResult.Write; /* end of current page */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1030,24 +1087,24 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
|||||||
* we might have no open file or the wrong one. However, we do
|
* we might have no open file or the wrong one. However, we do
|
||||||
* not need to fsync more than one file.
|
* not need to fsync more than one file.
|
||||||
*/
|
*/
|
||||||
if (openLogFile >= 0 &&
|
if (sync_method != SYNC_METHOD_OPEN)
|
||||||
!XLByteInPrevSeg(LogwrtResult.Write, openLogId, openLogSeg))
|
|
||||||
{
|
{
|
||||||
if (close(openLogFile) != 0)
|
if (openLogFile >= 0 &&
|
||||||
elog(STOP, "close(logfile %u seg %u) failed: %m",
|
!XLByteInPrevSeg(LogwrtResult.Write, openLogId, openLogSeg))
|
||||||
openLogId, openLogSeg);
|
{
|
||||||
openLogFile = -1;
|
if (close(openLogFile) != 0)
|
||||||
|
elog(STOP, "close(logfile %u seg %u) failed: %m",
|
||||||
|
openLogId, openLogSeg);
|
||||||
|
openLogFile = -1;
|
||||||
|
}
|
||||||
|
if (openLogFile < 0)
|
||||||
|
{
|
||||||
|
XLByteToPrevSeg(LogwrtResult.Write, openLogId, openLogSeg);
|
||||||
|
openLogFile = XLogFileOpen(openLogId, openLogSeg, false);
|
||||||
|
openLogOff = 0;
|
||||||
|
}
|
||||||
|
issue_xlog_fsync();
|
||||||
}
|
}
|
||||||
if (openLogFile < 0)
|
|
||||||
{
|
|
||||||
XLByteToPrevSeg(LogwrtResult.Write, openLogId, openLogSeg);
|
|
||||||
openLogFile = XLogFileOpen(openLogId, openLogSeg, false);
|
|
||||||
openLogOff = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pg_fdatasync(openLogFile) != 0)
|
|
||||||
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
|
|
||||||
openLogId, openLogSeg);
|
|
||||||
LogwrtResult.Flush = LogwrtResult.Write;
|
LogwrtResult.Flush = LogwrtResult.Write;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1191,7 +1248,8 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
|
|||||||
*/
|
*/
|
||||||
if (*usexistent)
|
if (*usexistent)
|
||||||
{
|
{
|
||||||
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
fd = BasicOpenFile(path, O_RDWR | PG_BINARY | XLOG_SYNC_BIT,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
@ -1208,6 +1266,7 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
|
|||||||
unlink(tpath);
|
unlink(tpath);
|
||||||
unlink(path);
|
unlink(path);
|
||||||
|
|
||||||
|
/* do not use XLOG_SYNC_BIT here --- want to fsync only at end of fill */
|
||||||
fd = BasicOpenFile(tpath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
|
fd = BasicOpenFile(tpath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
|
||||||
S_IRUSR | S_IWUSR);
|
S_IRUSR | S_IWUSR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -1220,8 +1279,8 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
|
|||||||
* allow "holes" in files, just seeking to the end doesn't allocate
|
* allow "holes" in files, just seeking to the end doesn't allocate
|
||||||
* intermediate space. This way, we know that we have all the space
|
* intermediate space. This way, we know that we have all the space
|
||||||
* and (after the fsync below) that all the indirect blocks are down
|
* and (after the fsync below) that all the indirect blocks are down
|
||||||
* on disk. Therefore, fdatasync(2) will be sufficient to sync future
|
* on disk. Therefore, fdatasync(2) or O_DSYNC will be sufficient to
|
||||||
* writes to the log file.
|
* sync future writes to the log file.
|
||||||
*/
|
*/
|
||||||
MemSet(zbuffer, 0, sizeof(zbuffer));
|
MemSet(zbuffer, 0, sizeof(zbuffer));
|
||||||
for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
|
for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
|
||||||
@ -1261,7 +1320,8 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
|
|||||||
log, seg);
|
log, seg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
fd = BasicOpenFile(path, O_RDWR | PG_BINARY | XLOG_SYNC_BIT,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
elog(STOP, "InitReopen(logfile %u seg %u) failed: %m",
|
elog(STOP, "InitReopen(logfile %u seg %u) failed: %m",
|
||||||
log, seg);
|
log, seg);
|
||||||
@ -1280,7 +1340,8 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
|
|||||||
|
|
||||||
XLogFileName(path, log, seg);
|
XLogFileName(path, log, seg);
|
||||||
|
|
||||||
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
|
fd = BasicOpenFile(path, O_RDWR | PG_BINARY | XLOG_SYNC_BIT,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
if (econt && errno == ENOENT)
|
if (econt && errno == ENOENT)
|
||||||
@ -1845,7 +1906,8 @@ WriteControlFile(void)
|
|||||||
memset(buffer, 0, BLCKSZ);
|
memset(buffer, 0, BLCKSZ);
|
||||||
memcpy(buffer, ControlFile, sizeof(ControlFileData));
|
memcpy(buffer, ControlFile, sizeof(ControlFileData));
|
||||||
|
|
||||||
fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, S_IRUSR | S_IWUSR);
|
fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
elog(STOP, "WriteControlFile failed to create control file (%s): %m",
|
elog(STOP, "WriteControlFile failed to create control file (%s): %m",
|
||||||
ControlFilePath);
|
ControlFilePath);
|
||||||
@ -2852,3 +2914,120 @@ xlog_outrec(char *buf, XLogRecord *record)
|
|||||||
sprintf(buf + strlen(buf), ": %s",
|
sprintf(buf + strlen(buf), ": %s",
|
||||||
RmgrTable[record->xl_rmid].rm_name);
|
RmgrTable[record->xl_rmid].rm_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GUC support routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
check_xlog_sync_method(const char *method)
|
||||||
|
{
|
||||||
|
if (strcasecmp(method, "fsync") == 0) return true;
|
||||||
|
#ifdef HAVE_FDATASYNC
|
||||||
|
if (strcasecmp(method, "fdatasync") == 0) return true;
|
||||||
|
#endif
|
||||||
|
#ifdef OPEN_SYNC_FLAG
|
||||||
|
if (strcasecmp(method, "open_sync") == 0) return true;
|
||||||
|
#endif
|
||||||
|
#ifdef OPEN_DATASYNC_FLAG
|
||||||
|
if (strcasecmp(method, "open_datasync") == 0) return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
assign_xlog_sync_method(const char *method)
|
||||||
|
{
|
||||||
|
int new_sync_method;
|
||||||
|
int new_sync_bit;
|
||||||
|
|
||||||
|
if (strcasecmp(method, "fsync") == 0)
|
||||||
|
{
|
||||||
|
new_sync_method = SYNC_METHOD_FSYNC;
|
||||||
|
new_sync_bit = 0;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_FDATASYNC
|
||||||
|
else if (strcasecmp(method, "fdatasync") == 0)
|
||||||
|
{
|
||||||
|
new_sync_method = SYNC_METHOD_FDATASYNC;
|
||||||
|
new_sync_bit = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef OPEN_SYNC_FLAG
|
||||||
|
else if (strcasecmp(method, "open_sync") == 0)
|
||||||
|
{
|
||||||
|
new_sync_method = SYNC_METHOD_OPEN;
|
||||||
|
new_sync_bit = OPEN_SYNC_FLAG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef OPEN_DATASYNC_FLAG
|
||||||
|
else if (strcasecmp(method, "open_datasync") == 0)
|
||||||
|
{
|
||||||
|
new_sync_method = SYNC_METHOD_OPEN;
|
||||||
|
new_sync_bit = OPEN_DATASYNC_FLAG;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Can't get here unless guc.c screwed up */
|
||||||
|
elog(ERROR, "Bogus xlog sync method %s", method);
|
||||||
|
new_sync_method = 0; /* keep compiler quiet */
|
||||||
|
new_sync_bit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sync_method != new_sync_method || open_sync_bit != new_sync_bit)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* To ensure that no blocks escape unsynced, force an fsync on
|
||||||
|
* the currently open log segment (if any). Also, if the open
|
||||||
|
* flag is changing, close the log file so it will be reopened
|
||||||
|
* (with new flag bit) at next use.
|
||||||
|
*/
|
||||||
|
if (openLogFile >= 0)
|
||||||
|
{
|
||||||
|
if (pg_fsync(openLogFile) != 0)
|
||||||
|
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
|
||||||
|
openLogId, openLogSeg);
|
||||||
|
if (open_sync_bit != new_sync_bit)
|
||||||
|
{
|
||||||
|
if (close(openLogFile) != 0)
|
||||||
|
elog(STOP, "close(logfile %u seg %u) failed: %m",
|
||||||
|
openLogId, openLogSeg);
|
||||||
|
openLogFile = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sync_method = new_sync_method;
|
||||||
|
open_sync_bit = new_sync_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Issue appropriate kind of fsync (if any) on the current XLOG output file
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
issue_xlog_fsync(void)
|
||||||
|
{
|
||||||
|
switch (sync_method)
|
||||||
|
{
|
||||||
|
case SYNC_METHOD_FSYNC:
|
||||||
|
if (pg_fsync(openLogFile) != 0)
|
||||||
|
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
|
||||||
|
openLogId, openLogSeg);
|
||||||
|
break;
|
||||||
|
#ifdef HAVE_FDATASYNC
|
||||||
|
case SYNC_METHOD_FDATASYNC:
|
||||||
|
if (pg_fdatasync(openLogFile) != 0)
|
||||||
|
elog(STOP, "fdatasync(logfile %u seg %u) failed: %m",
|
||||||
|
openLogId, openLogSeg);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case SYNC_METHOD_OPEN:
|
||||||
|
/* write synced it already */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(STOP, "bogus sync_method %d", sync_method);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Support for grand unified configuration scheme, including SET
|
* Support for grand unified configuration scheme, including SET
|
||||||
* command, configuration file, and command line options.
|
* command, configuration file, and command line options.
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.32 2001/03/13 01:17:06 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.33 2001/03/16 05:44:33 tgl Exp $
|
||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* Copyright 2000 by PostgreSQL Global Development Group
|
||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "utils/guc.h"
|
#include "utils/guc.h"
|
||||||
|
|
||||||
|
#include "access/xlog.h"
|
||||||
#include "commands/async.h"
|
#include "commands/async.h"
|
||||||
#include "libpq/auth.h"
|
#include "libpq/auth.h"
|
||||||
#include "libpq/pqcomm.h"
|
#include "libpq/pqcomm.h"
|
||||||
@ -33,23 +34,17 @@
|
|||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
|
|
||||||
|
|
||||||
/* XXX should be in a header file */
|
/* XXX these should be in other modules' header files */
|
||||||
extern bool Log_connections;
|
extern bool Log_connections;
|
||||||
|
|
||||||
extern int CheckPointSegments;
|
|
||||||
extern int CheckPointTimeout;
|
extern int CheckPointTimeout;
|
||||||
extern int XLOGbuffers;
|
|
||||||
extern int XLOGfiles;
|
|
||||||
extern int XLOG_DEBUG;
|
|
||||||
extern int CommitDelay;
|
extern int CommitDelay;
|
||||||
extern int CommitSiblings;
|
extern int CommitSiblings;
|
||||||
|
|
||||||
extern bool FixBTree;
|
extern bool FixBTree;
|
||||||
|
|
||||||
#ifdef ENABLE_SYSLOG
|
#ifdef ENABLE_SYSLOG
|
||||||
extern char *Syslog_facility;
|
extern char *Syslog_facility;
|
||||||
extern char *Syslog_ident;
|
extern char *Syslog_ident;
|
||||||
bool check_facility(const char *facility);
|
static bool check_facility(const char *facility);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -138,7 +133,8 @@ struct config_string
|
|||||||
GucContext context;
|
GucContext context;
|
||||||
char **variable;
|
char **variable;
|
||||||
const char *default_val;
|
const char *default_val;
|
||||||
bool (*parse_hook)(const char *);
|
bool (*parse_hook)(const char *proposed);
|
||||||
|
void (*assign_hook)(const char *newval);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -330,25 +326,29 @@ static struct config_string
|
|||||||
ConfigureNamesString[] =
|
ConfigureNamesString[] =
|
||||||
{
|
{
|
||||||
{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
|
{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
|
||||||
PG_KRB_SRVTAB, NULL},
|
PG_KRB_SRVTAB, NULL, NULL},
|
||||||
|
|
||||||
{"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group,
|
|
||||||
"", NULL},
|
|
||||||
|
|
||||||
#ifdef ENABLE_SYSLOG
|
#ifdef ENABLE_SYSLOG
|
||||||
{"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
|
{"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
|
||||||
"LOCAL0", check_facility},
|
"LOCAL0", check_facility, NULL},
|
||||||
{"syslog_ident", PGC_POSTMASTER, &Syslog_ident,
|
{"syslog_ident", PGC_POSTMASTER, &Syslog_ident,
|
||||||
"postgres", NULL},
|
"postgres", NULL, NULL},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group,
|
||||||
|
"", NULL, NULL},
|
||||||
|
|
||||||
{"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir,
|
{"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir,
|
||||||
"", NULL},
|
"", NULL, NULL},
|
||||||
|
|
||||||
{"virtual_host", PGC_POSTMASTER, &VirtualHost,
|
{"virtual_host", PGC_POSTMASTER, &VirtualHost,
|
||||||
"", NULL},
|
"", NULL, NULL},
|
||||||
|
|
||||||
{NULL, 0, NULL, NULL, NULL}
|
{"wal_sync_method", PGC_SIGHUP, &XLOG_sync_method,
|
||||||
|
XLOG_sync_method_default,
|
||||||
|
check_xlog_sync_method, assign_xlog_sync_method},
|
||||||
|
|
||||||
|
{NULL, 0, NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******** end of options list ********/
|
/******** end of options list ********/
|
||||||
@ -723,7 +723,10 @@ set_config_option(const char * name, const char * value, GucContext
|
|||||||
elog(elevel, "out of memory");
|
elog(elevel, "out of memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
free(*conf->variable);
|
if (conf->assign_hook)
|
||||||
|
(conf->assign_hook)(str);
|
||||||
|
if (*conf->variable)
|
||||||
|
free(*conf->variable);
|
||||||
*conf->variable = str;
|
*conf->variable = str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -737,7 +740,10 @@ set_config_option(const char * name, const char * value, GucContext
|
|||||||
elog(elevel, "out of memory");
|
elog(elevel, "out of memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
free(*conf->variable);
|
if (conf->assign_hook)
|
||||||
|
(conf->assign_hook)(str);
|
||||||
|
if (*conf->variable)
|
||||||
|
free(*conf->variable);
|
||||||
*conf->variable = str;
|
*conf->variable = str;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -855,7 +861,7 @@ ParseLongOption(const char * string, char ** name, char ** value)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_SYSLOG
|
#ifdef ENABLE_SYSLOG
|
||||||
bool
|
static bool
|
||||||
check_facility(const char *facility)
|
check_facility(const char *facility)
|
||||||
{
|
{
|
||||||
if (strcasecmp(facility,"LOCAL0") == 0) return true;
|
if (strcasecmp(facility,"LOCAL0") == 0) return true;
|
||||||
|
@ -107,6 +107,8 @@
|
|||||||
#
|
#
|
||||||
#wal_buffers = 8 # min 4
|
#wal_buffers = 8 # min 4
|
||||||
#wal_files = 0 # range 0-64
|
#wal_files = 0 # range 0-64
|
||||||
|
#wal_sync_method = fsync # fsync or fdatasync or open_sync or open_datasync
|
||||||
|
# Note: default wal_sync_method varies across platforms
|
||||||
#wal_debug = 0 # range 0-16
|
#wal_debug = 0 # range 0-16
|
||||||
#commit_delay = 0 # range 0-100000
|
#commit_delay = 0 # range 0-100000
|
||||||
#commit_siblings = 5 # range 1-1000
|
#commit_siblings = 5 # range 1-1000
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: xlog.h,v 1.20 2001/03/13 20:32:37 tgl Exp $
|
* $Id: xlog.h,v 1.21 2001/03/16 05:44:33 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef XLOG_H
|
#ifndef XLOG_H
|
||||||
#define XLOG_H
|
#define XLOG_H
|
||||||
@ -176,6 +176,15 @@ extern StartUpID ThisStartUpID; /* current SUI */
|
|||||||
extern bool InRecovery;
|
extern bool InRecovery;
|
||||||
extern XLogRecPtr MyLastRecPtr;
|
extern XLogRecPtr MyLastRecPtr;
|
||||||
|
|
||||||
|
/* these variables are GUC parameters related to XLOG */
|
||||||
|
extern int CheckPointSegments;
|
||||||
|
extern int XLOGbuffers;
|
||||||
|
extern int XLOGfiles;
|
||||||
|
extern int XLOG_DEBUG;
|
||||||
|
extern char *XLOG_sync_method;
|
||||||
|
extern const char XLOG_sync_method_default[];
|
||||||
|
|
||||||
|
|
||||||
extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata);
|
extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata);
|
||||||
extern void XLogFlush(XLogRecPtr RecPtr);
|
extern void XLogFlush(XLogRecPtr RecPtr);
|
||||||
|
|
||||||
@ -202,4 +211,7 @@ extern void GetRedoRecPtr(void);
|
|||||||
*/
|
*/
|
||||||
extern XLogRecPtr GetUndoRecPtr(void);
|
extern XLogRecPtr GetUndoRecPtr(void);
|
||||||
|
|
||||||
|
extern bool check_xlog_sync_method(const char *method);
|
||||||
|
extern void assign_xlog_sync_method(const char *method);
|
||||||
|
|
||||||
#endif /* XLOG_H */
|
#endif /* XLOG_H */
|
||||||
|
Reference in New Issue
Block a user