mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Rework WAL-reading supporting structs
The state-tracking of WAL reading in various places was pretty messy, mostly because the ancient physical-replication WAL reading code wasn't using the XLogReader abstraction. This led to some untidy code. Make it prettier by creating two additional supporting structs, WALSegmentContext and WALOpenSegment which keep track of WAL-reading state. This makes code cleaner, as well as supports more future cleanup. Author: Antonin Houska Reviewed-by: Álvaro Herrera and (older versions) Robert Haas Discussion: https://postgr.es/m/14984.1554998742@spoje.net
This commit is contained in:
@ -68,8 +68,8 @@ report_invalid_record(XLogReaderState *state, const char *fmt,...)
|
||||
* Returns NULL if the xlogreader couldn't be allocated.
|
||||
*/
|
||||
XLogReaderState *
|
||||
XLogReaderAllocate(int wal_segment_size, XLogPageReadCB pagereadfunc,
|
||||
void *private_data)
|
||||
XLogReaderAllocate(int wal_segment_size, const char *waldir,
|
||||
XLogPageReadCB pagereadfunc, void *private_data)
|
||||
{
|
||||
XLogReaderState *state;
|
||||
|
||||
@ -96,7 +96,10 @@ XLogReaderAllocate(int wal_segment_size, XLogPageReadCB pagereadfunc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->wal_segment_size = wal_segment_size;
|
||||
/* Initialize segment info. */
|
||||
WALOpenSegmentInit(&state->seg, &state->segcxt, wal_segment_size,
|
||||
waldir);
|
||||
|
||||
state->read_page = pagereadfunc;
|
||||
/* system_identifier initialized to zeroes above */
|
||||
state->private_data = private_data;
|
||||
@ -198,6 +201,23 @@ allocate_recordbuf(XLogReaderState *state, uint32 reclength)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the passed segment structs.
|
||||
*/
|
||||
void
|
||||
WALOpenSegmentInit(WALOpenSegment *seg, WALSegmentContext *segcxt,
|
||||
int segsize, const char *waldir)
|
||||
{
|
||||
seg->ws_file = -1;
|
||||
seg->ws_segno = 0;
|
||||
seg->ws_off = 0;
|
||||
seg->ws_tli = 0;
|
||||
|
||||
segcxt->ws_segsize = segsize;
|
||||
if (waldir)
|
||||
snprintf(segcxt->ws_dir, MAXPGPATH, "%s", waldir);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to read an XLOG record.
|
||||
*
|
||||
@ -490,8 +510,8 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
|
||||
(record->xl_info & ~XLR_INFO_MASK) == XLOG_SWITCH)
|
||||
{
|
||||
/* Pretend it extends to end of segment */
|
||||
state->EndRecPtr += state->wal_segment_size - 1;
|
||||
state->EndRecPtr -= XLogSegmentOffset(state->EndRecPtr, state->wal_segment_size);
|
||||
state->EndRecPtr += state->segcxt.ws_segsize - 1;
|
||||
state->EndRecPtr -= XLogSegmentOffset(state->EndRecPtr, state->segcxt.ws_segsize);
|
||||
}
|
||||
|
||||
if (DecodeXLogRecord(state, record, errormsg))
|
||||
@ -533,12 +553,12 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
|
||||
|
||||
Assert((pageptr % XLOG_BLCKSZ) == 0);
|
||||
|
||||
XLByteToSeg(pageptr, targetSegNo, state->wal_segment_size);
|
||||
targetPageOff = XLogSegmentOffset(pageptr, state->wal_segment_size);
|
||||
XLByteToSeg(pageptr, targetSegNo, state->segcxt.ws_segsize);
|
||||
targetPageOff = XLogSegmentOffset(pageptr, state->segcxt.ws_segsize);
|
||||
|
||||
/* check whether we have all the requested data already */
|
||||
if (targetSegNo == state->readSegNo && targetPageOff == state->readOff &&
|
||||
reqLen <= state->readLen)
|
||||
if (targetSegNo == state->seg.ws_segno &&
|
||||
targetPageOff == state->seg.ws_off && reqLen <= state->readLen)
|
||||
return state->readLen;
|
||||
|
||||
/*
|
||||
@ -553,13 +573,13 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
|
||||
* record is. This is so that we can check the additional identification
|
||||
* info that is present in the first page's "long" header.
|
||||
*/
|
||||
if (targetSegNo != state->readSegNo && targetPageOff != 0)
|
||||
if (targetSegNo != state->seg.ws_segno && targetPageOff != 0)
|
||||
{
|
||||
XLogRecPtr targetSegmentPtr = pageptr - targetPageOff;
|
||||
|
||||
readLen = state->read_page(state, targetSegmentPtr, XLOG_BLCKSZ,
|
||||
state->currRecPtr,
|
||||
state->readBuf, &state->readPageTLI);
|
||||
state->readBuf);
|
||||
if (readLen < 0)
|
||||
goto err;
|
||||
|
||||
@ -577,7 +597,7 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
|
||||
*/
|
||||
readLen = state->read_page(state, pageptr, Max(reqLen, SizeOfXLogShortPHD),
|
||||
state->currRecPtr,
|
||||
state->readBuf, &state->readPageTLI);
|
||||
state->readBuf);
|
||||
if (readLen < 0)
|
||||
goto err;
|
||||
|
||||
@ -596,7 +616,7 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
|
||||
{
|
||||
readLen = state->read_page(state, pageptr, XLogPageHeaderSize(hdr),
|
||||
state->currRecPtr,
|
||||
state->readBuf, &state->readPageTLI);
|
||||
state->readBuf);
|
||||
if (readLen < 0)
|
||||
goto err;
|
||||
}
|
||||
@ -608,8 +628,8 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
|
||||
goto err;
|
||||
|
||||
/* update read state information */
|
||||
state->readSegNo = targetSegNo;
|
||||
state->readOff = targetPageOff;
|
||||
state->seg.ws_segno = targetSegNo;
|
||||
state->seg.ws_off = targetPageOff;
|
||||
state->readLen = readLen;
|
||||
|
||||
return readLen;
|
||||
@ -625,8 +645,8 @@ err:
|
||||
static void
|
||||
XLogReaderInvalReadState(XLogReaderState *state)
|
||||
{
|
||||
state->readSegNo = 0;
|
||||
state->readOff = 0;
|
||||
state->seg.ws_segno = 0;
|
||||
state->seg.ws_off = 0;
|
||||
state->readLen = 0;
|
||||
}
|
||||
|
||||
@ -745,16 +765,16 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
|
||||
Assert((recptr % XLOG_BLCKSZ) == 0);
|
||||
|
||||
XLByteToSeg(recptr, segno, state->wal_segment_size);
|
||||
offset = XLogSegmentOffset(recptr, state->wal_segment_size);
|
||||
XLByteToSeg(recptr, segno, state->segcxt.ws_segsize);
|
||||
offset = XLogSegmentOffset(recptr, state->segcxt.ws_segsize);
|
||||
|
||||
XLogSegNoOffsetToRecPtr(segno, offset, state->wal_segment_size, recaddr);
|
||||
XLogSegNoOffsetToRecPtr(segno, offset, state->segcxt.ws_segsize, recaddr);
|
||||
|
||||
if (hdr->xlp_magic != XLOG_PAGE_MAGIC)
|
||||
{
|
||||
char fname[MAXFNAMELEN];
|
||||
|
||||
XLogFileName(fname, state->readPageTLI, segno, state->wal_segment_size);
|
||||
XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
|
||||
|
||||
report_invalid_record(state,
|
||||
"invalid magic number %04X in log segment %s, offset %u",
|
||||
@ -768,7 +788,7 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
{
|
||||
char fname[MAXFNAMELEN];
|
||||
|
||||
XLogFileName(fname, state->readPageTLI, segno, state->wal_segment_size);
|
||||
XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
|
||||
|
||||
report_invalid_record(state,
|
||||
"invalid info bits %04X in log segment %s, offset %u",
|
||||
@ -791,7 +811,7 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
(unsigned long long) state->system_identifier);
|
||||
return false;
|
||||
}
|
||||
else if (longhdr->xlp_seg_size != state->wal_segment_size)
|
||||
else if (longhdr->xlp_seg_size != state->segcxt.ws_segsize)
|
||||
{
|
||||
report_invalid_record(state,
|
||||
"WAL file is from different database system: incorrect segment size in page header");
|
||||
@ -808,7 +828,7 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
{
|
||||
char fname[MAXFNAMELEN];
|
||||
|
||||
XLogFileName(fname, state->readPageTLI, segno, state->wal_segment_size);
|
||||
XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
|
||||
|
||||
/* hmm, first page of file doesn't have a long header? */
|
||||
report_invalid_record(state,
|
||||
@ -828,7 +848,7 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
{
|
||||
char fname[MAXFNAMELEN];
|
||||
|
||||
XLogFileName(fname, state->readPageTLI, segno, state->wal_segment_size);
|
||||
XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
|
||||
|
||||
report_invalid_record(state,
|
||||
"unexpected pageaddr %X/%X in log segment %s, offset %u",
|
||||
@ -853,7 +873,7 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
{
|
||||
char fname[MAXFNAMELEN];
|
||||
|
||||
XLogFileName(fname, state->readPageTLI, segno, state->wal_segment_size);
|
||||
XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
|
||||
|
||||
report_invalid_record(state,
|
||||
"out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u",
|
||||
@ -997,7 +1017,6 @@ out:
|
||||
|
||||
#endif /* FRONTEND */
|
||||
|
||||
|
||||
/* ----------------------------------------
|
||||
* Functions for decoding the data and block references in a record.
|
||||
* ----------------------------------------
|
||||
|
Reference in New Issue
Block a user