Add lookup table for replication slot conflict reasons
authorMichael Paquier <[email protected]>
Wed, 21 Feb 2024 23:40:40 +0000 (08:40 +0900)
committerMichael Paquier <[email protected]>
Wed, 21 Feb 2024 23:40:40 +0000 (08:40 +0900)
This commit switches the handling of the conflict cause strings for
replication slots to use a table rather than being explicitly listed,
using a C99-designated initializer syntax for the array elements.  This
makes the whole more readable while easing future maintenance with less
areas to update when adding a new conflict reason.

This is similar to 74a730631065, but the scale of the change is smaller
as there are less conflict causes than LWLock builtin tranche names.

Author: Bharath Rupireddy
Reviewed-by: Jelte Fennema-Nio
Discussion: https://postgr.es/m/CALj2ACUxSLA91QGFrJsWNKs58KXb1C03mbuwKmzqqmoAKLwJaw@mail.gmail.com

src/backend/replication/slot.c
src/backend/replication/slotfuncs.c
src/include/replication/slot.h

index a142855bd32249418ad2e91b4fec5fba6aa0461f..233652b479928579cc3b4b947fd2111d26c42a70 100644 (file)
@@ -77,6 +77,22 @@ typedef struct ReplicationSlotOnDisk
    ReplicationSlotPersistentData slotdata;
 } ReplicationSlotOnDisk;
 
+/*
+ * Lookup table for slot invalidation causes.
+ */
+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",
+};
+
+/* Maximum number of invalidation causes */
+#define    RS_INVAL_MAX_CAUSES RS_INVAL_WAL_LEVEL
+
+StaticAssertDecl(lengthof(SlotInvalidationCauses) == (RS_INVAL_MAX_CAUSES + 1),
+                "array length mismatch");
+
 /* size of version independent data */
 #define ReplicationSlotOnDiskConstantSize \
    offsetof(ReplicationSlotOnDisk, slotdata)
@@ -2290,23 +2306,26 @@ RestoreSlotFromDisk(const char *name)
 }
 
 /*
- * Maps the pg_replication_slots.conflict_reason text value to
- * ReplicationSlotInvalidationCause enum value
+ * Maps a conflict reason for a replication slot to
+ * ReplicationSlotInvalidationCause.
  */
 ReplicationSlotInvalidationCause
-GetSlotInvalidationCause(char *conflict_reason)
+GetSlotInvalidationCause(const char *conflict_reason)
 {
+   ReplicationSlotInvalidationCause cause;
+   bool        found PG_USED_FOR_ASSERTS_ONLY = false;
+
    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);
+   for (cause = RS_INVAL_NONE; cause <= RS_INVAL_MAX_CAUSES; cause++)
+   {
+       if (strcmp(SlotInvalidationCauses[cause], conflict_reason) == 0)
+       {
+           found = true;
+           break;
+       }
+   }
 
-   /* Keep compiler quiet */
-   return RS_INVAL_NONE;
+   Assert(found);
+   return cause;
 }
index d2fa5e669a32f19989b0d987d3c7329851a1272e..c108bf9608f7a397abc81016c2303c6bb782e0af 100644 (file)
@@ -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);
index e706ca834c092567d8ee8e1da50fb717152d78ea..acbf567150e6e478e3ed52dc0a1adcd8c6f5fbd4 100644 (file)
@@ -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.
+ *
+ * When adding a new invalidation cause here, remember to update
+ * SlotInvalidationCauses and RS_INVAL_MAX_CAUSES.
  */
 typedef enum ReplicationSlotInvalidationCause
 {
@@ -52,13 +55,7 @@ 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"
+extern PGDLLIMPORT const char *const SlotInvalidationCauses[];
 
 /*
  * On-Disk data of a replication slot, preserved across restarts.
@@ -275,6 +272,6 @@ extern void CheckPointReplicationSlots(bool is_shutdown);
 extern void CheckSlotRequirements(void);
 extern void CheckSlotPermissions(void);
 extern ReplicationSlotInvalidationCause
-           GetSlotInvalidationCause(char *conflict_reason);
+           GetSlotInvalidationCause(const char *conflict_reason);
 
 #endif                         /* SLOT_H */