From 05dd489048d2a3c983a376469972816196f384c6 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Wed, 4 Mar 2026 12:42:12 +0800 Subject: [PATCH v7 12/12] WIP: xlogrecovery: consolidate file-local mutable state --- src/backend/access/transam/xlogrecovery.c | 395 ++++++++++++++-------- 1 file changed, 256 insertions(+), 139 deletions(-) diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index ecd66fd86a4..f683bebaec1 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -105,25 +105,10 @@ bool wal_receiver_create_temp_slot = false; * recoveryTargetTLIRequested: numeric value of requested timeline, if constant * * recoveryTargetTLI: the currently understood target timeline; changes - * - * expectedTLEs: a list of TimeLineHistoryEntries for recoveryTargetTLI and - * the timelines of its known parents, newest first (so recoveryTargetTLI is - * always the first list member). Only these TLIs are expected to be seen in - * the WAL segments we read, and indeed only these TLIs will be considered as - * candidate WAL files to open at all. - * - * curFileTLI: the TLI appearing in the name of the current input WAL file. - * (This is not necessarily the same as the timeline from which we are - * replaying WAL, which StartupXLOG calls replayTLI, because we could be - * scanning data that was copied from an ancestor timeline when the current - * file was created.) During a sequential scan we do not allow this value - * to decrease. */ RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal = RECOVERY_TARGET_TIMELINE_LATEST; TimeLineID recoveryTargetTLIRequested = 0; TimeLineID recoveryTargetTLI = 0; -static List *expectedTLEs; -static TimeLineID curFileTLI; /* * When ArchiveRecoveryRequested is set, archive recovery was requested, @@ -145,53 +130,12 @@ bool InArchiveRecovery = false; * in standby mode. These variables are only valid in the startup process. * They work similarly to ArchiveRecoveryRequested and InArchiveRecovery. */ -static bool StandbyModeRequested = false; bool StandbyMode = false; /* was a signal file present at startup? */ static bool standby_signal_file_found = false; static bool recovery_signal_file_found = false; -/* - * CheckPointLoc is the position of the checkpoint record that determines - * where to start the replay. It comes from the backup label file or the - * control file. - * - * RedoStartLSN is the checkpoint's REDO location, also from the backup label - * file or the control file. In standby mode, XLOG streaming usually starts - * from the position where an invalid record was found. But if we fail to - * read even the initial checkpoint record, we use the REDO location instead - * of the checkpoint location as the start position of XLOG streaming. - * Otherwise we would have to jump backwards to the REDO location after - * reading the checkpoint record, because the REDO record can precede the - * checkpoint record. - */ -static XLogRecPtr CheckPointLoc = InvalidXLogRecPtr; -static TimeLineID CheckPointTLI = 0; -static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr; -static TimeLineID RedoStartTLI = 0; - -/* - * Local copy of SharedHotStandbyActive variable. False actually means "not - * known, need to check the shared state". - */ -static bool LocalHotStandbyActive = false; - -/* - * Local copy of SharedPromoteIsTriggered variable. False actually means "not - * known, need to check the shared state". - */ -static bool LocalPromoteIsTriggered = false; - -/* Has the recovery code requested a walreceiver wakeup? */ -static bool doRequestWalReceiverReply; - -/* XLogReader object used to parse the WAL records */ -static XLogReaderState *xlogreader = NULL; - -/* XLogPrefetcher object used to consume WAL records with read-ahead */ -static XLogPrefetcher *xlogprefetcher = NULL; - /* Parameters passed down from ReadRecord to the XLogPageRead callback. */ typedef struct XLogPageReadPrivate { @@ -201,9 +145,6 @@ typedef struct XLogPageReadPrivate TimeLineID replayTLI; } XLogPageReadPrivate; -/* flag to tell XLogPageRead that we have started replaying */ -static bool InRedo = false; - /* * Codes indicating where we got a WAL file from during recovery, or where * to attempt to get one. @@ -219,6 +160,204 @@ typedef enum /* human-readable names for XLogSources, for debugging output */ static const char *const xlogSourceNames[] = {"any", "archive", "pg_wal", "stream"}; +/* + * Forward declaration for state field holding shared-memory recovery control + * pointer. + */ +typedef struct XLogRecoveryCtlData XLogRecoveryCtlData; + +/* + * File-local mutable state for WAL recovery. + * + * Keep state in a single object to avoid a broad set of independent static + * globals and make it easier to evolve recovery internals. + */ +typedef struct XLogRecoveryLocalState +{ + /* + * A list of TimeLineHistoryEntries for recoveryTargetTLI and the + * timelines of its known parents, newest first (so recoveryTargetTLI is + * always the first list member). Only these TLIs are expected to be seen + * in the WAL segments we read, and indeed only these TLIs will be + * considered as candidate WAL files to open at all. + */ + List *expectedTLEs; + + /* + * The TLI appearing in the name of the current input WAL file. (This is + * not necessarily the same as the timeline from which we are replaying + * WAL, which StartupXLOG calls replayTLI, because we could be scanning + * data that was copied from an ancestor timeline when the current file + * was created.) During a sequential scan we do not allow this value to + * decrease. + */ + TimeLineID curFileTLI; + + /* + * When StandbyModeRequested is set, standby mode was requested, i.e. + * standby.signal file was present. It is only valid in the startup + * process. + */ + bool standbyModeRequested; + + /* + * CheckPointLoc is the position of the checkpoint record that determines + * where to start the replay. It comes from the backup label file or the + * control file. + * + * RedoStartLSN is the checkpoint's REDO location, also from the backup + * label file or the control file. In standby mode, XLOG streaming + * usually starts from the position where an invalid record was found. But + * if we fail to read even the initial checkpoint record, we use the REDO + * location instead of the checkpoint location as the start position of + * XLOG streaming. Otherwise we would have to jump backwards to the REDO + * location after reading the checkpoint record, because the REDO record + * can precede the checkpoint record. + */ + XLogRecPtr checkPointLoc; + TimeLineID checkPointTLI; + XLogRecPtr redoStartLSN; + TimeLineID redoStartTLI; + + /* + * Local copy of SharedHotStandbyActive variable. False actually means + * "not known, need to check the shared state". + */ + bool localHotStandbyActive; + + /* + * Local copy of SharedPromoteIsTriggered variable. False actually means + * "not known, need to check the shared state". + */ + bool localPromoteIsTriggered; + + /* Has the recovery code requested a walreceiver wakeup? */ + bool doRequestWalReceiverReply; + + /* XLogReader object used to parse the WAL records */ + XLogReaderState *xlogReader; + + /* XLogPrefetcher object used to consume WAL records with read-ahead */ + XLogPrefetcher *xlogPrefetcher; + + /* flag to tell XLogPageRead that we have started replaying */ + bool inRedo; + + /* + * readFile is -1 or a kernel FD for the log file segment that's currently + * open for reading. readSegNo identifies the segment. readOff is the + * offset of the page just read, readLen indicates how much of it has been + * read into readBuf, and readSource indicates where we got the currently + * open file from. + * + * Note: we could use Reserve/ReleaseExternalFD to track consumption of + * this FD too (like for openLogFile in xlog.c); but it doesn't currently + * seem worthwhile, since the XLOG is not read by general-purpose + * sessions. + */ + int readFile; + XLogSegNo readSegNo; + uint32 readOff; + uint32 readLen; + XLogSource readSource; + + /* + * Keeps track of which source we're currently reading from. This is + * different from readSource in that this is always set, even when we + * don't currently have a WAL file open. If lastSourceFailed is set, our + * last attempt to read from currentSource failed, and we should try + * another source next. + * + * pendingWalRcvRestart is set when a config change occurs that requires a + * walreceiver restart. This is only valid in XLOG_FROM_STREAM state. + */ + XLogSource currentSource; + bool lastSourceFailed; + bool pendingWalRcvRestart; + + /* + * These variables track when we last obtained some WAL data to process, + * and where we got it from. (XLogReceiptSource is initially the same as + * readSource, but readSource gets reset to zero when we don't have data + * to process right now. It is also different from currentSource, which + * also changes when we try to read from a source and fail, while + * XLogReceiptSource tracks where we last successfully read some WAL.) + */ + TimestampTz xlogReceiptTime; + XLogSource xlogReceiptSource; + + /* Local copy of WalRcv->flushedUpto */ + XLogRecPtr flushedUpto; + TimeLineID receiveTLI; + + /* Copy of backupEndRequired from the control file */ + bool backupEndRequired; + + /* Buffers dedicated to consistency checks of size BLCKSZ */ + char *replayImageMasked; + char *primaryImageMasked; + + XLogRecoveryCtlData *xlogRecoveryCtl; + + /* + * if recoveryStopsBefore/After returns true, it saves information of the + * stop point here + */ + TransactionId recoveryStopXid; + TimestampTz recoveryStopTime; + XLogRecPtr recoveryStopLSN; + char recoveryStopName[MAXFNAMELEN]; + bool recoveryStopAfter; +} XLogRecoveryLocalState; + +static XLogRecoveryLocalState XLogRecoveryState = +{ + .checkPointLoc = InvalidXLogRecPtr, + .redoStartLSN = InvalidXLogRecPtr, + .readFile = -1, + .readSource = XLOG_FROM_ANY, + .currentSource = XLOG_FROM_ANY, + .xlogReceiptSource = XLOG_FROM_ANY, + .flushedUpto = InvalidXLogRecPtr, + .xlogReader = NULL, + .xlogPrefetcher = NULL +}; + +#define expectedTLEs (XLogRecoveryState.expectedTLEs) +#define curFileTLI (XLogRecoveryState.curFileTLI) +#define StandbyModeRequested (XLogRecoveryState.standbyModeRequested) +#define CheckPointLoc (XLogRecoveryState.checkPointLoc) +#define CheckPointTLI (XLogRecoveryState.checkPointTLI) +#define RedoStartLSN (XLogRecoveryState.redoStartLSN) +#define RedoStartTLI (XLogRecoveryState.redoStartTLI) +#define LocalHotStandbyActive (XLogRecoveryState.localHotStandbyActive) +#define LocalPromoteIsTriggered (XLogRecoveryState.localPromoteIsTriggered) +#define doRequestWalReceiverReply (XLogRecoveryState.doRequestWalReceiverReply) +#define InRedo (XLogRecoveryState.inRedo) +#define readFile (XLogRecoveryState.readFile) +#define readSegNo (XLogRecoveryState.readSegNo) +#define readOff (XLogRecoveryState.readOff) +#define readLen (XLogRecoveryState.readLen) +#define readSource (XLogRecoveryState.readSource) +#define currentSource (XLogRecoveryState.currentSource) +#define lastSourceFailed (XLogRecoveryState.lastSourceFailed) +#define pendingWalRcvRestart (XLogRecoveryState.pendingWalRcvRestart) +#define XLogReceiptTime (XLogRecoveryState.xlogReceiptTime) +#define XLogReceiptSource (XLogRecoveryState.xlogReceiptSource) +#define flushedUpto (XLogRecoveryState.flushedUpto) +#define receiveTLI (XLogRecoveryState.receiveTLI) +#define xlogreader (XLogRecoveryState.xlogReader) +#define xlogprefetcher (XLogRecoveryState.xlogPrefetcher) +#define BackupEndRequired (XLogRecoveryState.backupEndRequired) +#define replay_image_masked (XLogRecoveryState.replayImageMasked) +#define primary_image_masked (XLogRecoveryState.primaryImageMasked) +#define XLogRecoveryCtl (XLogRecoveryState.xlogRecoveryCtl) +#define recoveryStopXid (XLogRecoveryState.recoveryStopXid) +#define recoveryStopTime (XLogRecoveryState.recoveryStopTime) +#define recoveryStopLSN (XLogRecoveryState.recoveryStopLSN) +#define recoveryStopName (XLogRecoveryState.recoveryStopName) +#define recoveryStopAfter (XLogRecoveryState.recoveryStopAfter) + /* * readFile is -1 or a kernel FD for the log file segment that's currently * open for reading. readSegNo identifies the segment. readOff is the offset @@ -229,11 +368,6 @@ static const char *const xlogSourceNames[] = {"any", "archive", "pg_wal", "strea * FD too (like for openLogFile in xlog.c); but it doesn't currently seem * worthwhile, since the XLOG is not read by general-purpose sessions. */ -static int readFile = -1; -static XLogSegNo readSegNo = 0; -static uint32 readOff = 0; -static uint32 readLen = 0; -static XLogSource readSource = XLOG_FROM_ANY; /* * Keeps track of which source we're currently reading from. This is @@ -245,9 +379,6 @@ static XLogSource readSource = XLOG_FROM_ANY; * pendingWalRcvRestart is set when a config change occurs that requires a * walreceiver restart. This is only valid in XLOG_FROM_STREAM state. */ -static XLogSource currentSource = XLOG_FROM_ANY; -static bool lastSourceFailed = false; -static bool pendingWalRcvRestart = false; /* * These variables track when we last obtained some WAL data to process, @@ -257,12 +388,8 @@ static bool pendingWalRcvRestart = false; * also changes when we try to read from a source and fail, while * XLogReceiptSource tracks where we last successfully read some WAL.) */ -static TimestampTz XLogReceiptTime = 0; -static XLogSource XLogReceiptSource = XLOG_FROM_ANY; /* Local copy of WalRcv->flushedUpto */ -static XLogRecPtr flushedUpto = InvalidXLogRecPtr; -static TimeLineID receiveTLI = 0; /* * Copy of minRecoveryPoint and backupEndPoint from the control file. @@ -282,7 +409,6 @@ static TimeLineID minRecoveryPointTLI; static XLogRecPtr backupStartPoint; static XLogRecPtr backupEndPoint; -static bool backupEndRequired = false; /* * Have we reached a consistent database state? In crash recovery, we have @@ -301,8 +427,6 @@ static bool backupEndRequired = false; bool reachedConsistency = false; /* Buffers dedicated to consistency checks of size BLCKSZ */ -static char *replay_image_masked = NULL; -static char *primary_image_masked = NULL; /* @@ -368,8 +492,6 @@ typedef struct XLogRecoveryCtlData slock_t info_lck; /* locks shared variables shown above */ } XLogRecoveryCtlData; -static XLogRecoveryCtlData *XLogRecoveryCtl = NULL; - /* * abortedRecPtr is the start pointer of a broken record at end of WAL when * recovery completes; missingContrecPtr is the location of the first @@ -383,21 +505,16 @@ static XLogRecPtr missingContrecPtr; * if recoveryStopsBefore/After returns true, it saves information of the stop * point here */ -static TransactionId recoveryStopXid; -static TimestampTz recoveryStopTime; -static XLogRecPtr recoveryStopLSN; -static char recoveryStopName[MAXFNAMELEN]; -static bool recoveryStopAfter; /* prototypes for local functions */ -static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI); +static void ApplyWalRecord(XLogReaderState *reader, XLogRecord *record, TimeLineID *replayTLI); static void EnableStandbyMode(void); static void readRecoverySignalFile(void); static void validateRecoveryParameters(void); static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, - bool *backupEndRequired, bool *backupFromStandby); + bool *backupEndRequiredPtr, bool *backupFromStandby); static bool read_tablespace_map(List **tablespaces); static void xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI); @@ -419,11 +536,11 @@ static void recoveryPausesHere(bool endOfRecovery); static bool recoveryApplyDelay(XLogReaderState *record); static void ConfirmRecoveryPaused(void); -static XLogRecord *ReadRecord(XLogPrefetcher *xlogprefetcher, +static XLogRecord *ReadRecord(XLogPrefetcher *prefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI); -static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, +static int XLogPageRead(XLogReaderState *reader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf); static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, @@ -433,7 +550,7 @@ static XLogPageReadResult WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, XLogRecPtr replayLSN, bool nonblocking); static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr); -static XLogRecord *ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, +static XLogRecord *ReadCheckpointRecord(XLogPrefetcher *prefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI); static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN); static int XLogFileRead(XLogSegNo segno, TimeLineID tli, @@ -596,7 +713,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, * process after checking for signal files and after performing validation * of the recovery parameters. */ - if (read_backup_label(&CheckPointLoc, &CheckPointTLI, &backupEndRequired, + if (read_backup_label(&CheckPointLoc, &CheckPointTLI, &BackupEndRequired, &backupFromStandby)) { List *tablespaces = NIL; @@ -994,7 +1111,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, if (haveBackupLabel) { ControlFile->backupStartPoint = checkPoint.redo; - ControlFile->backupEndRequired = backupEndRequired; + ControlFile->backupEndRequired = BackupEndRequired; if (backupFromStandby) { @@ -1011,7 +1128,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, /* remember these, so that we know when we have reached consistency */ backupStartPoint = ControlFile->backupStartPoint; - backupEndRequired = ControlFile->backupEndRequired; + BackupEndRequired = ControlFile->backupEndRequired; backupEndPoint = ControlFile->backupEndPoint; if (InArchiveRecovery) { @@ -1227,7 +1344,7 @@ validateRecoveryParameters(void) */ static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, - bool *backupEndRequired, bool *backupFromStandby) + bool *backupEndRequiredPtr, bool *backupFromStandby) { char startxlogfilename[MAXFNAMELEN]; TimeLineID tli_from_walseg, @@ -1244,7 +1361,7 @@ read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, /* suppress possible uninitialized-variable warnings */ *checkPointLoc = InvalidXLogRecPtr; *backupLabelTLI = 0; - *backupEndRequired = false; + *backupEndRequiredPtr = false; *backupFromStandby = false; /* @@ -1294,7 +1411,7 @@ read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, if (fscanf(lfp, "BACKUP METHOD: %19s\n", backuptype) == 1) { if (strcmp(backuptype, "streamed") == 0) - *backupEndRequired = true; + *backupEndRequiredPtr = true; } /* @@ -1939,14 +2056,14 @@ PerformWalRecovery(void) * Subroutine of PerformWalRecovery, to apply one WAL record. */ static void -ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI) +ApplyWalRecord(XLogReaderState *reader, XLogRecord *record, TimeLineID *replayTLI) { ErrorContextCallback errcallback; bool switchedTLI = false; /* Setup error traceback support for ereport() */ errcallback.callback = rm_redo_error_callback; - errcallback.arg = xlogreader; + errcallback.arg = reader; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1973,7 +2090,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl { CheckPoint checkPoint; - memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint)); + memcpy(&checkPoint, XLogRecGetData(reader), sizeof(CheckPoint)); newReplayTLI = checkPoint.ThisTimeLineID; prevReplayTLI = checkPoint.PrevTimeLineID; } @@ -1981,7 +2098,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl { xl_end_of_recovery xlrec; - memcpy(&xlrec, XLogRecGetData(xlogreader), sizeof(xl_end_of_recovery)); + memcpy(&xlrec, XLogRecGetData(reader), sizeof(xl_end_of_recovery)); newReplayTLI = xlrec.ThisTimeLineID; prevReplayTLI = xlrec.PrevTimeLineID; } @@ -1989,7 +2106,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl if (newReplayTLI != *replayTLI) { /* Check that it's OK to switch to this TLI */ - checkTimeLineSwitch(xlogreader->EndRecPtr, + checkTimeLineSwitch(reader->EndRecPtr, newReplayTLI, prevReplayTLI, *replayTLI); /* Following WAL records should be run with new TLI */ @@ -2003,7 +2120,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl * XLogFlush will update minRecoveryPoint correctly. */ SpinLockAcquire(&XLogRecoveryCtl->info_lck); - XLogRecoveryCtl->replayEndRecPtr = xlogreader->EndRecPtr; + XLogRecoveryCtl->replayEndRecPtr = reader->EndRecPtr; XLogRecoveryCtl->replayEndTLI = *replayTLI; SpinLockRelease(&XLogRecoveryCtl->info_lck); @@ -2019,10 +2136,10 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl * directly here, rather than in xlog_redo() */ if (record->xl_rmid == RM_XLOG_ID) - xlogrecovery_redo(xlogreader, *replayTLI); + xlogrecovery_redo(reader, *replayTLI); /* Now apply the WAL record itself */ - GetRmgr(record->xl_rmid).rm_redo(xlogreader); + GetRmgr(record->xl_rmid).rm_redo(reader); /* * After redo, check whether the backup pages associated with the WAL @@ -2030,7 +2147,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl * if consistency check is enabled for this record. */ if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0) - verifyBackupPageConsistency(xlogreader); + verifyBackupPageConsistency(reader); /* Pop the error context stack */ error_context_stack = errcallback.previous; @@ -2040,8 +2157,8 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl * replayed. */ SpinLockAcquire(&XLogRecoveryCtl->info_lck); - XLogRecoveryCtl->lastReplayedReadRecPtr = xlogreader->ReadRecPtr; - XLogRecoveryCtl->lastReplayedEndRecPtr = xlogreader->EndRecPtr; + XLogRecoveryCtl->lastReplayedReadRecPtr = reader->ReadRecPtr; + XLogRecoveryCtl->lastReplayedEndRecPtr = reader->EndRecPtr; XLogRecoveryCtl->lastReplayedTLI = *replayTLI; SpinLockRelease(&XLogRecoveryCtl->info_lck); @@ -2091,7 +2208,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl * Before we continue on the new timeline, clean up any (possibly * bogus) future WAL segments on the old timeline. */ - RemoveNonParentXlogFiles(xlogreader->EndRecPtr, *replayTLI); + RemoveNonParentXlogFiles(reader->EndRecPtr, *replayTLI); /* Reset the prefetcher. */ XLogPrefetchReconfigure(); @@ -2246,7 +2363,7 @@ CheckRecoveryConsistency(void) ReachedEndOfBackup(lastReplayedEndRecPtr, lastReplayedTLI); backupStartPoint = InvalidXLogRecPtr; backupEndPoint = InvalidXLogRecPtr; - backupEndRequired = false; + BackupEndRequired = false; ereport(LOG, errmsg("completed backup recovery with redo LSN %X/%08X and end LSN %X/%08X", @@ -2260,7 +2377,7 @@ CheckRecoveryConsistency(void) * XLOG_BACKUP_END arrives to advise us of the correct minRecoveryPoint. * All we know prior to that is that we're not consistent yet. */ - if (!reachedConsistency && !backupEndRequired && + if (!reachedConsistency && !BackupEndRequired && minRecoveryPoint <= lastReplayedEndRecPtr) { /* @@ -3164,19 +3281,19 @@ ConfirmRecoveryPaused(void) * record is available. */ static XLogRecord * -ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, +ReadRecord(XLogPrefetcher *prefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI) { XLogRecord *record; - XLogReaderState *xlogreader = XLogPrefetcherGetReader(xlogprefetcher); - XLogPageReadPrivate *private = (XLogPageReadPrivate *) xlogreader->private_data; + XLogReaderState *reader = XLogPrefetcherGetReader(prefetcher); + XLogPageReadPrivate *private = (XLogPageReadPrivate *) reader->private_data; Assert(AmStartupProcess() || !IsUnderPostmaster); /* Pass through parameters to XLogPageRead */ private->fetching_ckpt = fetching_ckpt; private->emode = emode; - private->randAccess = !XLogRecPtrIsValid(xlogreader->ReadRecPtr); + private->randAccess = !XLogRecPtrIsValid(reader->ReadRecPtr); private->replayTLI = replayTLI; /* This is the first attempt to read this page. */ @@ -3186,7 +3303,7 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, { char *errormsg; - record = XLogPrefetcherReadRecord(xlogprefetcher, &errormsg); + record = XLogPrefetcherReadRecord(prefetcher, &errormsg); if (record == NULL) { /* @@ -3202,10 +3319,10 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, * overwrite contrecord in the wrong place, breaking everything. */ if (!ArchiveRecoveryRequested && - XLogRecPtrIsValid(xlogreader->abortedRecPtr)) + XLogRecPtrIsValid(reader->abortedRecPtr)) { - abortedRecPtr = xlogreader->abortedRecPtr; - missingContrecPtr = xlogreader->missingContrecPtr; + abortedRecPtr = reader->abortedRecPtr; + missingContrecPtr = reader->missingContrecPtr; } if (readFile >= 0) @@ -3221,29 +3338,29 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, * shouldn't loop anymore in that case. */ if (errormsg) - ereport(emode_for_corrupt_record(emode, xlogreader->EndRecPtr), + ereport(emode_for_corrupt_record(emode, reader->EndRecPtr), (errmsg_internal("%s", errormsg) /* already translated */ )); } /* * Check page TLI is one of the expected values. */ - else if (!tliInHistory(xlogreader->latestPageTLI, expectedTLEs)) + else if (!tliInHistory(reader->latestPageTLI, expectedTLEs)) { char fname[MAXFNAMELEN]; XLogSegNo segno; int32 offset; - XLByteToSeg(xlogreader->latestPagePtr, segno, wal_segment_size); - offset = XLogSegmentOffset(xlogreader->latestPagePtr, + XLByteToSeg(reader->latestPagePtr, segno, wal_segment_size); + offset = XLogSegmentOffset(reader->latestPagePtr, wal_segment_size); - XLogFileName(fname, xlogreader->seg.ws_tli, segno, + XLogFileName(fname, reader->seg.ws_tli, segno, wal_segment_size); - ereport(emode_for_corrupt_record(emode, xlogreader->EndRecPtr), + ereport(emode_for_corrupt_record(emode, reader->EndRecPtr), errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%08X, offset %u", - xlogreader->latestPageTLI, + reader->latestPageTLI, fname, - LSN_FORMAT_ARGS(xlogreader->latestPagePtr), + LSN_FORMAT_ARGS(reader->latestPagePtr), offset)); record = NULL; } @@ -3279,8 +3396,8 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, if (StandbyModeRequested) EnableStandbyMode(); - SwitchIntoArchiveRecovery(xlogreader->EndRecPtr, replayTLI); - minRecoveryPoint = xlogreader->EndRecPtr; + SwitchIntoArchiveRecovery(reader->EndRecPtr, replayTLI); + minRecoveryPoint = reader->EndRecPtr; minRecoveryPointTLI = replayTLI; CheckRecoveryConsistency(); @@ -3333,11 +3450,11 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, * sleep and retry. */ static int -XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, +XLogPageRead(XLogReaderState *reader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf) { XLogPageReadPrivate *private = - (XLogPageReadPrivate *) xlogreader->private_data; + (XLogPageReadPrivate *) reader->private_data; int emode = private->emode; uint32 targetPageOff; XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY; @@ -3384,7 +3501,7 @@ retry: flushedUpto < targetPagePtr + reqLen)) { if (readFile >= 0 && - xlogreader->nonblocking && + reader->nonblocking && readSource == XLOG_FROM_STREAM && flushedUpto < targetPagePtr + reqLen) return XLREAD_WOULDBLOCK; @@ -3394,8 +3511,8 @@ retry: private->fetching_ckpt, targetRecPtr, private->replayTLI, - xlogreader->EndRecPtr, - xlogreader->nonblocking)) + reader->EndRecPtr, + reader->nonblocking)) { case XLREAD_WOULDBLOCK: return XLREAD_WOULDBLOCK; @@ -3479,7 +3596,7 @@ retry: Assert(targetPageOff == readOff); Assert(reqLen <= readLen); - xlogreader->seg.ws_tli = curFileTLI; + reader->seg.ws_tli = curFileTLI; /* * Check the page header immediately, so that we can retry immediately if @@ -3515,18 +3632,18 @@ retry: */ if (StandbyMode && (targetPagePtr % wal_segment_size) == 0 && - !XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf)) + !XLogReaderValidatePageHeader(reader, targetPagePtr, readBuf)) { /* * Emit this error right now then retry this page immediately. Use * errmsg_internal() because the message was already translated. */ - if (xlogreader->errormsg_buf[0]) - ereport(emode_for_corrupt_record(emode, xlogreader->EndRecPtr), - (errmsg_internal("%s", xlogreader->errormsg_buf))); + if (reader->errormsg_buf[0]) + ereport(emode_for_corrupt_record(emode, reader->EndRecPtr), + (errmsg_internal("%s", reader->errormsg_buf))); /* reset any error XLogReaderValidatePageHeader() might have set */ - XLogReaderResetError(xlogreader); + XLogReaderResetError(reader); goto next_record_is_invalid; } @@ -3538,7 +3655,7 @@ next_record_is_invalid: * If we're reading ahead, give up fast. Retries and error reporting will * be handled by a later read when recovery catches up to this point. */ - if (xlogreader->nonblocking) + if (reader->nonblocking) return XLREAD_WOULDBLOCK; lastSourceFailed = true; @@ -4116,7 +4233,7 @@ emode_for_corrupt_record(int emode, XLogRecPtr RecPtr) * Subroutine to try to fetch and validate a prior checkpoint record. */ static XLogRecord * -ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, +ReadCheckpointRecord(XLogPrefetcher *prefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI) { XLogRecord *record; @@ -4131,8 +4248,8 @@ ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, return NULL; } - XLogPrefetcherBeginRead(xlogprefetcher, RecPtr); - record = ReadRecord(xlogprefetcher, LOG, true, replayTLI); + XLogPrefetcherBeginRead(prefetcher, RecPtr); + record = ReadRecord(prefetcher, LOG, true, replayTLI); if (record == NULL) { -- 2.50.1 (Apple Git-155)