v12-0002-Introduce-archive-modules-infrastructure.patch
application/octet-stream
Filename: v12-0002-Introduce-archive-modules-infrastructure.patch
Type: application/octet-stream
Part: 1
Message:
Re: archive modules
Patch
Format: format-patch
Series: patch v12-0002
Subject: Introduce archive modules infrastructure.
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 1 | 1 |
| src/backend/postmaster/pgarch.c | 66 | 5 |
| src/backend/postmaster/shell_archive.c | 23 | 1 |
| src/backend/utils/init/miscinit.c | 1 | 0 |
| src/backend/utils/misc/guc.c | 11 | 1 |
| src/backend/utils/misc/postgresql.conf.sample | 1 | 0 |
| src/include/access/xlog.h | 0 | 1 |
| src/include/postmaster/pgarch.h | 44 | 2 |
From 76e0d1b1c32cba4d1b4cfe9f3d71c9d43a3e9b6c Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
Date: Fri, 19 Nov 2021 01:04:41 +0000
Subject: [PATCH v12 2/4] Introduce archive modules infrastructure.
---
src/backend/access/transam/xlog.c | 2 +-
src/backend/postmaster/pgarch.c | 71 +++++++++++++++++++++++++--
src/backend/postmaster/shell_archive.c | 24 ++++++++-
src/backend/utils/init/miscinit.c | 1 +
src/backend/utils/misc/guc.c | 12 ++++-
src/backend/utils/misc/postgresql.conf.sample | 1 +
src/include/access/xlog.h | 1 -
src/include/postmaster/pgarch.h | 46 ++++++++++++++++-
8 files changed, 147 insertions(+), 11 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 87cd05c945..fa13bf4d21 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8832,7 +8832,7 @@ ShutdownXLOG(int code, Datum arg)
* process one more time at the end of shutdown). The checkpoint
* record will go to the next XLOG file and won't be archived (yet).
*/
- if (XLogArchivingActive() && XLogArchiveCommandSet())
+ if (XLogArchivingActive())
RequestXLogSwitch(false);
CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index dc68dd570e..61e88ff133 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -88,6 +88,8 @@ typedef struct PgArchData
slock_t arch_lck;
} PgArchData;
+char *XLogArchiveLibrary = "";
+
/* ----------
* Local data
@@ -95,6 +97,8 @@ typedef struct PgArchData
*/
static time_t last_sigterm_time = 0;
static PgArchData *PgArch = NULL;
+static ArchiveModuleCallbacks *ArchiveContext = NULL;
+
/*
* Stuff for tracking multiple files to archive from each scan of
@@ -139,6 +143,7 @@ static void pgarch_archiveDone(char *xlog);
static void pgarch_die(int code, Datum arg);
static void HandlePgArchInterrupts(void);
static int ready_file_comparator(Datum a, Datum b, void *arg);
+static void LoadArchiveLibrary(void);
/* Report shared memory space needed by PgArchShmemInit */
Size
@@ -235,6 +240,11 @@ PgArchiverMain(void)
*/
PgArch->pgprocno = MyProc->pgprocno;
+ /*
+ * Load the archive_library.
+ */
+ LoadArchiveLibrary();
+
/* Create workspace for pgarch_readyXlog() */
arch_files = palloc(sizeof(struct arch_files_state));
arch_files->arch_files_size = 0;
@@ -406,11 +416,11 @@ pgarch_ArchiverCopyLoop(void)
*/
HandlePgArchInterrupts();
- /* can't do anything if no command ... */
- if (!XLogArchiveCommandSet())
+ /* can't do anything if not configured ... */
+ if (!ArchiveContext->check_configured_cb())
{
ereport(WARNING,
- (errmsg("archive_mode enabled, yet archive_command is not set")));
+ (errmsg("archive_mode enabled, yet archiving is not configured")));
return;
}
@@ -491,7 +501,7 @@ pgarch_ArchiverCopyLoop(void)
/*
* pgarch_archiveXlog
*
- * Invokes system(3) to copy one archive file to wherever it should go
+ * Invokes archive_file_cb to copy one archive file to wherever it should go
*
* Returns true if successful
*/
@@ -508,7 +518,7 @@ pgarch_archiveXlog(char *xlog)
snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
set_ps_display(activitymsg);
- ret = shell_archive_file(xlog, pathname);
+ ret = ArchiveContext->archive_file_cb(xlog, pathname);
if (ret)
snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
else
@@ -761,5 +771,56 @@ HandlePgArchInterrupts(void)
{
ConfigReloadPending = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * Load the archive_library in case it changed. Ideally, this would
+ * first unload any pre-existing loaded archive library to release
+ * custom GUCs, decommission background workers, etc., but there is
+ * presently no mechanism for unloading a library. For more
+ * information, see the comment above internal_unload_library().
+ */
+ LoadArchiveLibrary();
}
}
+
+/*
+ * LoadArchiveLibrary
+ *
+ * Loads the archiving callbacks into our local ArchiveContext.
+ */
+static void
+LoadArchiveLibrary(void)
+{
+ ArchiveModuleInit archive_init;
+
+ if (ArchiveContext == NULL)
+ ArchiveContext = palloc(sizeof(ArchiveModuleCallbacks));
+
+ memset(ArchiveContext, 0, sizeof(ArchiveModuleCallbacks));
+
+ /*
+ * If shell archiving is enabled, use our special initialization
+ * function. Otherwise, load the library and call its
+ * _PG_archive_module_init().
+ */
+ if (ShellArchivingEnabled())
+ archive_init = shell_archive_init;
+ else
+ archive_init = (ArchiveModuleInit)
+ load_external_function(XLogArchiveLibrary,
+ "_PG_archive_module_init", false, NULL);
+
+ if (archive_init == NULL)
+ ereport(ERROR,
+ (errmsg("archive modules have to declare the "
+ "_PG_archive_module_init symbol")));
+
+ archive_init(ArchiveContext);
+
+ if (ArchiveContext->check_configured_cb == NULL)
+ ereport(ERROR,
+ (errmsg("archive modules must register a check callback")));
+ if (ArchiveContext->archive_file_cb == NULL)
+ ereport(ERROR,
+ (errmsg("archive modules must register an archive callback")));
+}
diff --git a/src/backend/postmaster/shell_archive.c b/src/backend/postmaster/shell_archive.c
index b54e701da4..19e240c205 100644
--- a/src/backend/postmaster/shell_archive.c
+++ b/src/backend/postmaster/shell_archive.c
@@ -2,6 +2,10 @@
*
* shell_archive.c
*
+ * This archiving function uses a user-specified shell command (the
+ * archive_command GUC) to copy write-ahead log files. It is used as the
+ * default, but other modules may define their own custom archiving logic.
+ *
* Copyright (c) 2022, PostgreSQL Global Development Group
*
* IDENTIFICATION
@@ -17,7 +21,25 @@
#include "pgstat.h"
#include "postmaster/pgarch.h"
-bool
+static bool shell_archive_configured(void);
+static bool shell_archive_file(const char *file, const char *path);
+
+void
+shell_archive_init(ArchiveModuleCallbacks *cb)
+{
+ AssertVariableIsOfType(&shell_archive_init, ArchiveModuleInit);
+
+ cb->check_configured_cb = shell_archive_configured;
+ cb->archive_file_cb = shell_archive_file;
+}
+
+static bool
+shell_archive_configured(void)
+{
+ return XLogArchiveCommand[0] != '\0';
+}
+
+static bool
shell_archive_file(const char *file, const char *path)
{
char xlogarchcmd[MAXPGPATH];
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 88801374b5..358d9ed029 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -38,6 +38,7 @@
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "postmaster/interrupt.h"
+#include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
#include "storage/fd.h"
#include "storage/ipc.h"
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f9504d3aec..2554923e1d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3869,13 +3869,23 @@ static struct config_string ConfigureNamesString[] =
{
{"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
gettext_noop("Sets the shell command that will be called to archive a WAL file."),
- NULL
+ gettext_noop("This is unused if \"archive_library\" does not indicate archiving via shell is enabled.")
},
&XLogArchiveCommand,
"",
NULL, NULL, show_archive_command
},
+ {
+ {"archive_library", PGC_SIGHUP, WAL_ARCHIVING,
+ gettext_noop("Sets the library that will be called to archive a WAL file."),
+ gettext_noop("A value of \"shell\" or an empty string indicates that \"archive_command\" should be used.")
+ },
+ &XLogArchiveLibrary,
+ "shell",
+ NULL, NULL, NULL
+ },
+
{
{"restore_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
gettext_noop("Sets the shell command that will be called to retrieve an archived WAL file."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index a1acd46b61..e8bdd1fe13 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -245,6 +245,7 @@
#archive_mode = off # enables archiving; off, on, or always
# (change requires restart)
+#archive_library = 'shell' # library to use to archive a logfile segment
#archive_command = '' # command to use to archive a logfile segment
# placeholders: %p = path of file to archive
# %f = file name only
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 34f6c89f06..b7dfb580ad 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -155,7 +155,6 @@ extern PGDLLIMPORT int wal_level;
/* Is WAL archiving enabled always (even during recovery)? */
#define XLogArchivingAlways() \
(AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode == ARCHIVE_MODE_ALWAYS)
-#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
/*
* Is WAL-logging necessary for archival or log-shipping, or can we skip
diff --git a/src/include/postmaster/pgarch.h b/src/include/postmaster/pgarch.h
index 9c4bd69b56..03b5ab7c22 100644
--- a/src/include/postmaster/pgarch.h
+++ b/src/include/postmaster/pgarch.h
@@ -33,7 +33,49 @@ extern void PgArchiverMain(void) pg_attribute_noreturn();
extern void PgArchWakeup(void);
extern void PgArchForceDirScan(void);
-/* in shell_archive.c */
-extern bool shell_archive_file(const char *file, const char *path);
+/*
+ * The value of the archive_library GUC.
+ */
+extern char *XLogArchiveLibrary;
+
+/*
+ * Callback that gets called to determine if the archive module is
+ * configured.
+ */
+typedef bool (*ArchiveCheckConfiguredCB) (void);
+
+/*
+ * Callback called to archive a single WAL file.
+ */
+typedef bool (*ArchiveFileCB) (const char *file, const char *path);
+
+/*
+ * Archive module callbacks
+ */
+typedef struct ArchiveModuleCallbacks
+{
+ ArchiveCheckConfiguredCB check_configured_cb;
+ ArchiveFileCB archive_file_cb;
+} ArchiveModuleCallbacks;
+
+/*
+ * Type of the shared library symbol _PG_archive_module_init that is looked
+ * up when loading an archive library.
+ */
+typedef void (*ArchiveModuleInit) (ArchiveModuleCallbacks *cb);
+
+/*
+ * 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 void shell_archive_init(ArchiveModuleCallbacks *cb);
+
+/*
+ * We consider archiving via shell to be enabled if archive_library is
+ * empty or if archive_library is set to "shell".
+ */
+#define ShellArchivingEnabled() \
+ (XLogArchiveLibrary[0] == '\0' || strcmp(XLogArchiveLibrary, "shell") == 0)
#endif /* _PGARCH_H */
--
2.16.6