Change xlog page-header format to include StartUpID. Use the SUI to

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...
This commit is contained in:
Tom Lane 2001-03-13 20:32:37 +00:00
parent e2f91389a5
commit 1b87e24c4a
2 changed files with 63 additions and 16 deletions

View 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;

View 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.