1. Checkpoint.undo may be after checkpoint itself:
authorVadim B. Mikheev <vadim4o@yahoo.com>
Tue, 9 Jan 2001 06:24:33 +0000 (06:24 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Tue, 9 Jan 2001 06:24:33 +0000 (06:24 +0000)
   - 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.

src/backend/access/transam/xlog.c
src/backend/utils/misc/guc.c

index 136ce1de7b054bc0c3e0f0ee3906b0b2431af1cb..c0b6104db5ab2f011d0a1846c357f7bc4c151bbf 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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 @@
 #include "miscadmin.h"
 
 int            XLOGbuffers = 8;
+int            XLOGfiles = 0;  /* how many files to pre-allocate */
 XLogRecPtr MyLastRecPtr = {0, 0};
 uint32     CritSectionCount = 0;
 bool       InRecovery = false;
@@ -182,6 +183,18 @@ typedef struct BkpBlock
 #define XLogLastSeg        (0xffffffff / XLogSegSize)
 #define XLogFileSize   (XLogLastSeg * XLogSegSize)
 
+#define NextLogSeg(_logId, _logSeg)        \
+{\
+   if (_logSeg >= XLogLastSeg)\
+   {\
+       _logId++;\
+       _logSeg = 0;\
+   }\
+   else\
+       _logSeg++;\
+}
+
+
 #define XLogFileName(path, log, seg)   \
            snprintf(path, MAXPGPATH, "%s%c%08X%08X",   \
                     XLogDir, SEP_CHAR, log, seg)
@@ -856,8 +869,8 @@ XLogWrite(char *buffer)
            UpdateControlFile();
            SpinRelease(ControlFileLockId);
            if (!usexistent)    /* there was no file */
-               elog(LOG, "XLogWrite: had to create new log file - "
-                   "you probably should do checkpoints more often");
+               elog(LOG, "XLogWrite: new log file created - "
+                   "try to increase WAL_FILES");
        }
 
        if (logFile < 0)
@@ -1186,7 +1199,7 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
        tmpRecPtr.xrecoff += SizeOfXLogPHD;
    }
    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);
 
    if (readFile >= 0 && (RecPtr->xlogid != readId ||
@@ -1232,15 +1245,21 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
    record = (XLogRecord *) ((char *) readBuf + RecPtr->xrecoff % BLCKSZ);
 
 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)
    {
-       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);
        goto next_record_is_invalid;
    }
    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);
        goto next_record_is_invalid;
    }
@@ -1841,8 +1860,6 @@ StartupXLOG()
        elog(STOP, "Invalid redo in checkPoint record");
    if (checkPoint.undo.xrecoff == 0)
        checkPoint.undo = RecPtr;
-   if (XLByteLT(RecPtr, checkPoint.undo))
-       elog(STOP, "Invalid undo in checkPoint record");
 
    if (XLByteLT(checkPoint.undo, RecPtr) || 
        XLByteLT(checkPoint.redo, RecPtr))
@@ -1969,6 +1986,23 @@ StartupXLOG()
        CreateCheckPoint(true);
        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;
 
    ControlFile->state = DB_IN_PRODUCTION;
@@ -2117,48 +2151,70 @@ CreateCheckPoint(bool shutdown)
 
    SpinAcquire(ControlFileLockId);
    if (shutdown)
+   {
+       /* probably should delete extra log files */
        ControlFile->state = DB_SHUTDOWNED;
-   else    /* create new log file */
+   }
+   else    /* create new log file(s) */
    {
-       if (recptr.xrecoff % XLogSegSize >= 
-           (uint32) (0.75 * XLogSegSize))
+       int     lf;
+       bool    usexistent = true;
+
+       _logId = recptr.xlogid;
+       _logSeg = (recptr.xrecoff - 1) / XLogSegSize;
+       if (XLOGfiles > 0)
        {
-           int     lf;
-           bool    usexistent = true;
+           struct timeval  delay;
+           int             i;
 
-           _logId = recptr.xlogid;
-           _logSeg = recptr.xrecoff / XLogSegSize;
-           if (_logSeg >= XLogLastSeg)
+           for (i = 1; i <= XLOGfiles; i++)
            {
-               _logId++;
-               _logSeg = 0;
+               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);
            close(lf);
        }
    }
 
    ControlFile->checkPoint = MyLastRecPtr;
-
-   _logId = ControlFile->logId;
-   _logSeg = ControlFile->logSeg - 1;
    strcpy(archdir, ControlFile->archdir);
-
    ControlFile->time = time(NULL);
    UpdateControlFile();
    SpinRelease(ControlFileLockId);
 
    /*
     * 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;
        _logSeg = checkPoint.undo.xrecoff / XLogSegSize;
    }
+   else
+   {
+       _logId = checkPoint.redo.xlogid;
+       _logSeg = checkPoint.redo.xrecoff / XLogSegSize;
+   }
    if (_logId || _logSeg)
    {
        if (_logSeg)
index 6b9b50416e31a53a1578b3d2be573d9f9aba8628..9c23f7317767a2fc2392d1e8e326339bd9eb2cec 100644 (file)
@@ -4,7 +4,7 @@
  * Support for grand unified configuration scheme, including SET
  * 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
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -38,6 +38,7 @@ extern bool Log_connections;
 
 extern int CheckPointTimeout;
 extern int XLOGbuffers;
+extern int XLOGfiles;
 extern int XLOG_DEBUG;
 extern int CommitDelay;
 
@@ -274,6 +275,9 @@ ConfigureNamesInt[] =
    {"wal_buffers",         PGC_POSTMASTER,         &XLOGbuffers,
     8, 4, INT_MAX},
 
+   {"wal_files",           PGC_POSTMASTER,         &XLOGfiles,
+    0, 0, 64},
+
    {"wal_debug",           PGC_SUSET,              &XLOG_DEBUG,
     0, 0, 16},