From 5abe0ba43ca079a0af5905ed617795e885be81c9 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathandbossart@gmail.com>
Date: Fri, 27 Jan 2023 22:19:57 -0800
Subject: [PATCH 4/4] add private state to archive modules

---
 contrib/basic_archive/basic_archive.c   | 27 ++++++++++++-------------
 src/backend/postmaster/pgarch.c         |  9 +++++----
 src/backend/postmaster/shell_archive.c  | 14 ++++++-------
 src/include/postmaster/archive_module.h | 12 +++++------
 4 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/contrib/basic_archive/basic_archive.c b/contrib/basic_archive/basic_archive.c
index 1655f72b5b..fefa79debc 100644
--- a/contrib/basic_archive/basic_archive.c
+++ b/contrib/basic_archive/basic_archive.c
@@ -41,10 +41,9 @@
 PG_MODULE_MAGIC;
 
 static char *archive_directory = NULL;
-static MemoryContext basic_archive_context;
 
-static bool basic_archive_configured(void);
-static bool basic_archive_file(const char *file, const char *path);
+static bool basic_archive_configured(void *arg);
+static bool basic_archive_file(const char *file, const char *path, void *arg);
 static void basic_archive_file_internal(const char *file, const char *path);
 static bool check_archive_directory(char **newval, void **extra, GucSource source);
 static bool compare_files(const char *file1, const char *file2);
@@ -73,22 +72,22 @@ _PG_init(void)
 							   check_archive_directory, NULL, NULL);
 
 	MarkGUCPrefixReserved("basic_archive");
-
-	basic_archive_context = AllocSetContextCreate(TopMemoryContext,
-												  "basic_archive",
-												  ALLOCSET_DEFAULT_SIZES);
 }
 
 /*
  * _PG_archive_module_init
  *
- * Returns the module's archiving callbacks.
+ * Returns the module's archiving callbacks and initializes private state.
  */
 const ArchiveModuleCallbacks *
-_PG_archive_module_init(void)
+_PG_archive_module_init(void **arg)
 {
 	AssertVariableIsOfType(&_PG_archive_module_init, ArchiveModuleInit);
 
+	(*arg) = (void *) AllocSetContextCreate(TopMemoryContext,
+											"basic_archive",
+											ALLOCSET_DEFAULT_SIZES);
+
 	return &basic_archive_callbacks;
 }
 
@@ -140,7 +139,7 @@ check_archive_directory(char **newval, void **extra, GucSource source)
  * Checks that archive_directory is not blank.
  */
 static bool
-basic_archive_configured(void)
+basic_archive_configured(void *arg)
 {
 	return archive_directory != NULL && archive_directory[0] != '\0';
 }
@@ -151,7 +150,7 @@ basic_archive_configured(void)
  * Archives one file.
  */
 static bool
-basic_archive_file(const char *file, const char *path)
+basic_archive_file(const char *file, const char *path, void *arg)
 {
 	sigjmp_buf	local_sigjmp_buf;
 	MemoryContext oldcontext;
@@ -161,7 +160,7 @@ basic_archive_file(const char *file, const char *path)
 	 * we can easily reset it during error recovery (thus avoiding memory
 	 * leaks).
 	 */
-	oldcontext = MemoryContextSwitchTo(basic_archive_context);
+	oldcontext = MemoryContextSwitchTo((MemoryContext) arg);
 
 	/*
 	 * Since the archiver operates at the bottom of the exception stack,
@@ -188,7 +187,7 @@ basic_archive_file(const char *file, const char *path)
 
 		/* Reset our memory context and switch back to the original one */
 		MemoryContextSwitchTo(oldcontext);
-		MemoryContextReset(basic_archive_context);
+		MemoryContextReset((MemoryContext) arg);
 
 		/* Remove our exception handler */
 		PG_exception_stack = NULL;
@@ -211,7 +210,7 @@ basic_archive_file(const char *file, const char *path)
 
 	/* Reset our memory context and switch back to the original one */
 	MemoryContextSwitchTo(oldcontext);
-	MemoryContextReset(basic_archive_context);
+	MemoryContextReset((MemoryContext) arg);
 
 	return true;
 }
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 627c579f0e..939b5beb00 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -99,6 +99,7 @@ char	   *XLogArchiveLibrary = "";
 static time_t last_sigterm_time = 0;
 static PgArchData *PgArch = NULL;
 static const ArchiveModuleCallbacks *ArchiveCallbacks;
