From 8ce4d69f631953e7bf3cd45044156bae758602a2 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Wed, 21 Feb 2024 04:15:02 +0000 Subject: [PATCH v2] Add lookup table for replication slot invalidation causes --- src/backend/replication/slot.c | 45 +++++++++++++++++++---------- src/backend/replication/slotfuncs.c | 24 ++++----------- src/include/replication/slot.h | 16 +++++----- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index a142855bd3..82ad425ef4 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -77,6 +77,19 @@ typedef struct ReplicationSlotOnDisk ReplicationSlotPersistentData slotdata; } ReplicationSlotOnDisk; +/* + * Lookup table for invalidation cause names indexed by RS_INVAL_XXX. + */ +const char *const SlotInvalidationCauses[] = { + [RS_INVAL_NONE] = "none", + [RS_INVAL_WAL_REMOVED] = "wal_removed", + [RS_INVAL_HORIZON] = "rows_removed", + [RS_INVAL_WAL_LEVEL] = "wal_level_insufficient", +}; + +StaticAssertDecl(lengthof(SlotInvalidationCauses) == (RS_INVAL_MAX_CAUSES + 1), + "array length mismatch"); + /* size of version independent data */ #define ReplicationSlotOnDiskConstantSize \ offsetof(ReplicationSlotOnDisk, slotdata) @@ -2290,23 +2303,25 @@ RestoreSlotFromDisk(const char *name) } /* - * Maps the pg_replication_slots.conflict_reason text value to - * ReplicationSlotInvalidationCause enum value + * Look up invalidation cause by name. */ ReplicationSlotInvalidationCause -GetSlotInvalidationCause(char *conflict_reason) +GetSlotInvalidationCause(char *name) { - Assert(conflict_reason); - - if (strcmp(conflict_reason, SLOT_INVAL_WAL_REMOVED_TEXT) == 0) - return RS_INVAL_WAL_REMOVED; - else if (strcmp(conflict_reason, SLOT_INVAL_HORIZON_TEXT) == 0) - return RS_INVAL_HORIZON; - else if (strcmp(conflict_reason, SLOT_INVAL_WAL_LEVEL_TEXT) == 0) - return RS_INVAL_WAL_LEVEL; - else - Assert(0); + ReplicationSlotInvalidationCause cause; + bool found PG_USED_FOR_ASSERTS_ONLY = false; + + Assert(name); + + for (cause = RS_INVAL_NONE; cause <= RS_INVAL_MAX_CAUSES; cause++) + { + if (strcmp(SlotInvalidationCauses[cause], name) == 0) + { + found = true; + break; + } + } - /* Keep compiler quiet */ - return RS_INVAL_NONE; + Assert(found); + return cause; } diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index d2fa5e669a..c108bf9608 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -413,24 +413,12 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) nulls[i++] = true; else { - switch (slot_contents.data.invalidated) - { - case RS_INVAL_NONE: - nulls[i++] = true; - break; - - case RS_INVAL_WAL_REMOVED: - values[i++] = CStringGetTextDatum(SLOT_INVAL_WAL_REMOVED_TEXT); - break; - - case RS_INVAL_HORIZON: - values[i++] = CStringGetTextDatum(SLOT_INVAL_HORIZON_TEXT); - break; - - case RS_INVAL_WAL_LEVEL: - values[i++] = CStringGetTextDatum(SLOT_INVAL_WAL_LEVEL_TEXT); - break; - } + ReplicationSlotInvalidationCause cause = slot_contents.data.invalidated; + + if (cause == RS_INVAL_NONE) + nulls[i++] = true; + else + values[i++] = CStringGetTextDatum(SlotInvalidationCauses[cause]); } values[i++] = BoolGetDatum(slot_contents.data.failover); diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h index e706ca834c..b26697ba15 100644 --- a/src/include/replication/slot.h +++ b/src/include/replication/slot.h @@ -40,6 +40,9 @@ typedef enum ReplicationSlotPersistency /* * Slots can be invalidated, e.g. due to max_slot_wal_keep_size. If so, the * 'invalidated' field is set to a value other than _NONE. + * + * If you add a new invalidation cause here, remember to add its name in + * SlotInvalidationCauses in the same order as that of the cause. */ typedef enum ReplicationSlotInvalidationCause { @@ -52,13 +55,10 @@ typedef enum ReplicationSlotInvalidationCause RS_INVAL_WAL_LEVEL, } ReplicationSlotInvalidationCause; -/* - * The possible values for 'conflict_reason' returned in - * pg_get_replication_slots. - */ -#define SLOT_INVAL_WAL_REMOVED_TEXT "wal_removed" -#define SLOT_INVAL_HORIZON_TEXT "rows_removed" -#define SLOT_INVAL_WAL_LEVEL_TEXT "wal_level_insufficient" +/* Maximum number of invalidation causes */ +#define RS_INVAL_MAX_CAUSES RS_INVAL_WAL_LEVEL + +extern PGDLLIMPORT const char *const SlotInvalidationCauses[]; /* * On-Disk data of a replication slot, preserved across restarts. @@ -275,6 +275,6 @@ extern void CheckPointReplicationSlots(bool is_shutdown); extern void CheckSlotRequirements(void); extern void CheckSlotPermissions(void); extern ReplicationSlotInvalidationCause - GetSlotInvalidationCause(char *conflict_reason); + GetSlotInvalidationCause(char *cause); #endif /* SLOT_H */ -- 2.34.1