From ec96c1ce86a1c9b43ca273fe62d4f88569d8d74e Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Wed, 11 Jun 2025 19:43:59 +0200 Subject: [PATCH] XLog: Expose WAL replay progress test This allows extension code to check how far REDO has come, and potentially wait or change control flow based on REDO progress. --- src/backend/access/transam/xlogrecovery.c | 41 ++++++++++++++++------- src/include/access/xlogrecovery.h | 1 + 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index 5abe1eb9afd..4b41ab6986a 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -491,35 +491,50 @@ EnableStandbyMode(void) disable_startup_progress_timeout(); } +static XLogRecPtr replayRecPtr = InvalidXLogRecPtr; + /* - * Wait for recovery to complete replaying all WAL up to and including - * redoEndRecPtr. + * Check if a record at given LSN has been replayed yet. * - * This gets woken up for every WAL record replayed, so make sure you're not - * trying to wait an LSN that is too far in the future. + * Always returns TRUE when not in recovery mode. */ -void -XLogWaitForReplayOf(XLogRecPtr redoEndRecPtr) +bool +XLogRecordReplayFinished(XLogRecPtr redoEndRecPtr) { - static XLogRecPtr replayRecPtr = 0; - if (!RecoveryInProgress()) - return; + return true; /* * Check the backend-local variable first, we may be able to skip accessing * shared memory (which requires locking) */ if (redoEndRecPtr <= replayRecPtr) - return; + return true; + /* update the backend-local cache with more up-to-date values */ replayRecPtr = GetXLogReplayRecPtr(NULL); + return redoEndRecPtr <= replayRecPtr; +} + +/* + * Wait for recovery to complete replaying all WAL up to and including + * redoEndRecPtr. + * + * This gets woken up for every WAL record replayed, so make sure you're not + * trying to wait an LSN that is too far in the future. + */ +void +XLogWaitForReplayOf(XLogRecPtr redoEndRecPtr) +{ /* - * Check again if we're going to need to wait, now that we've updated - * the local cached variable. + * Check if the record has been replayed yet. This includes up-to-date + * information about current replay state - if it hasn't been replayed, + * we're probably going to have to wait. + * + * This also returns if we're not in recovery mode. */ - if (redoEndRecPtr <= replayRecPtr) + if (XLogRecordReplayFinished(redoEndRecPtr)) return; /* diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h index d1e2ba9b670..aefc30cf83a 100644 --- a/src/include/access/xlogrecovery.h +++ b/src/include/access/xlogrecovery.h @@ -137,6 +137,7 @@ extern void ShutdownWalRecovery(void); extern void RemovePromoteSignalFiles(void); extern bool HotStandbyActive(void); +extern bool XLogRecordReplayFinished(XLogRecPtr redoEndRecPtr); extern void XLogWaitForReplayOf(XLogRecPtr redoEndRecPtr); extern XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI); extern RecoveryPauseState GetRecoveryPauseState(void);