Move the code to archive files via the shell to a separate file.
authorRobert Haas <rhaas@postgresql.org>
Fri, 28 Jan 2022 18:29:32 +0000 (13:29 -0500)
committerRobert Haas <rhaas@postgresql.org>
Fri, 28 Jan 2022 18:29:32 +0000 (13:29 -0500)
This is preparatory work for allowing more extensibility in this area.

Nathan Bossart

Discussion: http://postgr.es/m/668D2428-F73B-475E-87AE-F89D67942270@amazon.com

src/backend/postmaster/Makefile
src/backend/postmaster/pgarch.c
src/backend/postmaster/shell_archive.c [new file with mode: 0644]
src/include/postmaster/pgarch.h

index 787c6a2c3bf0df294117fcdfa779924a1651ac8d..dbbeac5a82f675ccc1fc024bbc545868a139fa12 100644 (file)
@@ -23,6 +23,7 @@ OBJS = \
        pgarch.o \
        pgstat.o \
        postmaster.o \
+       shell_archive.o \
        startup.o \
        syslogger.o \
        walwriter.o
index 1121e4fb29c78d95b45c92617909190f9150ad5b..6e3fcedc9788395a6623938980b7723fc352a798 100644 (file)
  */
 #include "postgres.h"
 
-#include <fcntl.h>
-#include <signal.h>
 #include <time.h>
 #include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
 #include <unistd.h>
 
 #include "access/xlog.h"
 #include "access/xlog_internal.h"
 #include "lib/binaryheap.h"
 #include "libpq/pqsignal.h"
-#include "miscadmin.h"
 #include "pgstat.h"
 #include "postmaster/interrupt.h"
 #include "postmaster/pgarch.h"
