LCOV - code coverage report
Current view: top level - src/backend/postmaster - pgarch.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 142 190 74.7 %
Date: 2020-06-01 09:07:10 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pgarch.c
       4             :  *
       5             :  *  PostgreSQL WAL archiver
       6             :  *
       7             :  *  All functions relating to archiver are included here
       8             :  *
       9             :  *  - All functions executed by archiver process
      10             :  *
      11             :  *  - archiver is forked from postmaster, and the two
      12             :  *  processes then communicate using signals. All functions
      13             :  *  executed by postmaster are included in this file.
      14             :  *
      15             :  *  Initial author: Simon Riggs     simon@2ndquadrant.com
      16             :  *
      17             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
      18             :  * Portions Copyright (c) 1994, Regents of the University of California
      19             :  *
      20             :  *
      21             :  * IDENTIFICATION
      22             :  *    src/backend/postmaster/pgarch.c
      23             :  *
      24             :  *-------------------------------------------------------------------------
      25             :  */
      26             : #include "postgres.h"
      27             : 
      28             : #include <fcntl.h>
      29             : #include <signal.h>
      30             : #include <time.h>
      31             : #include <sys/stat.h>
      32             : #include <sys/time.h>
      33             : #include <sys/wait.h>
      34             : #include <unistd.h>
      35             : 
      36             : #include "access/xlog.h"
      37             : #include "access/xlog_internal.h"
      38             : #include "libpq/pqsignal.h"
      39             : #include "miscadmin.h"
      40             : #include "pgstat.h"
      41             : #include "postmaster/fork_process.h"
      42             : #include "postmaster/interrupt.h"
      43             : #include "postmaster/pgarch.h"
      44             : #include "postmaster/postmaster.h"
      45             : #include "storage/dsm.h"
      46             : #include "storage/fd.h"
      47             : #include "storage/ipc.h"
      48             : #include "storage/latch.h"
      49             : #include "storage/pg_shmem.h"
      50             : #include "storage/pmsignal.h"
      51             : #include "utils/guc.h"
      52             : #include "utils/ps_status.h"
      53             : 
      54             : 
      55             : /* ----------
      56             :  * Timer definitions.
      57             :  * ----------
      58             :  */
      59             : #define PGARCH_AUTOWAKE_INTERVAL 60 /* How often to force a poll of the
      60             :                                      * archive status directory; in seconds. */
      61             : #define PGARCH_RESTART_INTERVAL 10  /* How often to attempt to restart a
      62             :                                      * failed archiver; in seconds. */
      63             : 
      64             : /*
      65             :  * Maximum number of retries allowed when attempting to archive a WAL
      66             :  * file.
      67             :  */
      68             : #define NUM_ARCHIVE_RETRIES 3
      69             : 
      70             : /*
      71             :  * Maximum number of retries allowed when attempting to remove an
      72             :  * orphan archive status file.
      73             :  */
      74             : #define NUM_ORPHAN_CLEANUP_RETRIES 3
      75             : 
      76             : 
      77             : /* ----------
      78             :  * Local data
      79             :  * ----------
      80             :  */
      81             : static time_t last_pgarch_start_time;
      82             : static time_t last_sigterm_time = 0;
      83             : 
      84             : /*
      85             :  * Flags set by interrupt handlers for later service in the main loop.
      86             :  */
      87             : static volatile sig_atomic_t wakened = false;
      88             : static volatile sig_atomic_t ready_to_stop = false;
      89             : 
      90             : /* ----------
      91             :  * Local function forward declarations
      92             :  * ----------
      93             :  */
      94             : #ifdef EXEC_BACKEND
      95             : static pid_t pgarch_forkexec(void);
      96             : #endif
      97             : 
      98             : NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn();
      99             : static void pgarch_exit(SIGNAL_ARGS);
     100             : static void pgarch_waken(SIGNAL_ARGS);
     101             : static void pgarch_waken_stop(SIGNAL_ARGS);
     102             : static void pgarch_MainLoop(void);
     103             : static void pgarch_ArchiverCopyLoop(void);
     104             : static bool pgarch_archiveXlog(char *xlog);
     105             : static bool pgarch_readyXlog(char *xlog);
     106             : static void pgarch_archiveDone(char *xlog);
     107             : 
     108             : 
     109             : /* ------------------------------------------------------------
     110             :  * Public functions called from postmaster follow
     111             :  * ------------------------------------------------------------
     112             :  */
     113             : 
     114             : /*
     115             :  * pgarch_start
     116             :  *
     117             :  *  Called from postmaster at startup or after an existing archiver
     118             :  *  died.  Attempt to fire up a fresh archiver process.
     119             :  *
     120             :  *  Returns PID of child process, or 0 if fail.
     121             :  *
     122             :  *  Note: if fail, we will be called again from the postmaster main loop.
     123             :  */
     124             : int
     125          22 : pgarch_start(void)
     126             : {
     127             :     time_t      curtime;
     128             :     pid_t       pgArchPid;
     129             : 
     130             :     /*
     131             :      * Do nothing if no archiver needed
     132             :      */
     133          22 :     if (!XLogArchivingActive())
     134           0 :         return 0;
     135             : 
     136             :     /*
     137             :      * Do nothing if too soon since last archiver start.  This is a safety
     138             :      * valve to protect against continuous respawn attempts if the archiver is
     139             :      * dying immediately at launch. Note that since we will be re-called from
     140             :      * the postmaster main loop, we will get another chance later.
     141             :      */
     142          22 :     curtime = time(NULL);
     143          22 :     if ((unsigned int) (curtime - last_pgarch_start_time) <
     144             :         (unsigned int) PGARCH_RESTART_INTERVAL)
     145           0 :         return 0;
     146          22 :     last_pgarch_start_time = curtime;
     147             : 
     148             : #ifdef EXEC_BACKEND
     149             :     switch ((pgArchPid = pgarch_forkexec()))
     150             : #else
     151          22 :     switch ((pgArchPid = fork_process()))
     152             : #endif
     153             :     {
     154           0 :         case -1:
     155           0 :             ereport(LOG,
     156             :                     (errmsg("could not fork archiver: %m")));
     157           0 :             return 0;
     158             : 
     159             : #ifndef EXEC_BACKEND
     160          22 :         case 0:
     161             :             /* in postmaster child ... */
     162          22 :             InitPostmasterChild();
     163             : 
     164             :             /* Close the postmaster's sockets */
     165          22 :             ClosePostmasterPorts(false);
     166             : 
     167             :             /* Drop our connection to postmaster's shared memory, as well */
     168          22 :             dsm_detach_all();
     169          22 :             PGSharedMemoryDetach();
     170             : 
     171          22 :             PgArchiverMain(0, NULL);
     172             :             break;
     173             : #endif
     174             : 
     175          22 :         default:
     176          22 :             return (int) pgArchPid;
     177             :     }
     178             : 
     179             :     /* shouldn't get here */
     180             :     return 0;
     181             : }
     182             : 
     183             : /* ------------------------------------------------------------
     184             :  * Local functions called by archiver follow
     185             :  * ------------------------------------------------------------
     186             :  */
     187             : 
     188             : 
     189             : #ifdef EXEC_BACKEND
     190             : 
     191             : /*
     192             :  * pgarch_forkexec() -
     193             :  *
     194             :  * Format up the arglist for, then fork and exec, archive process
     195             :  */
     196             : static pid_t
     197             : pgarch_forkexec(void)
     198             : {
     199             :     char       *av[10];
     200             :     int         ac = 0;
     201             : 
     202             :     av[ac++] = "postgres";
     203             : 
     204             :     av[ac++] = "--forkarch";
     205             : 
     206             :     av[ac++] = NULL;            /* filled in by postmaster_forkexec */
     207             : 
     208             :     av[ac] = NULL;
     209             :     Assert(ac < lengthof(av));
     210             : 
     211             :     return postmaster_forkexec(ac, av);
     212             : }
     213             : #endif                          /* EXEC_BACKEND */
     214             : 
     215             : 
     216             : /*
     217             :  * PgArchiverMain
     218             :  *
     219             :  *  The argc/argv parameters are valid only in EXEC_BACKEND case.  However,
     220             :  *  since we don't use 'em, it hardly matters...
     221             :  */
     222             : NON_EXEC_STATIC void
     223          22 : PgArchiverMain(int argc, char *argv[])
     224             : {
     225             :     /*
     226             :      * Ignore all signals usually bound to some action in the postmaster,
     227             :      * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
     228             :      */
     229          22 :     pqsignal(SIGHUP, SignalHandlerForConfigReload);
     230          22 :     pqsignal(SIGINT, SIG_IGN);
     231          22 :     pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
     232          22 :     pqsignal(SIGQUIT, pgarch_exit);
     233          22 :     pqsignal(SIGALRM, SIG_IGN);
     234          22 :     pqsignal(SIGPIPE, SIG_IGN);
     235          22 :     pqsignal(SIGUSR1, pgarch_waken);
     236          22 :     pqsignal(SIGUSR2, pgarch_waken_stop);
     237             :     /* Reset some signals that are accepted by postmaster but not here */
     238          22 :     pqsignal(SIGCHLD, SIG_DFL);
     239          22 :     PG_SETMASK(&UnBlockSig);
     240             : 
     241          22 :     MyBackendType = B_ARCHIVER;
     242          22 :     init_ps_display(NULL);
     243             : 
     244          22 :     pgarch_MainLoop();
     245             : 
     246           0 :     exit(0);
     247             : }
     248             : 
     249             : /* SIGQUIT signal handler for archiver process */
     250             : static void
     251          22 : pgarch_exit(SIGNAL_ARGS)
     252             : {
     253             :     /* SIGQUIT means curl up and die ... */
     254          22 :     exit(1);
     255             : }
     256             : 
     257             : /* SIGUSR1 signal handler for archiver process */
     258             : static void
     259          28 : pgarch_waken(SIGNAL_ARGS)
     260             : {
     261          28 :     int         save_errno = errno;
     262             : 
     263             :     /* set flag that there is work to be done */
     264          28 :     wakened = true;
     265          28 :     SetLatch(MyLatch);
     266             : 
     267          28 :     errno = save_errno;
     268          28 : }
     269             : 
     270             : /* SIGUSR2 signal handler for archiver process */
     271             : static void
     272           0 : pgarch_waken_stop(SIGNAL_ARGS)
     273             : {
     274           0 :     int         save_errno = errno;
     275             : 
     276             :     /* set flag to do a final cycle and shut down afterwards */
     277           0 :     ready_to_stop = true;
     278           0 :     SetLatch(MyLatch);
     279             : 
     280           0 :     errno = save_errno;
     281           0 : }
     282             : 
     283             : /*
     284             :  * pgarch_MainLoop
     285             :  *
     286             :  * Main loop for archiver
     287             :  */
     288             : static void
     289          22 : pgarch_MainLoop(void)
     290             : {
     291          22 :     pg_time_t   last_copy_time = 0;
     292             :     bool        time_to_stop;
     293             : 
     294             :     /*
     295             :      * We run the copy loop immediately upon entry, in case there are
     296             :      * unarchived files left over from a previous database run (or maybe the
     297             :      * archiver died unexpectedly).  After that we wait for a signal or
     298             :      * timeout before doing more.
     299             :      */
     300          22 :     wakened = true;
     301             : 
     302             :     /*
     303             :      * There shouldn't be anything for the archiver to do except to wait for a
     304             :      * signal ... however, the archiver exists to protect our data, so she
     305             :      * wakes up occasionally to allow herself to be proactive.
     306             :      */
     307             :     do
     308             :     {
     309          54 :         ResetLatch(MyLatch);
     310             : 
     311             :         /* When we get SIGUSR2, we do one more archive cycle, then exit */
     312          54 :         time_to_stop = ready_to_stop;
     313             : 
     314             :         /* Check for config update */
     315          54 :         if (ConfigReloadPending)
     316             :         {
     317           2 :             ConfigReloadPending = false;
     318           2 :             ProcessConfigFile(PGC_SIGHUP);
     319             :         }
     320             : 
     321             :         /*
     322             :          * If we've gotten SIGTERM, we normally just sit and do nothing until
     323             :          * SIGUSR2 arrives.  However, that means a random SIGTERM would
     324             :          * disable archiving indefinitely, which doesn't seem like a good
     325             :          * idea.  If more than 60 seconds pass since SIGTERM, exit anyway, so
     326             :          * that the postmaster can start a new archiver if needed.
     327             :          */
     328          54 :         if (ShutdownRequestPending)
     329             :         {
     330           0 :             time_t      curtime = time(NULL);
     331             : 
     332           0 :             if (last_sigterm_time == 0)
     333           0 :                 last_sigterm_time = curtime;
     334           0 :             else if ((unsigned int) (curtime - last_sigterm_time) >=
     335             :                      (unsigned int) 60)
     336           0 :                 break;
     337             :         }
     338             : 
     339             :         /* Do what we're here for */
     340          54 :         if (wakened || time_to_stop)
     341             :         {
     342          48 :             wakened = false;
     343          48 :             pgarch_ArchiverCopyLoop();
     344          44 :             last_copy_time = time(NULL);
     345             :         }
     346             : 
     347             :         /*
     348             :          * Sleep until a signal is received, or until a poll is forced by
     349             :          * PGARCH_AUTOWAKE_INTERVAL having passed since last_copy_time, or
     350             :          * until postmaster dies.
     351             :          */
     352          50 :         if (!time_to_stop)      /* Don't wait during last iteration */
     353             :         {
     354          50 :             pg_time_t   curtime = (pg_time_t) time(NULL);
     355             :             int         timeout;
     356             : 
     357          50 :             timeout = PGARCH_AUTOWAKE_INTERVAL - (curtime - last_copy_time);
     358          50 :             if (timeout > 0)
     359             :             {
     360             :                 int         rc;
     361             : 
     362          50 :                 rc = WaitLatch(MyLatch,
     363             :                                WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
     364             :                                timeout * 1000L,
     365             :                                WAIT_EVENT_ARCHIVER_MAIN);
     366          32 :                 if (rc & WL_TIMEOUT)
     367           0 :                     wakened = true;
     368          32 :                 if (rc & WL_POSTMASTER_DEATH)
     369           0 :                     time_to_stop = true;
     370             :             }
     371             :             else
     372           0 :                 wakened = true;
     373             :         }
     374             : 
     375             :         /*
     376             :          * The archiver quits either when the postmaster dies (not expected)
     377             :          * or after completing one more archiving cycle after receiving
     378             :          * SIGUSR2.
     379             :          */
     380          32 :     } while (!time_to_stop);
     381           0 : }
     382             : 
     383             : /*
     384             :  * pgarch_ArchiverCopyLoop
     385             :  *
     386             :  * Archives all outstanding xlogs then returns
     387             :  */
     388             : static void
     389          48 : pgarch_ArchiverCopyLoop(void)
     390             : {
     391             :     char        xlog[MAX_XFN_CHARS + 1];
     392             : 
     393             :     /*
     394             :      * loop through all xlogs with archive_status of .ready and archive
     395             :      * them...mostly we expect this to be a single file, though it is possible
     396             :      * some backend will add files onto the list of those that need archiving
     397             :      * while we are still copying earlier archives
     398             :      */
     399          86 :     while (pgarch_readyXlog(xlog))
     400             :     {
     401          42 :         int         failures = 0;
     402          42 :         int         failures_orphan = 0;
     403             : 
     404             :         for (;;)
     405           6 :         {
     406             :             struct stat stat_buf;
     407             :             char        pathname[MAXPGPATH];
     408             : 
     409             :             /*
     410             :              * Do not initiate any more archive commands after receiving
     411             :              * SIGTERM, nor after the postmaster has died unexpectedly. The
     412             :              * first condition is to try to keep from having init SIGKILL the
     413             :              * command, and the second is to avoid conflicts with another
     414             :              * archiver spawned by a newer postmaster.
     415             :              */
     416          48 :             if (ShutdownRequestPending || !PostmasterIsAlive())
     417           0 :                 return;
     418             : 
     419             :             /*
     420             :              * Check for config update.  This is so that we'll adopt a new
     421             :              * setting for archive_command as soon as possible, even if there
     422             :              * is a backlog of files to be archived.
     423             :              */
     424          48 :             if (ConfigReloadPending)
     425             :             {
     426           4 :                 ConfigReloadPending = false;
     427           4 :                 ProcessConfigFile(PGC_SIGHUP);
     428             :             }
     429             : 
     430             :             /* can't do anything if no command ... */
     431          48 :             if (!XLogArchiveCommandSet())
     432             :             {
     433           0 :                 ereport(WARNING,
     434             :                         (errmsg("archive_mode enabled, yet archive_command is not set")));
     435           0 :                 return;
     436             :             }
     437             : 
     438             :             /*
     439             :              * Since archive status files are not removed in a durable manner,
     440             :              * a system crash could leave behind .ready files for WAL segments
     441             :              * that have already been recycled or removed.  In this case,
     442             :              * simply remove the orphan status file and move on.  unlink() is
     443             :              * used here as even on subsequent crashes the same orphan files
     444             :              * would get removed, so there is no need to worry about
     445             :              * durability.
     446             :              */
     447          48 :             snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
     448          48 :             if (stat(pathname, &stat_buf) != 0 && errno == ENOENT)
     449             :             {
     450             :                 char        xlogready[MAXPGPATH];
     451             : 
     452           0 :                 StatusFilePath(xlogready, xlog, ".ready");
     453           0 :                 if (unlink(xlogready) == 0)
     454             :                 {
     455           0 :                     ereport(WARNING,
     456             :                             (errmsg("removed orphan archive status file \"%s\"",
     457             :                                     xlogready)));
     458             : 
     459             :                     /* leave loop and move to the next status file */
     460           0 :                     break;
     461             :                 }
     462             : 
     463           0 :                 if (++failures_orphan >= NUM_ORPHAN_CLEANUP_RETRIES)
     464             :                 {
     465           0 :                     ereport(WARNING,
     466             :                             (errmsg("removal of orphan archive status file \"%s\" failed too many times, will try again later",
     467             :                                     xlogready)));
     468             : 
     469             :                     /* give up cleanup of orphan status files */
     470           0 :                     return;
     471             :                 }
     472             : 
     473             :                 /* wait a bit before retrying */
     474           0 :                 pg_usleep(1000000L);
     475           0 :                 continue;
     476             :             }
     477             : 
     478          48 :             if (pgarch_archiveXlog(xlog))
     479             :             {
     480             :                 /* successful */
     481          38 :                 pgarch_archiveDone(xlog);
     482             : 
     483             :                 /*
     484             :                  * Tell the collector about the WAL file that we successfully
     485             :                  * archived
     486             :                  */
     487          38 :                 pgstat_send_archiver(xlog, false);
     488             : 
     489          38 :                 break;          /* out of inner retry loop */
     490             :             }
     491             :             else
     492             :             {
     493             :                 /*
     494             :                  * Tell the collector about the WAL file that we failed to
     495             :                  * archive
     496             :                  */
     497          10 :                 pgstat_send_archiver(xlog, true);
     498             : 
     499          10 :                 if (++failures >= NUM_ARCHIVE_RETRIES)
     500             :                 {
     501           0 :                     ereport(WARNING,
     502             :                             (errmsg("archiving write-ahead log file \"%s\" failed too many times, will try again later",
     503             :                                     xlog)));
     504           0 :                     return;     /* give up archiving for now */
     505             :                 }
     506          10 :                 pg_usleep(1000000L);    /* wait a bit before retrying */
     507             :             }
     508             :         }
     509             :     }
     510             : }
     511             : 
     512             : /*
     513             :  * pgarch_archiveXlog
     514             :  *
     515             :  * Invokes system(3) to copy one archive file to wherever it should go
     516             :  *
     517             :  * Returns true if successful
     518             :  */
     519             : static bool
     520          48 : pgarch_archiveXlog(char *xlog)
     521             : {
     522             :     char        xlogarchcmd[MAXPGPATH];
     523             :     char        pathname[MAXPGPATH];
     524             :     char        activitymsg[MAXFNAMELEN + 16];
     525             :     char       *dp;
     526             :     char       *endp;
     527             :     const char *sp;
     528             :     int         rc;
     529             : 
     530          48 :     snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
     531             : 
     532             :     /*
     533             :      * construct the command to be executed
     534             :      */
     535          48 :     dp = xlogarchcmd;
     536          48 :     endp = xlogarchcmd + MAXPGPATH - 1;
     537          48 :     *endp = '\0';
     538             : 
     539        4590 :     for (sp = XLogArchiveCommand; *sp; sp++)
     540             :     {
     541        4542 :         if (*sp == '%')
     542             :         {
     543          96 :             switch (sp[1])
     544             :             {
     545          48 :                 case 'p':
     546             :                     /* %p: relative path of source file */
     547          48 :                     sp++;
     548          48 :                     strlcpy(dp, pathname, endp - dp);
     549          48 :                     make_native_path(dp);
     550          48 :                     dp += strlen(dp);
     551          48 :                     break;
     552          48 :                 case 'f':
     553             :                     /* %f: filename of source file */
     554          48 :                     sp++;
     555          48 :                     strlcpy(dp, xlog, endp - dp);
     556          48 :                     dp += strlen(dp);
     557          48 :                     break;
     558           0 :                 case '%':
     559             :                     /* convert %% to a single % */
     560           0 :                     sp++;
     561           0 :                     if (dp < endp)
     562           0 :                         *dp++ = *sp;
     563           0 :                     break;
     564           0 :                 default:
     565             :                     /* otherwise treat the % as not special */
     566           0 :                     if (dp < endp)
     567           0 :                         *dp++ = *sp;
     568           0 :                     break;
     569             :             }
     570             :         }
     571             :         else
     572             :         {
     573        4446 :             if (dp < endp)
     574        4446 :                 *dp++ = *sp;
     575             :         }
     576             :     }
     577          48 :     *dp = '\0';
     578             : 
     579          48 :     ereport(DEBUG3,
     580             :             (errmsg_internal("executing archive command \"%s\"",
     581             :                              xlogarchcmd)));
     582             : 
     583             :     /* Report archive activity in PS display */
     584          48 :     snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
     585          48 :     set_ps_display(activitymsg);
     586             : 
     587          48 :     rc = system(xlogarchcmd);
     588          48 :     if (rc != 0)
     589             :     {
     590             :         /*
     591             :          * If either the shell itself, or a called command, died on a signal,
     592             :          * abort the archiver.  We do this because system() ignores SIGINT and
     593             :          * SIGQUIT while waiting; so a signal is very likely something that
     594             :          * should have interrupted us too.  Also die if the shell got a hard
     595             :          * "command not found" type of error.  If we overreact it's no big
     596             :          * deal, the postmaster will just start the archiver again.
     597             :          */
     598          10 :         int         lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
     599             : 
     600          10 :         if (WIFEXITED(rc))
     601             :         {
     602          10 :             ereport(lev,
     603             :                     (errmsg("archive command failed with exit code %d",
     604             :                             WEXITSTATUS(rc)),
     605             :                      errdetail("The failed archive command was: %s",
     606             :                                xlogarchcmd)));
     607             :         }
     608           0 :         else if (WIFSIGNALED(rc))
     609             :         {
     610             : #if defined(WIN32)
     611             :             ereport(lev,
     612             :                     (errmsg("archive command was terminated by exception 0x%X",
     613             :                             WTERMSIG(rc)),
     614             :                      errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
     615             :                      errdetail("The failed archive command was: %s",
     616             :                                xlogarchcmd)));
     617             : #else
     618           0 :             ereport(lev,
     619             :                     (errmsg("archive command was terminated by signal %d: %s",
     620             :                             WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
     621             :                      errdetail("The failed archive command was: %s",
     622             :                                xlogarchcmd)));
     623             : #endif
     624             :         }
     625             :         else
     626             :         {
     627           0 :             ereport(lev,
     628             :                     (errmsg("archive command exited with unrecognized status %d",
     629             :                             rc),
     630             :                      errdetail("The failed archive command was: %s",
     631             :                                xlogarchcmd)));
     632             :         }
     633             : 
     634          10 :         snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
     635          10 :         set_ps_display(activitymsg);
     636             : 
     637          10 :         return false;
     638             :     }
     639          38 :     elog(DEBUG1, "archived write-ahead log file \"%s\"", xlog);
     640             : 
     641          38 :     snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
     642          38 :     set_ps_display(activitymsg);
     643             : 
     644          38 :     return true;
     645             : }
     646             : 
     647             : /*
     648             :  * pgarch_readyXlog
     649             :  *
     650             :  * Return name of the oldest xlog file that has not yet been archived.
     651             :  * No notification is set that file archiving is now in progress, so
     652             :  * this would need to be extended if multiple concurrent archival
     653             :  * tasks were created. If a failure occurs, we will completely
     654             :  * re-copy the file at the next available opportunity.
     655             :  *
     656             :  * It is important that we return the oldest, so that we archive xlogs
     657             :  * in order that they were written, for two reasons:
     658             :  * 1) to maintain the sequential chain of xlogs required for recovery
     659             :  * 2) because the oldest ones will sooner become candidates for
     660             :  * recycling at time of checkpoint
     661             :  *
     662             :  * NOTE: the "oldest" comparison will consider any .history file to be older
     663             :  * than any other file except another .history file.  Segments on a timeline
     664             :  * with a smaller ID will be older than all segments on a timeline with a
     665             :  * larger ID; the net result being that past timelines are given higher
     666             :  * priority for archiving.  This seems okay, or at least not obviously worth
     667             :  * changing.
     668             :  */
     669             : static bool
     670          86 : pgarch_readyXlog(char *xlog)
     671             : {
     672             :     /*
     673             :      * open xlog status directory and read through list of xlogs that have the
     674             :      * .ready suffix, looking for earliest file. It is possible to optimise
     675             :      * this code, though only a single file is expected on the vast majority
     676             :      * of calls, so....
     677             :      */
     678             :     char        XLogArchiveStatusDir[MAXPGPATH];
     679             :     DIR        *rldir;
     680             :     struct dirent *rlde;
     681          86 :     bool        found = false;
     682          86 :     bool        historyFound = false;
     683             : 
     684          86 :     snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
     685          86 :     rldir = AllocateDir(XLogArchiveStatusDir);
     686             : 
     687         426 :     while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
     688             :     {
     689         340 :         int         basenamelen = (int) strlen(rlde->d_name) - 6;
     690             :         char        basename[MAX_XFN_CHARS + 1];
     691             :         bool        ishistory;
     692             : 
     693             :         /* Ignore entries with unexpected number of characters */
     694         340 :         if (basenamelen < MIN_XFN_CHARS ||
     695             :             basenamelen > MAX_XFN_CHARS)
     696         288 :             continue;
     697             : 
     698             :         /* Ignore entries with unexpected characters */
     699         156 :         if (strspn(rlde->d_name, VALID_XFN_CHARS) < basenamelen)
     700           0 :             continue;
     701             : 
     702             :         /* Ignore anything not suffixed with .ready */
     703         156 :         if (strcmp(rlde->d_name + basenamelen, ".ready") != 0)
     704         104 :             continue;
     705             : 
     706             :         /* Truncate off the .ready */
     707          52 :         memcpy(basename, rlde->d_name, basenamelen);
     708          52 :         basename[basenamelen] = '\0';
     709             : 
     710             :         /* Is this a history file? */
     711          52 :         ishistory = IsTLHistoryFileName(basename);
     712             : 
     713             :         /*
     714             :          * Consume the file to archive.  History files have the highest
     715             :          * priority.  If this is the first file or the first history file
     716             :          * ever, copy it.  In the presence of a history file already chosen as
     717             :          * target, ignore all other files except history files which have been
     718             :          * generated for an older timeline than what is already chosen as
     719             :          * target to archive.
     720             :          */
     721          52 :         if (!found || (ishistory && !historyFound))
     722             :         {
     723          42 :             strcpy(xlog, basename);
     724          42 :             found = true;
     725          42 :             historyFound = ishistory;
     726             :         }
     727          10 :         else if (ishistory || !historyFound)
     728             :         {
     729           8 :             if (strcmp(basename, xlog) < 0)
     730           4 :                 strcpy(xlog, basename);
     731             :         }
     732             :     }
     733          86 :     FreeDir(rldir);
     734             : 
     735          86 :     return found;
     736             : }
     737             : 
     738             : /*
     739             :  * pgarch_archiveDone
     740             :  *
     741             :  * Emit notification that an xlog file has been successfully archived.
     742             :  * We do this by renaming the status file from NNN.ready to NNN.done.
     743             :  * Eventually, a checkpoint process will notice this and delete both the
     744             :  * NNN.done file and the xlog file itself.
     745             :  */
     746             : static void
     747          38 : pgarch_archiveDone(char *xlog)
     748             : {
     749             :     char        rlogready[MAXPGPATH];
     750             :     char        rlogdone[MAXPGPATH];
     751             : 
     752          38 :     StatusFilePath(rlogready, xlog, ".ready");
     753          38 :     StatusFilePath(rlogdone, xlog, ".done");
     754          38 :     (void) durable_rename(rlogready, rlogdone, WARNING);
     755          38 : }

Generated by: LCOV version 1.13