Skip to content

Commit 014f9f3

Browse files
committed
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
1 parent 87eeada commit 014f9f3

File tree

3 files changed

+58
-51
lines changed

3 files changed

+58
-51
lines changed

src/backend/access/transam/xlogfuncs.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,18 @@
2323
#include "access/xlogbackup.h"
2424
#include "access/xlogrecovery.h"
2525
#include "catalog/pg_type.h"
26+
#include "commands/waitlsn.h"
2627
#include "funcapi.h"
2728
#include "miscadmin.h"
2829
#include "pgstat.h"
2930
#include "replication/walreceiver.h"
3031
#include "storage/fd.h"
32+
#include "storage/proc.h"
3133
#include "storage/standby.h"
3234
#include "utils/builtins.h"
3335
#include "utils/memutils.h"
3436
#include "utils/pg_lsn.h"
37+
#include "utils/snapmgr.h"
3538
#include "utils/timestamp.h"
3639

3740
/*
@@ -747,3 +750,56 @@ pg_promote(PG_FUNCTION_ARGS)
747750
wait_seconds)));
748751
PG_RETURN_BOOL(false);
749752
}
753+
754+
/*
755+
* Waits until recovery replays the target LSN with optional timeout.
756+
*/
757+
Datum
758+
pg_wal_replay_wait(PG_FUNCTION_ARGS)
759+
{
760+
XLogRecPtr target_lsn = PG_GETARG_LSN(0);
761+
int64 timeout = PG_GETARG_INT64(1);
762+
763+
if (timeout < 0)
764+
ereport(ERROR,
765+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
766+
errmsg("\"timeout\" must not be negative")));
767+
768+
/*
769+
* We are going to wait for the LSN replay. We should first care that we
770+
* don't hold a snapshot and correspondingly our MyProc->xmin is invalid.
771+
* Otherwise, our snapshot could prevent the replay of WAL records
772+
* implying a kind of self-deadlock. This is the reason why
773+
* pg_wal_replay_wait() is a procedure, not a function.
774+
*
775+
* At first, we should check there is no active snapshot. According to
776+
* PlannedStmtRequiresSnapshot(), even in an atomic context, CallStmt is
777+
* processed with a snapshot. Thankfully, we can pop this snapshot,
778+
* because PortalRunUtility() can tolerate this.
779+
*/
780+
if (ActiveSnapshotSet())
781+
PopActiveSnapshot();
782+
783+
/*
784+
* At second, invalidate a catalog snapshot if any. And we should be done
785+
* with the preparation.
786+
*/
787+
InvalidateCatalogSnapshot();
788+
789+
/* Give up if there is still an active or registered snapshot. */
790+
if (GetOldestSnapshot())
791+
ereport(ERROR,
792+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
793+
errmsg("pg_wal_replay_wait() must be only called without an active or registered snapshot"),
794+
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.")));
795+
796+
/*
797+
* As the result we should hold no snapshot, and correspondingly our xmin
798+
* should be unset.
799+
*/
800+
Assert(MyProc->xmin == InvalidTransactionId);
801+
802+
(void) WaitForLSNReplay(target_lsn, timeout);
803+
804+
PG_RETURN_VOID();
805+
}

src/backend/commands/waitlsn.c

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ WaitLSNCleanup(void)
217217
* Wait using MyLatch till the given LSN is replayed, the postmaster dies or
218218
* timeout happens.
219219
*/
220-
static void
220+
void
221221
WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
222222
{
223223
XLogRecPtr currentLSN;
@@ -336,53 +336,3 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout)
336336
LSN_FORMAT_ARGS(currentLSN))));
337337
}
338338
}
339-
340-
Datum
341-
pg_wal_replay_wait(PG_FUNCTION_ARGS)
342-
{
343-
XLogRecPtr target_lsn = PG_GETARG_LSN(0);
344-
int64 timeout = PG_GETARG_INT64(1);
345-
346-
if (timeout < 0)
347-
ereport(ERROR,
348-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
349-
errmsg("\"timeout\" must not be negative")));
350-
351-
/*
352-
* We are going to wait for the LSN replay. We should first care that we
353-
* don't hold a snapshot and correspondingly our MyProc->xmin is invalid.
354-
* Otherwise, our snapshot could prevent the replay of WAL records
355-
* implying a kind of self-deadlock. This is the reason why
356-
* pg_wal_replay_wait() is a procedure, not a function.
357-
*
358-
* At first, we should check there is no active snapshot. According to
359-
* PlannedStmtRequiresSnapshot(), even in an atomic context, CallStmt is
360-
* processed with a snapshot. Thankfully, we can pop this snapshot,
361-
* because PortalRunUtility() can tolerate this.
362-
*/
363-
if (ActiveSnapshotSet())
364-
PopActiveSnapshot();
365-
366-
/*
367-
* At second, invalidate a catalog snapshot if any. And we should be done
368-
* with the preparation.
369-
*/
370-
InvalidateCatalogSnapshot();
371-
372-
/* Give up if there is still an active or registered snapshot. */
373-
if (GetOldestSnapshot())
374-
ereport(ERROR,
375-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
376-
errmsg("pg_wal_replay_wait() must be only called without an active or registered snapshot"),
377-
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.")));
378-
379-
/*
380-
* As the result we should hold no snapshot, and correspondingly our xmin
381-
* should be unset.
382-
*/
383-
Assert(MyProc->xmin == InvalidTransactionId);
384-
385-
(void) WaitForLSNReplay(target_lsn, timeout);
386-
387-
PG_RETURN_VOID();
388-
}

src/include/commands/waitlsn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,6 @@ extern Size WaitLSNShmemSize(void);
7676
extern void WaitLSNShmemInit(void);
7777
extern void WaitLSNSetLatches(XLogRecPtr currentLSN);
7878
extern void WaitLSNCleanup(void);
79+
extern void WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout);
7980

8081
#endif /* WAIT_LSN_H */

0 commit comments

Comments
 (0)