+static void *arch_module_private = NULL;
 
 
 /*
@@ -418,7 +419,7 @@ pgarch_ArchiverCopyLoop(void)
 
 			/* can't do anything if not configured ... */
 			if (ArchiveCallbacks->check_configured_cb != NULL &&
-				!ArchiveCallbacks->check_configured_cb())
+				!ArchiveCallbacks->check_configured_cb(arch_module_private))
 			{
 				ereport(WARNING,
 						(errmsg("archive_mode enabled, yet archiving is not configured")));
@@ -519,7 +520,7 @@ pgarch_archiveXlog(char *xlog)
 	snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
 	set_ps_display(activitymsg);
 
-	ret = ArchiveCallbacks->archive_file_cb(xlog, pathname);
+	ret = ArchiveCallbacks->archive_file_cb(xlog, pathname, arch_module_private);
 	if (ret)
 		snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
 	else
@@ -853,7 +854,7 @@ LoadArchiveLibrary(void)
 		ereport(ERROR,
 				(errmsg("archive modules have to define the symbol %s", "_PG_archive_module_init")));
 
-	ArchiveCallbacks = (*archive_init) ();
+	ArchiveCallbacks = (*archive_init) (&arch_module_private);
 
 	if (ArchiveCallbacks->archive_file_cb == NULL)
 		ereport(ERROR,
@@ -869,5 +870,5 @@ static void
 pgarch_call_module_shutdown_cb(int code, Datum arg)
 {
 	if (ArchiveCallbacks->shutdown_cb != NULL)
-		ArchiveCallbacks->shutdown_cb();
+		ArchiveCallbacks->shutdown_cb(arch_module_private);
 }
diff --git a/src/backend/postmaster/shell_archive.c b/src/backend/postmaster/shell_archive.c
index dde20c83de..31ceca67a3 100644
--- a/src/backend/postmaster/shell_archive.c
+++ b/src/backend/postmaster/shell_archive.c
@@ -22,9 +22,9 @@
 #include "pgstat.h"
 #include "postmaster/archive_module.h"
 
-static bool shell_archive_configured(void);
-static bool shell_archive_file(const char *file, const char *path);
-static void shell_archive_shutdown(void);
+static bool shell_archive_configured(void *arg);
+static bool shell_archive_file(const char *file, const char *path, void *arg);
+static void shell_archive_shutdown(void *arg);
 
 static const ArchiveModuleCallbacks shell_archive_callbacks = {
 	.check_configured_cb = shell_archive_configured,
@@ -33,7 +33,7 @@ static const ArchiveModuleCallbacks shell_archive_callbacks = {
 };
 
 const ArchiveModuleCallbacks *
-shell_archive_init(void)
+shell_archive_init(void **arg)
 {
 	AssertVariableIsOfType(&shell_archive_init, ArchiveModuleInit);
 
@@ -41,13 +41,13 @@ shell_archive_init(void)
 }
 
 static bool
-shell_archive_configured(void)
+shell_archive_configured(void *arg)
 {
 	return XLogArchiveCommand[0] != '\0';
 }
 
 static bool
-shell_archive_file(const char *file, const char *path)
+shell_archive_file(const char *file, const char *path, void *arg)
 {
 	char	   *xlogarchcmd;
 	char	   *nativePath = NULL;
@@ -129,7 +129,7 @@ shell_archive_file(const char *file, const char *path)
 }
 
 static void
-shell_archive_shutdown(void)
+shell_archive_shutdown(void *arg)
 {
 	elog(DEBUG1, "archiver process shutting down");
 }
diff --git a/src/include/postmaster/archive_module.h b/src/include/postmaster/archive_module.h
index 67b5624874..fb4ef8730e 100644
--- a/src/include/postmaster/archive_module.h
+++ b/src/include/postmaster/archive_module.h
@@ -25,24 +25,24 @@ extern PGDLLIMPORT char *XLogArchiveLibrary;
  */
 typedef struct ArchiveModuleCallbacks
 {
-	bool (*check_configured_cb) (void);
-	bool (*archive_file_cb) (const char *file, const char *path);
-	void (*shutdown_cb) (void);
+	bool (*check_configured_cb) (void *arg);
+	bool (*archive_file_cb) (const char *file, const char *path, void *arg);
+	void (*shutdown_cb) (void *arg);
 } ArchiveModuleCallbacks;
 
 /*
  * Type of the shared library symbol _PG_archive_module_init that is looked
  * up when loading an archive library.
  */
-typedef const ArchiveModuleCallbacks *(*ArchiveModuleInit) (void);
+typedef const ArchiveModuleCallbacks *(*ArchiveModuleInit) (void **arg);
 
-extern PGDLLEXPORT const ArchiveModuleCallbacks *_PG_archive_module_init(void);
+extern PGDLLEXPORT const ArchiveModuleCallbacks *_PG_archive_module_init(void **arg);
 
 /*
  * Since the logic for archiving via a shell command is in the core server
  * and does not need to be loaded via a shared library, it has a special
  * initialization function.
  */
-extern const ArchiveModuleCallbacks *shell_archive_init(void);
+extern const ArchiveModuleCallbacks *shell_archive_init(void **arg);
 
 #endif							/* _ARCHIVE_MODULE_H */
-- 
2.25.1

