Repair boundary-case bug introduced by patch of two months ago that
authorTom Lane <[email protected]>
Thu, 17 Jul 2003 16:45:25 +0000 (16:45 +0000)
committerTom Lane <[email protected]>
Thu, 17 Jul 2003 16:45:25 +0000 (16:45 +0000)
fixed incorrect initial setting of StartUpID.  The logic in XLogWrite()
expects that Write->curridx is advanced to the next page as soon as
LogwrtResult points to the end of the current page, but StartupXLOG()
failed to make that happen when the old WAL ended exactly on a page
boundary.  Per trouble report from Hannu Krosing.

src/backend/access/transam/xlog.c

index aead9250bb4b80b12aa52969715cd902c1b3892e..143ab67d8a81f7594652a51104f6cc38a86521ab 100644 (file)
@@ -2483,6 +2483,7 @@ StartupXLOG(void)
                                EndOfLog;
        XLogRecord *record;
        char       *buffer;
+       uint32          freespace;
 
        /* Use malloc() to ensure record buffer is MAXALIGNED */
        buffer = (char *) malloc(_INTL_MAXLOGRECSZ);
@@ -2678,8 +2679,6 @@ StartupXLOG(void)
        memcpy((char *) Insert->currpage, readBuf, BLCKSZ);
        Insert->currpos = (char *) Insert->currpage +
                (EndOfLog.xrecoff + BLCKSZ - XLogCtl->xlblocks[0].xrecoff);
-       /* Make sure rest of page is zero */
-       MemSet(Insert->currpos, 0, INSERT_FREESPACE(Insert));
 
        LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
 
@@ -2690,6 +2689,27 @@ StartupXLOG(void)
        XLogCtl->LogwrtRqst.Write = EndOfLog;
        XLogCtl->LogwrtRqst.Flush = EndOfLog;
 
+       freespace = INSERT_FREESPACE(Insert);
+       if (freespace > 0)
+       {
+               /* Make sure rest of page is zero */
+               MemSet(Insert->currpos, 0, freespace);
+               XLogCtl->Write.curridx = 0;
+       }
+       else
+       {
+               /*
+                * Whenever Write.LogwrtResult points to exactly the end of a page,
+                * Write.curridx must point to the *next* page (see XLogWrite()).
+                *
+                * Note: it might seem we should do AdvanceXLInsertBuffer() here,
+                * but we can't since we haven't yet determined the correct StartUpID
+                * to put into the new page's header.  The first actual attempt to
+                * insert a log record will advance the insert state.
+                */
+               XLogCtl->Write.curridx = NextBufIdx(0);
+       }
+
 #ifdef NOT_USED
        /* UNDO */
        if (InRecovery)