0001-Cache-standby-slot-index.patch.txt

text/plain

Filename: 0001-Cache-standby-slot-index.patch.txt
Type: text/plain
Part: 0
Message: RE: Synchronizing slots from primary to standby
From 3b24e04a225eb3bc82950432727662bdcb41f511 Mon Sep 17 00:00:00 2001
From: Hou Zhijie <houzj.fnst@cn.fujitsu.com>
Date: Fri, 8 Mar 2024 09:09:26 +0800
Subject: [PATCH] Cache standby slot index

---
 src/backend/replication/slot.c | 47 ++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 30db34ece8..8736d9a87b 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -93,10 +93,17 @@ typedef struct
 	/* Number of slot names in the slot_names[] */
 	int			nslotnames;
 
+	/* The offset of the slot index array */
+	int			slot_index_offset;
+
 	/*
 	 * slot_names contains 'nslotnames' consecutive null-terminated C strings.
 	 */
 	char		slot_names[FLEXIBLE_ARRAY_MEMBER];
+
+	/*
+	 * After all the C strings, there is a size 'nslotnames' slot index array.
+	 */
 } StandbySlotNamesConfigData;
 
 /*
@@ -156,6 +163,14 @@ static StandbySlotNamesConfigData *standby_slot_names_config;
  */
 static XLogRecPtr ss_oldest_flush_lsn = InvalidXLogRecPtr;
 
+/*
+ * This array caches the position of each standby slot in
+ * ReplicationSlotCtl->replication_slots. The position will be updated if it
+ * becomes outdated due to a slot drop. See StandbySlotsHaveCaughtup for
+ * details.
+ */
+static int *standby_slot_index = NULL;
+
 static void ReplicationSlotShmemExit(int code, Datum arg);
 static void ReplicationSlotDropPtr(ReplicationSlot *slot);
 
@@ -2453,6 +2468,7 @@ check_standby_slot_names(char **newval, void **extra, GucSource source)
 	char	   *ptr;
 	List	   *elemlist;
 	int			size;
+	int			index_offset;
 	bool		ok;
 	StandbySlotNamesConfigData *config;
 
@@ -2477,11 +2493,15 @@ check_standby_slot_names(char **newval, void **extra, GucSource source)
 	foreach_ptr(char, slot_name, elemlist)
 		size += strlen(slot_name) + 1;
 
+	index_offset = size;
+	size += list_length(elemlist) * sizeof(int);
+
 	/* GUC extra value must be guc_malloc'd, not palloc'd */
 	config = (StandbySlotNamesConfigData *) guc_malloc(LOG, size);
 
 	/* Transform the data into StandbySlotNamesConfigData */
 	config->nslotnames = list_length(elemlist);
+	config->slot_index_offset = index_offset;
 
 	ptr = config->slot_names;
 	foreach_ptr(char, slot_name, elemlist)
@@ -2490,6 +2510,9 @@ check_standby_slot_names(char **newval, void **extra, GucSource source)
 		ptr += strlen(slot_name) + 1;
 	}
 
+	/* Initialize the index array */
+	memset(ptr, -1, list_length(elemlist) * sizeof(int));
+
 	*extra = (void *) config;
 
 	pfree(rawname);
@@ -2510,6 +2533,12 @@ assign_standby_slot_names(const char *newval, void *extra)
 	ss_oldest_flush_lsn = InvalidXLogRecPtr;
 
 	standby_slot_names_config = (StandbySlotNamesConfigData *) extra;
+
+	if (extra)
+	{
+		char *ptr = (char *) extra + standby_slot_names_config->slot_index_offset;
+		standby_slot_index = (int *) ptr;
+	}
 }
 
 /*
@@ -2590,9 +2619,21 @@ StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel)
 		XLogRecPtr	restart_lsn;
 		bool		invalidated;
 		bool		inactive;
-		ReplicationSlot *slot;
+		ReplicationSlot *slot = NULL;
+		int			slot_index = standby_slot_index[i];
 
-		slot = SearchNamedReplicationSlot(name, false);
+		/* Get the replication slot using the standby slot index */
+		if (slot_index >= 0)
+			slot = &ReplicationSlotCtl->replication_slots[slot_index];
+
+		/*
+		 * If the slot index has not been initialized, or if the slot found by
+		 * the index does not match, which means the original slot was dropped,
+		 * then we search for the named slot among all replication slots and
+		 * update the index if the slot is found.
+		 */
+		if (!slot || !slot->in_use || strcmp(name, NameStr(slot->data.name)) != 0)
+			slot = SearchNamedReplicationSlot(name, false);
 
 		if (!slot)
 		{
@@ -2616,6 +2657,8 @@ StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel)
 			break;
 		}
 
+		standby_slot_index[i] = ReplicationSlotIndex(slot);
+
 		if (SlotIsLogical(slot))
 		{
 			/*
-- 
2.30.0.windows.2