]> granicus.if.org Git - postgresql/commitdiff
Change xlog page-header format to include StartUpID. Use the SUI to
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 13 Mar 2001 20:32:37 +0000 (20:32 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 13 Mar 2001 20:32:37 +0000 (20:32 +0000)
detect case that next page in log came from an older run than the prior
page.  This avoids the necessity to re-zero the log after recovery from
a crash, which is good because we need not risk destroying valuable log
information.
This forces another initdb since yesterday :-(.  Need to get that log
reset utility done...

src/backend/access/transam/xlog.c
src/include/access/xlog.h

index 3d6b8255e969a1f03ac7eead7459658f0fde9dbd..d30392096830096d91b436ab705c0f1b8f18906a 100644 (file)
@@ -1,12 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * xlog.c
+ *             PostgreSQL transaction log manager
  *
  *
  * 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.56 2001/03/13 01:17:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.57 2001/03/13 20:32:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -344,6 +345,7 @@ static char *readBuf = NULL;
 static XLogRecPtr ReadRecPtr;
 static XLogRecPtr EndRecPtr;
 static XLogRecord *nextRecord = NULL;
+static StartUpID lastReadSUI;
 
 static bool InRedo = false;
 
@@ -355,6 +357,7 @@ static int  XLogFileOpen(uint32 log, uint32 seg, bool econt);
 static void PreallocXlogFiles(XLogRecPtr endptr);
 static void MoveOfflineLogs(uint32 log, uint32 seg);
 static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer);
+static bool ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI);
 static XLogRecord *ReadCheckpointRecord(XLogRecPtr RecPtr,
                                                                                const char *whichChkpt,
                                                                                char *buffer);
@@ -891,6 +894,7 @@ AdvanceXLInsertBuffer(void)
        MemSet((char*) Insert->currpage, 0, BLCKSZ);
        Insert->currpage->xlp_magic = XLOG_PAGE_MAGIC;
        /* Insert->currpage->xlp_info = 0; */   /* done by memset */
+       Insert->currpage->xlp_sui = ThisStartUpID;
 
        return update_needed;
 }
@@ -1498,6 +1502,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
                                total_len;
        uint32          targetPageOff;
        unsigned        i;
+       bool            nextmode = false;
 
        if (readBuf == NULL)
        {
@@ -1516,6 +1521,7 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
        if (RecPtr == NULL)
        {
                RecPtr = &tmpRecPtr;
+               nextmode = true;
                /* fast case if next record is on same page */
                if (nextRecord != NULL)
                {
@@ -1566,13 +1572,8 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer)
                                 readId, readSeg, readOff);
                        goto next_record_is_invalid;
                }
-               if (((XLogPageHeader) readBuf)->xlp_magic != XLOG_PAGE_MAGIC)
-               {
-                       elog(emode, "ReadRecord: invalid magic number %u in logfile %u seg %u off %u",
-                                ((XLogPageHeader) readBuf)->xlp_magic,
-                                readId, readSeg, readOff);
+               if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, nextmode))
                        goto next_record_is_invalid;
-               }
        }
        if ((((XLogPageHeader) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) &&
                RecPtr->xrecoff % BLCKSZ == SizeOfXLogPHD)
@@ -1651,13 +1652,8 @@ got_record:;
                                         readId, readSeg, readOff);
                                goto next_record_is_invalid;
                        }
-                       if (((XLogPageHeader) readBuf)->xlp_magic != XLOG_PAGE_MAGIC)
-                       {
-                               elog(emode, "ReadRecord: invalid magic number %u in logfile %u seg %u off %u",
-                                        ((XLogPageHeader) readBuf)->xlp_magic,
-                                        readId, readSeg, readOff);
+                       if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, true))
                                goto next_record_is_invalid;
