summaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c74
1 files changed, 47 insertions, 27 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7c18f0ff5a6..fbc4223034a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.53 2001/02/13 20:40:25 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.54 2001/02/18 04:39:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,13 @@
#include "miscadmin.h"
+
+/* Max time to wait to acquire XLog activity locks */
+#define XLOG_LOCK_TIMEOUT (5*60*1000000) /* 5 minutes */
+/* Max time to wait to acquire checkpoint lock */
+#define CHECKPOINT_LOCK_TIMEOUT (10*60*1000000) /* 10 minutes */
+
+
int XLOGbuffers = 8;
int XLOGfiles = 0; /* how many files to pre-allocate */
XLogRecPtr MyLastRecPtr = {0, 0};
@@ -178,8 +185,8 @@ typedef struct BkpBlock
/*
* We break each log file in 16Mb segments
*/
-#define XLogSegSize (16*1024*1024)
-#define XLogLastSeg (0xffffffff / XLogSegSize)
+#define XLogSegSize ((uint32) (16*1024*1024))
+#define XLogLastSeg (((uint32) 0xffffffff) / XLogSegSize)
#define XLogFileSize (XLogLastSeg * XLogSegSize)
#define NextLogSeg(_logId, _logSeg) \
@@ -423,7 +430,7 @@ begin:;
}
}
}
- S_LOCK_SLEEP(&(XLogCtl->insert_lck), i++);
+ S_LOCK_SLEEP(&(XLogCtl->insert_lck), i++, XLOG_LOCK_TIMEOUT);
if (!TAS(&(XLogCtl->insert_lck)))
break;
}
@@ -721,7 +728,7 @@ XLogFlush(XLogRecPtr record)
break;
}
}
- S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++);
+ S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++, XLOG_LOCK_TIMEOUT);
}
if (logFile >= 0 && (LgwrResult.Write.xlogid != logId ||
@@ -741,7 +748,7 @@ XLogFlush(XLogRecPtr record)
logFile = XLogFileOpen(logId, logSeg, false);
}
- if (pg_fsync(logFile) != 0)
+ if (pg_fdatasync(logFile) != 0)
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
logId, logSeg);
LgwrResult.Flush = LgwrResult.Write;
@@ -826,7 +833,7 @@ GetFreeXLBuffer()
InitXLBuffer(curridx);
return;
}
- S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++);
+ S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++, XLOG_LOCK_TIMEOUT);
}
}
@@ -846,7 +853,7 @@ XLogWrite(char *buffer)
{
if (wcnt > 0)
{
- if (pg_fsync(logFile) != 0)
+ if (pg_fdatasync(logFile) != 0)
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
logId, logSeg);
if (LgwrResult.Write.xlogid != logId)
@@ -928,7 +935,7 @@ XLogWrite(char *buffer)
if (XLByteLT(LgwrResult.Flush, LgwrRqst.Flush) &&
XLByteLE(LgwrRqst.Flush, LgwrResult.Write))
{
- if (pg_fsync(logFile) != 0)
+ if (pg_fdatasync(logFile) != 0)
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
logId, logSeg);
LgwrResult.Flush = LgwrResult.Write;
@@ -948,13 +955,14 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
{
char path[MAXPGPATH];
char tpath[MAXPGPATH];
+ char zbuffer[BLCKSZ];
int fd;
+ int nbytes;
XLogFileName(path, log, seg);
/*
- * Try to use existent file (checkpoint maker
- * creates it sometime).
+ * Try to use existent file (checkpoint maker creates it sometimes).
*/
if (*usexistent)
{
@@ -963,7 +971,7 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
{
if (errno != ENOENT)
elog(STOP, "InitOpen(logfile %u seg %u) failed: %m",
- logId, logSeg);
+ logId, logSeg);
}
else
return(fd);
@@ -979,33 +987,44 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
elog(STOP, "InitCreate(logfile %u seg %u) failed: %m",
logId, logSeg);
- if (lseek(fd, XLogSegSize - 1, SEEK_SET) != (off_t) (XLogSegSize - 1))
- elog(STOP, "lseek(logfile %u seg %u) failed: %m",
- logId, logSeg);
-
- if (write(fd, "", 1) != 1)
- elog(STOP, "write(logfile %u seg %u) failed: %m",
- logId, logSeg);
+ /*
+ * Zero-fill the file. We have to do this the hard way to ensure that
+ * all the file space has really been allocated --- on platforms that
+ * allow "holes" in files, just seeking to the end doesn't allocate
+ * intermediate space. This way, we know that we have all the space
+ * and (after the fsync below) that all the indirect blocks are down
+ * on disk. Therefore, fdatasync(2) will be sufficient to sync future
+ * writes to the log file.
+ */
+ MemSet(zbuffer, 0, sizeof(zbuffer));
+ for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
+ {
+ if ((int) write(fd, zbuffer, sizeof(zbuffer)) != (int) sizeof(zbuffer))
+ elog(STOP, "ZeroFill(logfile %u seg %u) failed: %m",
+ logId, logSeg);
+ }
if (pg_fsync(fd) != 0)
elog(STOP, "fsync(logfile %u seg %u) failed: %m",
logId, logSeg);
- if (lseek(fd, 0, SEEK_SET) < 0)
- elog(STOP, "lseek(logfile %u seg %u off %u) failed: %m",
- log, seg, 0);
-
close(fd);
+ /*
+ * Prefer link() to rename() here just to be sure that we don't overwrite
+ * an existing logfile. However, there shouldn't be one, so rename()
+ * is an acceptable substitute except for the truly paranoid.
+ */
#ifndef __BEOS__
if (link(tpath, path) < 0)
+ elog(STOP, "InitRelink(logfile %u seg %u) failed: %m",
+ logId, logSeg);
+ unlink(tpath);
#else
if (rename(tpath, path) < 0)
-#endif
elog(STOP, "InitRelink(logfile %u seg %u) failed: %m",
logId, logSeg);
-
- unlink(tpath);
+#endif
fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
if (fd < 0)
@@ -2101,7 +2120,8 @@ CreateCheckPoint(bool shutdown)
/* Grab lock, using larger than normal sleep between tries (1 sec) */
while (TAS(&(XLogCtl->chkp_lck)))
{
- S_LOCK_SLEEP_INTERVAL(&(XLogCtl->chkp_lck), spins++, 1000000);
+ S_LOCK_SLEEP_INTERVAL(&(XLogCtl->chkp_lck), spins++,
+ CHECKPOINT_LOCK_TIMEOUT, 1000000);
}
memset(&checkPoint, 0, sizeof(checkPoint));