From fe498c31c2163a69728ad749e365112c65739fe1 Mon Sep 17 00:00:00 2001 From: Shveta Malik Date: Wed, 20 Dec 2023 10:54:53 +0530 Subject: [PATCH v2] Function to get invalidation cause of a replication slot. This patch implements a new system function pg_get_slot_invalidation_cause('slot_name') to get invalidation cause of a replication slot. This function returns 0 if the replication slot is not invalidated; else returns invalidation cause. Possible invalidation causes are: 1 = required WAL has been removed. 2 = required rows have been removed. 3 = wal_level insufficient on the primary server --- doc/src/sgml/func.sgml | 32 +++++++++++++++++++++++ src/backend/replication/slotfuncs.c | 27 +++++++++++++++++++ src/include/catalog/pg_proc.dat | 4 +++ src/test/recovery/t/019_replslot_limit.pl | 6 +++++ 4 files changed, 69 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 20da3ed033..2ec0c411ca 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -27684,6 +27684,38 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset + + + + pg_get_slot_invalidation_cause + + pg_get_slot_invalidation_cause ( slot_name name ) + integer + + + Returns invalidation cause of the replication slot named + slot_name. Returns 0 if the given replication + slot is not invalidated. Possible invalidation causes are: + + + + 1 = required WAL has been removed. + + + + + 2 = required rows have been removed. + + + + + 3 = wal_level insufficient on the primary server + + + + + + diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index 4b694a03d0..3ac6c45170 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -225,6 +225,33 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * SQL function for getting invalidation cause of a slot. + * + * Returns ReplicationSlotInvalidationCause enum value for valid slot_name; + * Returns RS_INVAL_NONE if the given slot is not invalidated. + */ +Datum +pg_get_slot_invalidation_cause(PG_FUNCTION_ARGS) +{ + Name name = PG_GETARG_NAME(0); + ReplicationSlot *s; + ReplicationSlotInvalidationCause cause; + + s = SearchNamedReplicationSlot(NameStr(*name), true); + if (s == NULL) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("replication slot \"%s\" does not exist", + NameStr(*name)))); + + SpinLockAcquire(&s->mutex); + cause = s->data.invalidated; + SpinLockRelease(&s->mutex); + + PG_RETURN_INT16(cause); +} + /* * pg_get_replication_slots - SQL SRF showing all replication slots * that currently exist on the database cluster. diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 77e8b13764..ce001dacb9 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -11095,6 +11095,10 @@ proname => 'pg_drop_replication_slot', provolatile => 'v', proparallel => 'u', prorettype => 'void', proargtypes => 'name', prosrc => 'pg_drop_replication_slot' }, +{ oid => '8484', descr => 'what caused the replication slot to become invalid', + proname => 'pg_get_slot_invalidation_cause', provolatile => 's', proisstrict => 't', + prorettype => 'int2', proargtypes => 'name', + prosrc => 'pg_get_slot_invalidation_cause' }, { oid => '3781', descr => 'information about replication slots currently in use', proname => 'pg_get_replication_slots', prorows => '10', proisstrict => 'f', diff --git a/src/test/recovery/t/019_replslot_limit.pl b/src/test/recovery/t/019_replslot_limit.pl index 7d94f15778..61ac19e974 100644 --- a/src/test/recovery/t/019_replslot_limit.pl +++ b/src/test/recovery/t/019_replslot_limit.pl @@ -201,6 +201,12 @@ $result = $node_primary->safe_psql( is($result, "rep1|f|t|lost|", 'check that the slot became inactive and the state "lost" persists'); +$result = $node_primary->safe_psql( + 'postgres', + qq[SELECT pg_get_slot_invalidation_cause('rep1')]); +is($result, "1", + 'check that the invalidation cause of the slot is obtained correctly'); + # Wait until current checkpoint ends my $checkpoint_ended = 0; for (my $i = 0; $i < 10 * $PostgreSQL::Test::Utils::timeout_default; $i++) -- 2.34.1