-                       }
                        if (!(((XLogPageHeader) readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD))
                        {
                                elog(emode, "ReadRecord: there is no ContRecord flag in logfile %u seg %u off %u",
@@ -1719,6 +1715,50 @@ next_record_is_invalid:;
        return NULL;
 }
 
+/*
+ * Check whether the xlog header of a page just read in looks valid.
+ *
+ * This is just a convenience subroutine to avoid duplicated code in
+ * ReadRecord.  It's not intended for use from anywhere else.
+ */
+static bool
+ValidXLOGHeader(XLogPageHeader hdr, int emode, bool checkSUI)
+{
+       if (hdr->xlp_magic != XLOG_PAGE_MAGIC)
+       {
+               elog(emode, "ReadRecord: invalid magic number %04X in logfile %u seg %u off %u",
+                        hdr->xlp_magic, readId, readSeg, readOff);
+               return false;
+       }
+       if ((hdr->xlp_info & ~XLP_ALL_FLAGS) != 0)
+       {
+               elog(emode, "ReadRecord: invalid info bits %04X in logfile %u seg %u off %u",
+                        hdr->xlp_info, readId, readSeg, readOff);
+               return false;
+       }
+       /*
+        * We disbelieve a SUI less than the previous page's SUI, or more
+        * than a few counts greater.  In theory as many as 512 shutdown
+        * checkpoint records could appear on a 32K-sized xlog page, so
+        * that's the most differential there could legitimately be.
+        *
+        * Note this check can only be applied when we are reading the next page
+        * in sequence, so ReadRecord passes a flag indicating whether to check.
+        */
+       if (checkSUI)
+       {
+               if (hdr->xlp_sui < lastReadSUI ||
+                       hdr->xlp_sui > lastReadSUI + 512)
+               {
+                       elog(emode, "ReadRecord: out-of-sequence SUI %u (after %u) in logfile %u seg %u off %u",
+                                hdr->xlp_sui, lastReadSUI, readId, readSeg, readOff);
+                       return false;
+               }
+       }
+       lastReadSUI = hdr->xlp_sui;
+       return true;
+}
+
 /*
  * I/O routines for pg_control
  *
@@ -2023,6 +2063,7 @@ BootStrapXLOG(void)
        memset(buffer, 0, BLCKSZ);
        page->xlp_magic = XLOG_PAGE_MAGIC;
        page->xlp_info = 0;
+       page->xlp_sui = checkPoint.ThisStartUpID;
        record = (XLogRecord *) ((char *) page + SizeOfXLogPHD);
        record->xl_prev.xlogid = 0;
        record->xl_prev.xrecoff = 0;
index dd079496ed65bde9bdff40c0b156fc8c9267625e..fa51d68d39ecd861814b9a4073652e1822f940f4 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xlog.h,v 1.19 2001/03/13 01:17:06 tgl Exp $
+ * $Id: xlog.h,v 1.20 2001/03/13 20:32:37 tgl Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -26,6 +26,9 @@
  * really:
  *
  * SizeOfXLogRecord + xl_len + n_backup_blocks * (sizeof(BkpBlock) + BLCKSZ)
+ *
+ * rounded up to a MAXALIGN boundary (so that all xlog records start on
+ * MAXALIGN boundaries).
  */
 typedef struct XLogRecord
 {
@@ -105,12 +108,13 @@ typedef struct XLogContRecord
 /*
  * Each page of XLOG file has a header like this:
  */
-#define XLOG_PAGE_MAGIC 0x17345169 /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD058 /* can be used as WAL version indicator */
 
 typedef struct XLogPageHeaderData
 {
-       uint32          xlp_magic;              /* magic value for correctness checks */
+       uint16          xlp_magic;              /* magic value for correctness checks */
        uint16          xlp_info;               /* flag bits, see below */
+       StartUpID       xlp_sui;                /* StartUpID of first record on page */
 } XLogPageHeaderData;
 
 #define SizeOfXLogPHD  MAXALIGN(sizeof(XLogPageHeaderData))
@@ -119,6 +123,8 @@ typedef XLogPageHeaderData *XLogPageHeader;
 
 /* When record crosses page boundary, set this flag in new page's header */
 #define XLP_FIRST_IS_CONTRECORD                0x0001
+/* All defined flag bits in xlp_info (used for validity checking of header) */
+#define XLP_ALL_FLAGS                          0x0001
 
 /*
  * We break each logical log file (xlogid value) into 16Mb segments.