v2-0001-Avoid-duplicate-registration-of-callbacks-in-pgou.patch

application/octet-stream

Filename: v2-0001-Avoid-duplicate-registration-of-callbacks-in-pgou.patch
Type: application/octet-stream
Part: 0
Message: RE: "out of relcache_callback_list slots" after multiple calls to pg_logical_slot_get_binary_changes

Patch

Format: format-patch
Series: patch v2-0001
Subject: Avoid duplicate registration of callbacks in pgoutput
File+
src/backend/replication/pgoutput/pgoutput.c 35 23
From e72ce3656c043e0c1d99373833da04f508429691 Mon Sep 17 00:00:00 2001
From: Shi Yu <shiy.fnst@fujitsu.com>
Date: Tue, 21 Feb 2023 10:55:46 +0800
Subject: [PATCH v2] Avoid duplicate registration of callbacks in pgoutput

---
 src/backend/replication/pgoutput/pgoutput.c | 58 +++++++++++++--------
 1 file changed, 35 insertions(+), 23 deletions(-)

diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 98377c094b..20c740f7fb 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -82,6 +82,7 @@ static void pgoutput_stream_prepare_txn(LogicalDecodingContext *ctx,
 static bool publications_valid;
 static bool in_streaming;
 static bool publish_no_origin;
+static bool callback_registered = false;
 
 static List *LoadPublications(List *pubnames);
 static void publication_invalidation_cb(Datum arg, int cacheid,
@@ -504,12 +505,15 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 		/* Init publication state. */
 		data->publications = NIL;
 		publications_valid = false;
-		CacheRegisterSyscacheCallback(PUBLICATIONOID,
-									  publication_invalidation_cb,
-									  (Datum) 0);
+		/* Register callbacks if we didn't do that. */
+		if (!callback_registered)
+			CacheRegisterSyscacheCallback(PUBLICATIONOID,
+										  publication_invalidation_cb,
+										  (Datum) 0);
 
 		/* Initialize relation schema cache. */
 		init_rel_sync_cache(CacheMemoryContext);
+		callback_registered = true;
 	}
 	else
 	{
@@ -1946,28 +1950,36 @@ init_rel_sync_cache(MemoryContext cachectx)
 
 	Assert(RelationSyncCache != NULL);
 
-	/* We must update the cache entry for a relation after a relcache flush */
-	CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, (Datum) 0);
 
-	/*
-	 * Flush all cache entries after a pg_namespace change, in case it was a
-	 * schema rename affecting a relation being replicated.
-	 */
-	CacheRegisterSyscacheCallback(NAMESPACEOID,
-								  rel_sync_cache_publication_cb,
-								  (Datum) 0);
+	/* Register callbacks if we didn't do that. */
+	if (!callback_registered)
+	{
+		/*
+		 * We must update the cache entry for a relation after a relcache
+		 * flush
+		 */
+		CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, (Datum) 0);
 
-	/*
-	 * Flush all cache entries after any publication changes.  (We need no
-	 * callback entry for pg_publication, because publication_invalidation_cb
-	 * will take care of it.)
-	 */
-	CacheRegisterSyscacheCallback(PUBLICATIONRELMAP,
-								  rel_sync_cache_publication_cb,
-								  (Datum) 0);
-	CacheRegisterSyscacheCallback(PUBLICATIONNAMESPACEMAP,
-								  rel_sync_cache_publication_cb,
-								  (Datum) 0);
+		/*
+		 * Flush all cache entries after a pg_namespace change, in case it was
+		 * a schema rename affecting a relation being replicated.
+		 */
+		CacheRegisterSyscacheCallback(NAMESPACEOID,
+									  rel_sync_cache_publication_cb,
+									  (Datum) 0);
+
+		/*
+		 * Flush all cache entries after any publication changes.  (We need no
+		 * callback entry for pg_publication, because
+		 * publication_invalidation_cb will take care of it.)
+		 */
+		CacheRegisterSyscacheCallback(PUBLICATIONRELMAP,
+									  rel_sync_cache_publication_cb,
+									  (Datum) 0);
+		CacheRegisterSyscacheCallback(PUBLICATIONNAMESPACEMAP,
+									  rel_sync_cache_publication_cb,
+									  (Datum) 0);
+	}
 }
 
 /*
-- 
2.31.1