@@ -504,132 +499,24 @@ pgarch_ArchiverCopyLoop(void)
 static bool
 pgarch_archiveXlog(char *xlog)
 {
-       char            xlogarchcmd[MAXPGPATH];
        char            pathname[MAXPGPATH];
        char            activitymsg[MAXFNAMELEN + 16];
-       char       *dp;
-       char       *endp;
-       const char *sp;
-       int                     rc;
+       bool            ret;
 
        snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
 
-       /*
-        * construct the command to be executed
-        */
-       dp = xlogarchcmd;
-       endp = xlogarchcmd + MAXPGPATH - 1;
-       *endp = '\0';
-
-       for (sp = XLogArchiveCommand; *sp; sp++)
-       {
-               if (*sp == '%')
-               {
-                       switch (sp[1])
-                       {
-                               case 'p':
-                                       /* %p: relative path of source file */
-                                       sp++;
-                                       strlcpy(dp, pathname, endp - dp);
-                                       make_native_path(dp);
-                                       dp += strlen(dp);
-                                       break;
-                               case 'f':
-                                       /* %f: filename of source file */
-                                       sp++;
-                                       strlcpy(dp, xlog, endp - dp);
-                                       dp += strlen(dp);
-                                       break;
-                               case '%':
-                                       /* convert %% to a single % */
-                                       sp++;
-                                       if (dp < endp)
-                                               *dp++ = *sp;
-                                       break;
-                               default:
-                                       /* otherwise treat the % as not special */
-                                       if (dp < endp)
-                                               *dp++ = *sp;
-                                       break;
-                       }
-               }
-               else
-               {
-                       if (dp < endp)
-                               *dp++ = *sp;
-               }
-       }
-       *dp = '\0';
-
-       ereport(DEBUG3,
-                       (errmsg_internal("executing archive command \"%s\"",
-                                                        xlogarchcmd)));
-
        /* Report archive activity in PS display */
        snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
        set_ps_display(activitymsg);
 
-       pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
-       rc = system(xlogarchcmd);
-       pgstat_report_wait_end();
-
-       if (rc != 0)
-       {
-               /*
-                * If either the shell itself, or a called command, died on a signal,
-                * abort the archiver.  We do this because system() ignores SIGINT and
-                * SIGQUIT while waiting; so a signal is very likely something that
-                * should have interrupted us too.  Also die if the shell got a hard
-                * "command not found" type of error.  If we overreact it's no big
-                * deal, the postmaster will just start the archiver again.
-                */
-               int                     lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
-
-               if (WIFEXITED(rc))
-               {
-                       ereport(lev,
-                                       (errmsg("archive command failed with exit code %d",
-                                                       WEXITSTATUS(rc)),
-                                        errdetail("The failed archive command was: %s",
-                                                          xlogarchcmd)));
-               }
-               else if (WIFSIGNALED(rc))
-               {
-#if defined(WIN32)
-                       ereport(lev,
-                                       (errmsg("archive command was terminated by exception 0x%X",
-                                                       WTERMSIG(rc)),
-                                        errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
-                                        errdetail("The failed archive command was: %s",
-                                                          xlogarchcmd)));
-#else
-                       ereport(lev,
-                                       (errmsg("archive command was terminated by signal %d: %s",
-                                                       WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
-                                        errdetail("The failed archive command was: %s",
-                                                          xlogarchcmd)));
-#endif
-               }
-               else
-               {
-                       ereport(lev,
-                                       (errmsg("archive command exited with unrecognized status %d",
-                                                       rc),
-                                        errdetail("The failed archive command was: %s",
-                                                          xlogarchcmd)));
-               }
-
+       ret = shell_archive_file(xlog, pathname);
+       if (ret)
+               snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
+       else
                snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
-               set_ps_display(activitymsg);
-
-               return false;
-       }
-       elog(DEBUG1, "archived write-ahead log file \"%s\"", xlog);
-
-       snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
        set_ps_display(activitymsg);
 
-       return true;
+       return ret;
 }
 
 /*
diff --git a/src/backend/postmaster/shell_archive.c b/src/backend/postmaster/shell_archive.c
new file mode 100644 (file)
index 0000000..b54e701
--- /dev/null
@@ -0,0 +1,135 @@
+/*-------------------------------------------------------------------------
+ *
+ * shell_archive.c
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       src/backend/postmaster/shell_archive.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <sys/wait.h>
+
+#include "access/xlog.h"
+#include "pgstat.h"
+#include "postmaster/pgarch.h"
+
+bool
+shell_archive_file(const char *file, const char *path)
+{
+       char            xlogarchcmd[MAXPGPATH];
+       char       *dp;
+       char       *endp;
+       const char *sp;
+       int                     rc;
+
+       /*
+        * construct the command to be executed
+        */
+       dp = xlogarchcmd;
+       endp = xlogarchcmd + MAXPGPATH - 1;
+       *endp = '\0';
+
+       for (sp = XLogArchiveCommand; *sp; sp++)
+       {
+               if (*sp == '%')
+               {
+                       switch (sp[1])
+                       {
+                               case 'p':
+                                       /* %p: relative path of source file */
+                                       sp++;
+                                       strlcpy(dp, path, endp - dp);
+                                       make_native_path(dp);
+                                       dp += strlen(dp);
+                                       break;
+                               case 'f':
+                                       /* %f: filename of source file */
+                                       sp++;
+                                       strlcpy(dp, file, endp - dp);
+                                       dp += strlen(dp);
+                                       break;
+                               case '%':
+                                       /* convert %% to a single % */
+                                       sp++;
+                                       if (dp < endp)
+                                               *dp++ = *sp;
+                                       break;
+                               default:
+                                       /* otherwise treat the % as not special */
+                                       if (dp < endp)
+                                               *dp++ = *sp;
+                                       break;
+                       }
+               }
+               else
+               {
+                       if (dp < endp)
+                               *dp++ = *sp;
+               }
+       }
+       *dp = '\0';
+
+       ereport(DEBUG3,
+                       (errmsg_internal("executing archive command \"%s\"",
+                                                        xlogarchcmd)));
+
+       pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
+       rc = system(xlogarchcmd);
+       pgstat_report_wait_end();
+
+       if (rc != 0)
+       {
+               /*
+                * If either the shell itself, or a called command, died on a signal,
+                * abort the archiver.  We do this because system() ignores SIGINT and
+                * SIGQUIT while waiting; so a signal is very likely something that
+                * should have interrupted us too.  Also die if the shell got a hard
+                * "command not found" type of error.  If we overreact it's no big
+                * deal, the postmaster will just start the archiver again.
+                */
+               int                     lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
+
+               if (WIFEXITED(rc))
+               {
+                       ereport(lev,
+                                       (errmsg("archive command failed with exit code %d",
+                                                       WEXITSTATUS(rc)),
+                                        errdetail("The failed archive command was: %s",
+                                                          xlogarchcmd)));
+               }
+               else if (WIFSIGNALED(rc))
+               {
+#if defined(WIN32)
+                       ereport(lev,
+                                       (errmsg("archive command was terminated by exception 0x%X",
+                                                       WTERMSIG(rc)),
+                                        errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
+                                        errdetail("The failed archive command was: %s",
+                                                          xlogarchcmd)));
+#else
+                       ereport(lev,
+                                       (errmsg("archive command was terminated by signal %d: %s",
+                                                       WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
+                                        errdetail("The failed archive command was: %s",
+                                                          xlogarchcmd)));
+#endif
+               }
+               else
+               {
+                       ereport(lev,
+                                       (errmsg("archive command exited with unrecognized status %d",
+                                                       rc),
+                                        errdetail("The failed archive command was: %s",
+                                                          xlogarchcmd)));
+               }
+
+               return false;
+       }
+
+       elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
+       return true;
+}
index ed55d6646b2db680d5c479870c438ed06939584b..991a6d061608d16533f40cc18862361f63483be9 100644 (file)
@@ -33,4 +33,7 @@ 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);
+
 #endif                                                 /* _PGARCH_H */