diff options
author | Alexander Korotkov <akorotkov@postgresql.org> | 2024-09-19 14:26:03 +0300 |
---|---|---|
committer | Alexander Korotkov <akorotkov@postgresql.org> | 2024-09-19 14:26:11 +0300 |
commit | 014f9f34d2527c14cdf4150863c053d2a117c1c7 (patch) | |
tree | 561d4bbfa88dd5cb422faac97ba131415851cc48 /src/backend/access/transam/xlogfuncs.c | |
parent | 87eeadaea1439693f6108ff599d750842ca6f338 (diff) | |
download | postgresql-014f9f34d2527c14cdf4150863c053d2a117c1c7.tar.gz postgresql-014f9f34d2527c14cdf4150863c053d2a117c1c7.zip |
Move pg_wal_replay_wait() to xlogfuncs.c
This commit moves pg_wal_replay_wait() procedure to be a neighbor of
WAL-related functions in xlogfuncs.c. The implementation of LSN waiting
continues to reside in the same place.
By proposal from Michael Paquier.
Reported-by: Peter Eisentraut
Discussion: https://postgr.es/m/18c0fa64-0475-415e-a1bd-665d922c5201%40eisentraut.org
Diffstat (limited to 'src/backend/access/transam/xlogfuncs.c')
-rw-r--r-- | src/backend/access/transam/xlogfuncs.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index 4e46baaebdf..3e3d2bb6189 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -23,15 +23,18 @@ #include "access/xlogbackup.h" #include "access/xlogrecovery.h" #include "catalog/pg_type.h" +#include "commands/waitlsn.h" #include "funcapi.h" #include "miscadmin.h" #include "pgstat.h" #include "replication/walreceiver.h" #include "storage/fd.h" +#include "storage/proc.h" #include "storage/standby.h" #include "utils/builtins.h" #include "utils/memutils.h" #include "utils/pg_lsn.h" +#include "utils/snapmgr.h" #include "utils/timestamp.h" /* @@ -747,3 +750,56 @@ pg_promote(PG_FUNCTION_ARGS) wait_seconds))); PG_RETURN_BOOL(false); } + +/* + * Waits until recovery replays the target LSN with optional timeout. + */ +Datum +pg_wal_replay_wait(PG_FUNCTION_ARGS) +{ + XLogRecPtr target_lsn = PG_GETARG_LSN(0); + int64 timeout = PG_GETARG_INT64(1); + + if (timeout < 0) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("\"timeout\" must not be negative"))); + + /* + * We are going to wait for the LSN replay. We should first care that we + * don't hold a snapshot and correspondingly our MyProc->xmin is invalid. + * Otherwise, our snapshot could prevent the replay of WAL records + * implying a kind of self-deadlock. This is the reason why + * pg_wal_replay_wait() is a procedure, not a function. + * + * At first, we should check there is no active snapshot. According to + * PlannedStmtRequiresSnapshot(), even in an atomic context, CallStmt is + * processed with a snapshot. Thankfully, we can pop this snapshot, + * because PortalRunUtility() can tolerate this. + */ + if (ActiveSnapshotSet()) + PopActiveSnapshot(); + + /* + * At second, invalidate a catalog snapshot if any. And we should be done + * with the preparation. + */ + InvalidateCatalogSnapshot(); + + /* Give up if there is still an active or registered snapshot. */ + if (GetOldestSnapshot()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("pg_wal_replay_wait() must be only called without an active or registered snapshot"), + errdetail("Make sure pg_wal_replay_wait() isn't called within a transaction with an isolation level higher than READ COMMITTED, another procedure, or a function."))); + + /* + * As the result we should hold no snapshot, and correspondingly our xmin + * should be unset. + */ + Assert(MyProc->xmin == InvalidTransactionId); + + (void) WaitForLSNReplay(target_lsn, timeout); + + PG_RETURN_VOID(); +} |