Commit 4b59366e authored by Vadim B. Mikheev's avatar Vadim B. Mikheev

1. Checkpoint.undo may be after checkpoint itself:

   - no more elog(STOP) in StartupXLOG();
   - both checkpoint' undo & redo are used to define
     oldest on-line log file.
2. Ability to pre-allocate a few log files at checkpoint time
   (wal_files option). Off by default.
parent 329001a2
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* 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.47 2000/12/30 06:52:34 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.48 2001/01/09 06:24:32 vadim Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "miscadmin.h" #include "miscadmin.h"
int XLOGbuffers = 8; int XLOGbuffers = 8;
int XLOGfiles = 0; /* how many files to pre-allocate */
XLogRecPtr MyLastRecPtr = {0, 0}; XLogRecPtr MyLastRecPtr = {0, 0};
uint32 CritSectionCount = 0; uint32 CritSectionCount = 0;
bool InRecovery = false; bool InRecovery = false;
...@@ -182,6 +183,18 @@ typedef struct BkpBlock ...@@ -182,6 +183,18 @@ typedef struct BkpBlock
#define XLogLastSeg (0xffffffff / XLogSegSize) #define XLogLastSeg (0xffffffff / XLogSegSize)
#define XLogFileSize (XLogLastSeg * XLogSegSize) #define XLogFileSize (XLogLastSeg * XLogSegSize)
#define NextLogSeg(_logId, _logSeg) \
{\
if (_logSeg >= XLogLastSeg)\
{\
_logId++;\
_logSeg = 0;\
}\
else\
_logSeg++;\
}
#define XLogFileName(path, log, seg) \ #define XLogFileName(path, log, seg) \
snprintf(path, MAXPGPATH, "%s%c%08X%08X", \ snprintf(path, MAXPGPATH, "%s%c%08X%08X", \
XLogDir, SEP_CHAR, log, seg) XLogDir, SEP_CHAR, log, seg)
...@@ -856,8 +869,8 @@ XLogWrite(char *buffer) ...@@ -856,8 +869,8 @@ XLogWrite(char *buffer)
UpdateControlFile(); UpdateControlFile();
SpinRelease(ControlFileLockId); SpinRelease(ControlFileLockId);
if (!usexistent) /* there was no file */ if (!usexistent) /* there was no file */
elog(LOG, "XLogWrite: had to create new log file - " elog(LOG, "XLogWrite: new log file created - "
"you probably should do checkpoints more often"); "try to increase WAL_FILES");
} }
if (logFile < 0) if (logFile < 0)
...@@ -1186,7 +1199,7 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer) ...@@ -1186,7 +1199,7 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
tmpRecPtr.xrecoff += SizeOfXLogPHD; tmpRecPtr.xrecoff += SizeOfXLogPHD;
} }
else if (!XRecOffIsValid(RecPtr->xrecoff)) else if (!XRecOffIsValid(RecPtr->xrecoff))
elog(STOP, "ReadRecord: invalid record offset in (%u, %u)", elog(STOP, "ReadRecord: invalid record offset at (%u, %u)",
RecPtr->xlogid, RecPtr->xrecoff); RecPtr->xlogid, RecPtr->xrecoff);
if (readFile >= 0 && (RecPtr->xlogid != readId || if (readFile >= 0 && (RecPtr->xlogid != readId ||
...@@ -1232,15 +1245,21 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer) ...@@ -1232,15 +1245,21 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
record = (XLogRecord *) ((char *) readBuf + RecPtr->xrecoff % BLCKSZ); record = (XLogRecord *) ((char *) readBuf + RecPtr->xrecoff % BLCKSZ);
got_record:; got_record:;
if (record->xl_len == 0)
{
elog(emode, "ReadRecord: record with zero len at (%u, %u)",
RecPtr->xlogid, RecPtr->xrecoff);
goto next_record_is_invalid;
}
if (record->xl_len > _INTL_MAXLOGRECSZ) if (record->xl_len > _INTL_MAXLOGRECSZ)
{ {
elog(emode, "ReadRecord: too long record len %u in (%u, %u)", elog(emode, "ReadRecord: too long record len %u at (%u, %u)",
record->xl_len, RecPtr->xlogid, RecPtr->xrecoff); record->xl_len, RecPtr->xlogid, RecPtr->xrecoff);
goto next_record_is_invalid; goto next_record_is_invalid;
} }
if (record->xl_rmid > RM_MAX_ID) if (record->xl_rmid > RM_MAX_ID)
{ {
elog(emode, "ReadRecord: invalid resource managed id %u in (%u, %u)", elog(emode, "ReadRecord: invalid resource managed id %u at (%u, %u)",
record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff); record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff);
goto next_record_is_invalid; goto next_record_is_invalid;
} }
...@@ -1841,8 +1860,6 @@ StartupXLOG() ...@@ -1841,8 +1860,6 @@ StartupXLOG()
elog(STOP, "Invalid redo in checkPoint record"); elog(STOP, "Invalid redo in checkPoint record");
if (checkPoint.undo.xrecoff == 0) if (checkPoint.undo.xrecoff == 0)
checkPoint.undo = RecPtr; checkPoint.undo = RecPtr;
if (XLByteLT(RecPtr, checkPoint.undo))
elog(STOP, "Invalid undo in checkPoint record");
if (XLByteLT(checkPoint.undo, RecPtr) || if (XLByteLT(checkPoint.undo, RecPtr) ||
XLByteLT(checkPoint.redo, RecPtr)) XLByteLT(checkPoint.redo, RecPtr))
...@@ -1969,6 +1986,23 @@ StartupXLOG() ...@@ -1969,6 +1986,23 @@ StartupXLOG()
CreateCheckPoint(true); CreateCheckPoint(true);
XLogCloseRelationCache(); XLogCloseRelationCache();
} }
if (XLOGfiles > 0) /* pre-allocate log files */
{
uint32 _logId = logId,
_logSeg = logSeg;
int lf, i;
bool usexistent;
for (i = 1; i <= XLOGfiles; i++)
{
NextLogSeg(_logId, _logSeg);
usexistent = false;
lf = XLogFileInit(_logId, _logSeg, &usexistent);
close(lf);
}
}
InRecovery = false; InRecovery = false;
ControlFile->state = DB_IN_PRODUCTION; ControlFile->state = DB_IN_PRODUCTION;
...@@ -2117,48 +2151,70 @@ CreateCheckPoint(bool shutdown) ...@@ -2117,48 +2151,70 @@ CreateCheckPoint(bool shutdown)
SpinAcquire(ControlFileLockId); SpinAcquire(ControlFileLockId);
if (shutdown) if (shutdown)
ControlFile->state = DB_SHUTDOWNED;
else /* create new log file */
{ {
if (recptr.xrecoff % XLogSegSize >= /* probably should delete extra log files */
(uint32) (0.75 * XLogSegSize)) ControlFile->state = DB_SHUTDOWNED;
}
else /* create new log file(s) */
{ {
int lf; int lf;
bool usexistent = true; bool usexistent = true;
_logId = recptr.xlogid; _logId = recptr.xlogid;
_logSeg = recptr.xrecoff / XLogSegSize; _logSeg = (recptr.xrecoff - 1) / XLogSegSize;
if (_logSeg >= XLogLastSeg) if (XLOGfiles > 0)
{ {
_logId++; struct timeval delay;
_logSeg = 0; int i;
for (i = 1; i <= XLOGfiles; i++)
{
usexistent = true;
NextLogSeg(_logId, _logSeg);
lf = XLogFileInit(_logId, _logSeg, &usexistent);
close(lf);
/*
* Give up ControlFileLockId for 1/50 sec to let other
* backends switch to new log file in XLogWrite()
*/
SpinRelease(ControlFileLockId);
delay.tv_sec = 0;
delay.tv_usec = 20000;
(void) select(0, NULL, NULL, NULL, &delay);
SpinAcquire(ControlFileLockId);
} }
else }
_logSeg++; else if ((recptr.xrecoff - 1) % XLogSegSize >=
(uint32) (0.75 * XLogSegSize))
{
NextLogSeg(_logId, _logSeg);
lf = XLogFileInit(_logId, _logSeg, &usexistent); lf = XLogFileInit(_logId, _logSeg, &usexistent);
close(lf); close(lf);
} }
} }
ControlFile->checkPoint = MyLastRecPtr; ControlFile->checkPoint = MyLastRecPtr;
_logId = ControlFile->logId;
_logSeg = ControlFile->logSeg - 1;
strcpy(archdir, ControlFile->archdir); strcpy(archdir, ControlFile->archdir);
ControlFile->time = time(NULL); ControlFile->time = time(NULL);
UpdateControlFile(); UpdateControlFile();
SpinRelease(ControlFileLockId); SpinRelease(ControlFileLockId);
/* /*
* Delete offline log files. Get oldest online * Delete offline log files. Get oldest online
* log file from undo rec if it's valid. * log file from redo or undo record, whatever
* is older.
*/ */
if (checkPoint.undo.xrecoff != 0) if (checkPoint.undo.xrecoff != 0 &&
XLByteLT(checkPoint.undo, checkPoint.redo))
{ {
_logId = checkPoint.undo.xlogid; _logId = checkPoint.undo.xlogid;
_logSeg = checkPoint.undo.xrecoff / XLogSegSize; _logSeg = checkPoint.undo.xrecoff / XLogSegSize;
} }
else
{
_logId = checkPoint.redo.xlogid;
_logSeg = checkPoint.redo.xrecoff / XLogSegSize;
}
if (_logId || _logSeg) if (_logId || _logSeg)
{ {
if (_logSeg) if (_logSeg)
......
...@@ -4,7 +4,7 @@ ...@@ -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.26 2000/12/03 14:36:46 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.27 2001/01/09 06:24:33 vadim 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>.
...@@ -38,6 +38,7 @@ extern bool Log_connections; ...@@ -38,6 +38,7 @@ extern bool Log_connections;
extern int CheckPointTimeout; extern int CheckPointTimeout;
extern int XLOGbuffers; extern int XLOGbuffers;
extern int XLOGfiles;
extern int XLOG_DEBUG; extern int XLOG_DEBUG;
extern int CommitDelay; extern int CommitDelay;
...@@ -274,6 +275,9 @@ ConfigureNamesInt[] = ...@@ -274,6 +275,9 @@ ConfigureNamesInt[] =
{"wal_buffers", PGC_POSTMASTER, &XLOGbuffers, {"wal_buffers", PGC_POSTMASTER, &XLOGbuffers,
8, 4, INT_MAX}, 8, 4, INT_MAX},
{"wal_files", PGC_POSTMASTER, &XLOGfiles,
0, 0, 64},
{"wal_debug", PGC_SUSET, &XLOG_DEBUG, {"wal_debug", PGC_SUSET, &XLOG_DEBUG,
0, 0, 16}, 0, 0, 16},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment