summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Freund2023-04-08 05:19:05 +0000
committerAndres Freund2023-04-08 05:19:05 +0000
commit4397abd0a2af955326c0608d63f3716ce5901004 (patch)
treeed9a7a022b746da014567065db69e66e8a88edae
parent15f8203a5975d6b9b78e2c64e213ed964b50c044 (diff)
Prevent use of invalidated logical slot in CreateDecodingContext()
Previously we had checks for this in multiple places. Support for logical decoding on standbys will add other forms of invalidation, making it worth while to centralize the checks. This slightly changes the error message for both the walsender and SQL interface. Particularly the SQL interface error was inaccurate, as the "This slot has never previously reserved WAL" portion was unreachable. Reviewed-by: "Drouvot, Bertrand" <[email protected]> Reviewed-by: Melanie Plageman <[email protected]> Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/replication/logical/logical.c16
-rw-r--r--src/backend/replication/logical/logicalfuncs.c13
-rw-r--r--src/backend/replication/walsender.c7
3 files changed, 16 insertions, 20 deletions
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index c3ec97a0a6..6082d222d5 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -518,6 +518,22 @@ CreateDecodingContext(XLogRecPtr start_lsn,
errmsg("replication slot \"%s\" was not created in this database",
NameStr(slot->data.name))));
+ /*
+ * Check if slot has been invalidated due to max_slot_wal_keep_size. Avoid
+ * "cannot get changes" wording in this errmsg because that'd be
+ * confusingly ambiguous about no changes being available when called from
+ * pg_logical_slot_get_changes_guts().
+ */
+ if (MyReplicationSlot->data.invalidated == RS_INVAL_WAL_REMOVED)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("can no longer get changes from replication slot \"%s\"",
+ NameStr(MyReplicationSlot->data.name)),
+ errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
+
+ Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
+ Assert(MyReplicationSlot->data.restart_lsn != InvalidXLogRecPtr);
+
if (start_lsn == InvalidXLogRecPtr)
{
/* continue from last position */
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index fa1b641a2b..55a24c02c9 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -214,19 +214,6 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
LogicalOutputPrepareWrite,
LogicalOutputWrite, NULL);
- /*
- * After the sanity checks in CreateDecodingContext, make sure the
- * restart_lsn is valid. Avoid "cannot get changes" wording in this
- * errmsg because that'd be confusingly ambiguous about no changes
- * being available.
- */
- if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("can no longer get changes from replication slot \"%s\"",
- NameStr(*name)),
- errdetail("This slot has never previously reserved WAL, or it has been invalidated.")));
-
MemoryContextSwitchTo(oldcontext);
/*
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 75e8363e24..e40a9b1ba7 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1253,13 +1253,6 @@ StartLogicalReplication(StartReplicationCmd *cmd)
ReplicationSlotAcquire(cmd->slotname, true);
- if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("cannot read from logical replication slot \"%s\"",
- cmd->slotname),
- errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
-
/*
* Force a disconnect, so that the decoding code doesn't need to care
* about an eventual switch from running in recovery, to running in a