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 */