LCOV - differential code coverage report
Current view: top level - src/backend/postmaster - pgarch.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 81.7 % 219 179 4 9 21 6 7 117 16 39 26 127 1 4
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 17 17 17 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, 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 <time.h>
      29                 : #include <sys/stat.h>
      30                 : #include <unistd.h>
      31                 : 
      32                 : #include "access/xlog.h"
      33                 : #include "access/xlog_internal.h"
      34                 : #include "archive/archive_module.h"
      35                 : #include "archive/shell_archive.h"
      36                 : #include "lib/binaryheap.h"
      37                 : #include "libpq/pqsignal.h"
      38                 : #include "pgstat.h"
      39                 : #include "postmaster/interrupt.h"
      40                 : #include "postmaster/pgarch.h"
      41                 : #include "storage/fd.h"
      42                 : #include "storage/ipc.h"
      43                 : #include "storage/latch.h"
      44                 : #include "storage/pmsignal.h"
      45                 : #include "storage/proc.h"
      46                 : #include "storage/procsignal.h"
      47                 : #include "storage/shmem.h"
      48                 : #include "storage/spin.h"
      49                 : #include "utils/guc.h"
      50                 : #include "utils/memutils.h"
      51                 : #include "utils/ps_status.h"
      52                 : 
      53                 : 
      54                 : /* ----------
      55                 :  * Timer definitions.
      56                 :  * ----------
      57                 :  */
      58                 : #define PGARCH_AUTOWAKE_INTERVAL 60 /* How often to force a poll of the
      59                 :                                      * archive status directory; in seconds. */
      60                 : #define PGARCH_RESTART_INTERVAL 10  /* How often to attempt to restart a
      61                 :                                      * failed archiver; in seconds. */
      62                 : 
      63                 : /*
      64                 :  * Maximum number of retries allowed when attempting to archive a WAL
      65                 :  * file.
      66                 :  */
      67                 : #define NUM_ARCHIVE_RETRIES 3
      68                 : 
      69                 : /*
      70                 :  * Maximum number of retries allowed when attempting to remove an
      71                 :  * orphan archive status file.
      72                 :  */
      73                 : #define NUM_ORPHAN_CLEANUP_RETRIES 3
      74                 : 
      75                 : /*
      76                 :  * Maximum number of .ready files to gather per directory scan.
      77                 :  */
      78                 : #define NUM_FILES_PER_DIRECTORY_SCAN 64
      79                 : 
      80                 : /* Shared memory area for archiver process */
      81                 : typedef struct PgArchData
      82                 : {
      83                 :     int         pgprocno;       /* pgprocno of archiver process */
      84                 : 
      85                 :     /*
      86                 :      * Forces a directory scan in pgarch_readyXlog().  Protected by arch_lck.
      87                 :      */
      88                 :     bool        force_dir_scan;
      89                 : 
      90                 :     slock_t     arch_lck;
      91                 : } PgArchData;
      92                 : 
      93                 : char       *XLogArchiveLibrary = "";
      94                 : 
      95                 : 
      96                 : /* ----------
      97                 :  * Local data
      98                 :  * ----------
      99                 :  */
     100                 : static time_t last_sigterm_time = 0;
     101                 : static PgArchData *PgArch = NULL;
     102                 : static const ArchiveModuleCallbacks *ArchiveCallbacks;
     103                 : static ArchiveModuleState *archive_module_state;
     104                 : 
     105                 : 
     106                 : /*
     107                 :  * Stuff for tracking multiple files to archive from each scan of
     108                 :  * archive_status.  Minimizing the number of directory scans when there are
     109                 :  * many files to archive can significantly improve archival rate.
     110                 :  *
     111                 :  * arch_heap is a max-heap that is used during the directory scan to track
     112                 :  * the highest-priority files to archive.  After the directory scan
     113                 :  * completes, the file names are stored in ascending order of priority in
     114                 :  * arch_files.  pgarch_readyXlog() returns files from arch_files until it
     115                 :  * is empty, at which point another directory scan must be performed.
     116                 :  *
     117                 :  * We only need this data in the archiver process, so make it a palloc'd
     118                 :  * struct rather than a bunch of static arrays.
     119                 :  */
     120                 : struct arch_files_state
     121                 : {
     122                 :     binaryheap *arch_heap;
     123                 :     int         arch_files_size;    /* number of live entries in arch_files[] */
     124                 :     char       *arch_files[NUM_FILES_PER_DIRECTORY_SCAN];
     125                 :     /* buffers underlying heap, and later arch_files[], entries: */
     126                 :     char        arch_filenames[NUM_FILES_PER_DIRECTORY_SCAN][MAX_XFN_CHARS + 1];
     127                 : };
     128                 : 
     129                 : static struct arch_files_state *arch_files = NULL;
     130                 : 
     131                 : /*
     132                 :  * Flags set by interrupt handlers for later service in the main loop.
     133                 :  */
     134                 : static volatile sig_atomic_t ready_to_stop = false;
     135                 : 
     136                 : /* ----------
     137                 :  * Local function forward declarations
     138                 :  * ----------
     139                 :  */
     140                 : static void pgarch_waken_stop(SIGNAL_ARGS);
     141                 : static void pgarch_MainLoop(void);
     142                 : static void pgarch_ArchiverCopyLoop(void);
     143                 : static bool pgarch_archiveXlog(char *xlog);
     144                 : static bool pgarch_readyXlog(char *xlog);
     145                 : static void pgarch_archiveDone(char *xlog);
     146                 : static void pgarch_die(int code, Datum arg);
     147                 : static void HandlePgArchInterrupts(void);
     148                 : static int  ready_file_comparator(Datum a, Datum b, void *arg);
     149                 : static void LoadArchiveLibrary(void);
     150                 : static void pgarch_call_module_shutdown_cb(int code, Datum arg);
     151                 : 
     152                 : /* Report shared memory space needed by PgArchShmemInit */
     153                 : Size
     154 GIC        6390 : PgArchShmemSize(void)
     155                 : {
     156            6390 :     Size        size = 0;
     157 ECB             : 
     158 GIC        6390 :     size = add_size(size, sizeof(PgArchData));
     159 ECB             : 
     160 GIC        6390 :     return size;
     161 ECB             : }
     162                 : 
     163                 : /* Allocate and initialize archiver-related shared memory */
     164                 : void
     165 GIC        1826 : PgArchShmemInit(void)
     166                 : {
     167                 :     bool        found;
     168 ECB             : 
     169 GIC        1826 :     PgArch = (PgArchData *)
     170            1826 :         ShmemInitStruct("Archiver Data", PgArchShmemSize(), &found);
     171                 : 
     172 CBC        1826 :     if (!found)
     173 ECB             :     {
     174                 :         /* First time through, so initialize */
     175 CBC        3652 :         MemSet(PgArch, 0, PgArchShmemSize());
     176 GIC        1826 :         PgArch->pgprocno = INVALID_PGPROCNO;
     177            1826 :         SpinLockInit(&PgArch->arch_lck);
     178 ECB             :     }
     179 CBC        1826 : }
     180 ECB             : 
     181                 : /*
     182                 :  * PgArchCanRestart
     183                 :  *
     184                 :  * Return true and archiver is allowed to restart if enough time has
     185                 :  * passed since it was launched last to reach PGARCH_RESTART_INTERVAL.
     186                 :  * Otherwise return false.
     187                 :  *
     188                 :  * This is a safety valve to protect against continuous respawn attempts if the
     189                 :  * archiver is dying immediately at launch. Note that since we will retry to
     190                 :  * launch the archiver from the postmaster main loop, we will get another
     191                 :  * chance later.
     192                 :  */
     193                 : bool
     194 GIC          28 : PgArchCanRestart(void)
     195                 : {
     196                 :     static time_t last_pgarch_start_time = 0;
     197 CBC          28 :     time_t      curtime = time(NULL);
     198                 : 
     199                 :     /*
     200 ECB             :      * Return false and don't restart archiver if too soon since last archiver
     201                 :      * start.
     202                 :      */
     203 GIC          28 :     if ((unsigned int) (curtime - last_pgarch_start_time) <
     204                 :         (unsigned int) PGARCH_RESTART_INTERVAL)
     205 UIC           0 :         return false;
     206 ECB             : 
     207 GIC          28 :     last_pgarch_start_time = curtime;
     208 GBC          28 :     return true;
     209                 : }
     210 ECB             : 
     211                 : 
     212                 : /* Main entry point for archiver process */
     213                 : void
     214 GIC          10 : PgArchiverMain(void)
     215                 : {
     216                 :     /*
     217 ECB             :      * Ignore all signals usually bound to some action in the postmaster,
     218                 :      * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
     219                 :      */
     220 GIC          10 :     pqsignal(SIGHUP, SignalHandlerForConfigReload);
     221              10 :     pqsignal(SIGINT, SIG_IGN);
     222              10 :     pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
     223 ECB             :     /* SIGQUIT handler was already set up by InitPostmasterChild */
     224 CBC          10 :     pqsignal(SIGALRM, SIG_IGN);
     225              10 :     pqsignal(SIGPIPE, SIG_IGN);
     226 GIC          10 :     pqsignal(SIGUSR1, procsignal_sigusr1_handler);
     227 CBC          10 :     pqsignal(SIGUSR2, pgarch_waken_stop);
     228 ECB             : 
     229                 :     /* Reset some signals that are accepted by postmaster but not here */
     230 CBC          10 :     pqsignal(SIGCHLD, SIG_DFL);
     231                 : 
     232                 :     /* Unblock signals (they were blocked when the postmaster forked us) */
     233 GNC          10 :     sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
     234                 : 
     235                 :     /* We shouldn't be launched unnecessarily. */
     236 CBC          10 :     Assert(XLogArchivingActive());
     237                 : 
     238                 :     /* Arrange to clean up at archiver exit */
     239              10 :     on_shmem_exit(pgarch_die, 0);
     240                 : 
     241                 :     /*
     242 ECB             :      * Advertise our pgprocno so that backends can use our latch to wake us up
     243                 :      * while we're sleeping.
     244                 :      */
     245 GIC          10 :     PgArch->pgprocno = MyProc->pgprocno;
     246                 : 
     247                 :     /* Create workspace for pgarch_readyXlog() */
     248 CBC          10 :     arch_files = palloc(sizeof(struct arch_files_state));
     249 GIC          10 :     arch_files->arch_files_size = 0;
     250                 : 
     251 ECB             :     /* Initialize our max-heap for prioritizing files to archive. */
     252 CBC          10 :     arch_files->arch_heap = binaryheap_allocate(NUM_FILES_PER_DIRECTORY_SCAN,
     253                 :                                                 ready_file_comparator, NULL);
     254                 : 
     255 ECB             :     /* Load the archive_library. */
     256 GIC          10 :     LoadArchiveLibrary();
     257                 : 
     258              10 :     pgarch_MainLoop();
     259 ECB             : 
     260 GIC          10 :     proc_exit(0);
     261 ECB             : }
     262                 : 
     263                 : /*
     264                 :  * Wake up the archiver
     265                 :  */
     266                 : void
     267 GIC          59 : PgArchWakeup(void)
     268                 : {
     269              59 :     int         arch_pgprocno = PgArch->pgprocno;
     270 ECB             : 
     271                 :     /*
     272                 :      * We don't acquire ProcArrayLock here.  It's actually fine because
     273                 :      * procLatch isn't ever freed, so we just can potentially set the wrong
     274                 :      * process' (or no process') latch.  Even in that case the archiver will
     275                 :      * be relaunched shortly and will start archiving.
     276                 :      */
     277 GIC          59 :     if (arch_pgprocno != INVALID_PGPROCNO)
     278              46 :         SetLatch(&ProcGlobal->allProcs[arch_pgprocno].procLatch);
     279              59 : }
     280 ECB             : 
     281                 : 
     282                 : /* SIGUSR2 signal handler for archiver process */
     283                 : static void
     284 GIC          10 : pgarch_waken_stop(SIGNAL_ARGS)
     285                 : {
     286              10 :     int         save_errno = errno;
     287 ECB             : 
     288                 :     /* set flag to do a final cycle and shut down afterwards */
     289 CBC          10 :     ready_to_stop = true;
     290 GIC          10 :     SetLatch(MyLatch);
     291                 : 
     292 CBC          10 :     errno = save_errno;
     293              10 : }
     294                 : 
     295 ECB             : /*
     296                 :  * pgarch_MainLoop
     297                 :  *
     298                 :  * Main loop for archiver
     299                 :  */
     300                 : static void
     301 GIC          10 : pgarch_MainLoop(void)
     302                 : {
     303 ECB             :     bool        time_to_stop;
     304                 : 
     305                 :     /*
     306                 :      * There shouldn't be anything for the archiver to do except to wait for a
     307                 :      * signal ... however, the archiver exists to protect our data, so it
     308                 :      * wakes up occasionally to allow itself to be proactive.
     309                 :      */
     310                 :     do
     311                 :     {
     312 GIC          43 :         ResetLatch(MyLatch);
     313                 : 
     314 ECB             :         /* When we get SIGUSR2, we do one more archive cycle, then exit */
     315 GIC          43 :         time_to_stop = ready_to_stop;
     316                 : 
     317 ECB             :         /* Check for barrier events and config update */
     318 GIC          43 :         HandlePgArchInterrupts();
     319                 : 
     320 ECB             :         /*
     321                 :          * If we've gotten SIGTERM, we normally just sit and do nothing until
     322                 :          * SIGUSR2 arrives.  However, that means a random SIGTERM would
     323                 :          * disable archiving indefinitely, which doesn't seem like a good
     324                 :          * idea.  If more than 60 seconds pass since SIGTERM, exit anyway, so
     325                 :          * that the postmaster can start a new archiver if needed.
     326                 :          */
     327 GIC          43 :         if (ShutdownRequestPending)
     328                 :         {
     329 LBC           0 :             time_t      curtime = time(NULL);
     330                 : 
     331 UBC           0 :             if (last_sigterm_time == 0)
     332 UIC           0 :                 last_sigterm_time = curtime;
     333 UBC           0 :             else if ((unsigned int) (curtime - last_sigterm_time) >=
     334 EUB             :                      (unsigned int) 60)
     335 UBC           0 :                 break;
     336                 :         }
     337 EUB             : 
     338                 :         /* Do what we're here for */
     339 GIC          43 :         pgarch_ArchiverCopyLoop();
     340 ECB             : 
     341                 :         /*
     342                 :          * Sleep until a signal is received, or until a poll is forced by
     343                 :          * PGARCH_AUTOWAKE_INTERVAL, or until postmaster dies.
     344                 :          */
     345 CBC          43 :         if (!time_to_stop)      /* Don't wait during last iteration */
     346                 :         {
     347                 :             int         rc;
     348 ECB             : 
     349 GNC          33 :             rc = WaitLatch(MyLatch,
     350                 :                            WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
     351                 :                            PGARCH_AUTOWAKE_INTERVAL * 1000L,
     352                 :                            WAIT_EVENT_ARCHIVER_MAIN);
     353              33 :             if (rc & WL_POSTMASTER_DEATH)
     354 UNC           0 :                 time_to_stop = true;
     355 ECB             :         }
     356                 : 
     357                 :         /*
     358                 :          * The archiver quits either when the postmaster dies (not expected)
     359                 :          * or after completing one more archiving cycle after receiving
     360                 :          * SIGUSR2.
     361                 :          */
     362 GIC          43 :     } while (!time_to_stop);
     363              10 : }
     364 ECB             : 
     365                 : /*
     366                 :  * pgarch_ArchiverCopyLoop
     367                 :  *
     368                 :  * Archives all outstanding xlogs then returns
     369                 :  */
     370                 : static void
     371 GIC          43 : pgarch_ArchiverCopyLoop(void)
     372                 : {
     373                 :     char        xlog[MAX_XFN_CHARS + 1];
     374                 : 
     375                 :     /* force directory scan in the first call to pgarch_readyXlog() */
     376              43 :     arch_files->arch_files_size = 0;
     377 ECB             : 
     378                 :     /*
     379                 :      * loop through all xlogs with archive_status of .ready and archive
     380                 :      * them...mostly we expect this to be a single file, though it is possible
     381                 :      * some backend will add files onto the list of those that need archiving
     382                 :      * while we are still copying earlier archives
     383                 :      */
     384 GIC          67 :     while (pgarch_readyXlog(xlog))
     385                 :     {
     386              24 :         int         failures = 0;
     387              24 :         int         failures_orphan = 0;
     388                 : 
     389                 :         for (;;)
     390               1 :         {
     391                 :             struct stat stat_buf;
     392                 :             char        pathname[MAXPGPATH];
     393                 : 
     394 ECB             :             /*
     395 EUB             :              * Do not initiate any more archive commands after receiving
     396                 :              * SIGTERM, nor after the postmaster has died unexpectedly. The
     397                 :              * first condition is to try to keep from having init SIGKILL the
     398                 :              * command, and the second is to avoid conflicts with another
     399                 :              * archiver spawned by a newer postmaster.
     400                 :              */
     401 GIC          25 :             if (ShutdownRequestPending || !PostmasterIsAlive())
     402 LBC           0 :                 return;
     403                 : 
     404                 :             /*
     405 ECB             :              * Check for barrier events and config update.  This is so that
     406                 :              * we'll adopt a new setting for archive_command as soon as
     407                 :              * possible, even if there is a backlog of files to be archived.
     408 EUB             :              */
     409 GIC          25 :             HandlePgArchInterrupts();
     410 EUB             : 
     411                 :             /* can't do anything if not configured ... */
     412 GNC          25 :             if (ArchiveCallbacks->check_configured_cb != NULL &&
     413              25 :                 !ArchiveCallbacks->check_configured_cb(archive_module_state))
     414                 :             {
     415 UIC           0 :                 ereport(WARNING,
     416                 :                         (errmsg("archive_mode enabled, yet archiving is not configured")));
     417               0 :                 return;
     418                 :             }
     419                 : 
     420                 :             /*
     421                 :              * Since archive status files are not removed in a durable manner,
     422 ECB             :              * a system crash could leave behind .ready files for WAL segments
     423                 :              * that have already been recycled or removed.  In this case,
     424 EUB             :              * simply remove the orphan status file and move on.  unlink() is
     425                 :              * used here as even on subsequent crashes the same orphan files
     426                 :              * would get removed, so there is no need to worry about
     427                 :              * durability.
     428                 :              */
     429 GIC          25 :             snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
     430 GBC          25 :             if (stat(pathname, &stat_buf) != 0 && errno == ENOENT)
     431 UIC           0 :             {
     432                 :                 char        xlogready[MAXPGPATH];
     433                 : 
     434               0 :                 StatusFilePath(xlogready, xlog, ".ready");
     435 UBC           0 :                 if (unlink(xlogready) == 0)
     436                 :                 {
     437 UIC           0 :                     ereport(WARNING,
     438 EUB             :                             (errmsg("removed orphan archive status file \"%s\"",
     439                 :                                     xlogready)));
     440                 : 
     441                 :                     /* leave loop and move to the next status file */
     442 UIC           0 :                     break;
     443                 :                 }
     444                 : 
     445 UBC           0 :                 if (++failures_orphan >= NUM_ORPHAN_CLEANUP_RETRIES)
     446                 :                 {
     447 UIC           0 :                     ereport(WARNING,
     448                 :                             (errmsg("removal of orphan archive status file \"%s\" failed too many times, will try again later",
     449 EUB             :                                     xlogready)));
     450                 : 
     451                 :                     /* give up cleanup of orphan status files */
     452 UIC           0 :                     return;
     453 ECB             :                 }
     454                 : 
     455                 :                 /* wait a bit before retrying */
     456 LBC           0 :                 pg_usleep(1000000L);
     457 UIC           0 :                 continue;
     458                 :             }
     459                 : 
     460 GIC          25 :             if (pgarch_archiveXlog(xlog))
     461                 :             {
     462 ECB             :                 /* successful */
     463 GIC          24 :                 pgarch_archiveDone(xlog);
     464 ECB             : 
     465                 :                 /*
     466                 :                  * Tell the cumulative stats system about the WAL file that we
     467                 :                  * successfully archived
     468                 :                  */
     469 GIC          24 :                 pgstat_report_archiver(xlog, false);
     470                 : 
     471              24 :                 break;          /* out of inner retry loop */
     472 ECB             :             }
     473                 :             else
     474                 :             {
     475                 :                 /*
     476 EUB             :                  * Tell the cumulative stats system about the WAL file that we
     477                 :                  * failed to archive
     478                 :                  */
     479 GBC           1 :                 pgstat_report_archiver(xlog, true);
     480                 : 
     481 CBC           1 :                 if (++failures >= NUM_ARCHIVE_RETRIES)
     482                 :                 {
     483 UIC           0 :                     ereport(WARNING,
     484                 :                             (errmsg("archiving write-ahead log file \"%s\" failed too many times, will try again later",
     485                 :                                     xlog)));
     486               0 :                     return;     /* give up archiving for now */
     487                 :                 }
     488 GIC           1 :                 pg_usleep(1000000L);    /* wait a bit before retrying */
     489                 :             }
     490                 :         }
     491                 :     }
     492                 : }
     493                 : 
     494                 : /*
     495 ECB             :  * pgarch_archiveXlog
     496                 :  *
     497                 :  * Invokes archive_file_cb to copy one archive file to wherever it should go
     498                 :  *
     499                 :  * Returns true if successful
     500                 :  */
     501                 : static bool
     502 GIC          25 : pgarch_archiveXlog(char *xlog)
     503                 : {
     504 ECB             :     char        pathname[MAXPGPATH];
     505                 :     char        activitymsg[MAXFNAMELEN + 16];
     506                 :     bool        ret;
     507                 : 
     508 CBC          25 :     snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
     509 ECB             : 
     510                 :     /* Report archive activity in PS display */
     511 CBC          25 :     snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
     512              25 :     set_ps_display(activitymsg);
     513                 : 
     514 GNC          25 :     ret = ArchiveCallbacks->archive_file_cb(archive_module_state, xlog, pathname);
     515 GIC          25 :     if (ret)
     516              24 :         snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
     517                 :     else
     518               1 :         snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
     519              25 :     set_ps_display(activitymsg);
     520                 : 
     521              25 :     return ret;
     522                 : }
     523                 : 
     524                 : /*
     525                 :  * pgarch_readyXlog
     526                 :  *
     527                 :  * Return name of the oldest xlog file that has not yet been archived.
     528                 :  * No notification is set that file archiving is now in progress, so
     529                 :  * this would need to be extended if multiple concurrent archival
     530                 :  * tasks were created. If a failure occurs, we will completely
     531                 :  * re-copy the file at the next available opportunity.
     532                 :  *
     533                 :  * It is important that we return the oldest, so that we archive xlogs
     534                 :  * in order that they were written, for two reasons:
     535                 :  * 1) to maintain the sequential chain of xlogs required for recovery
     536                 :  * 2) because the oldest ones will sooner become candidates for
     537                 :  * recycling at time of checkpoint
     538                 :  *
     539                 :  * NOTE: the "oldest" comparison will consider any .history file to be older
     540 ECB             :  * than any other file except another .history file.  Segments on a timeline
     541                 :  * with a smaller ID will be older than all segments on a timeline with a
     542                 :  * larger ID; the net result being that past timelines are given higher
     543                 :  * priority for archiving.  This seems okay, or at least not obviously worth
     544                 :  * changing.
     545                 :  */
     546                 : static bool
     547 GIC          67 : pgarch_readyXlog(char *xlog)
     548                 : {
     549                 :     char        XLogArchiveStatusDir[MAXPGPATH];
     550                 :     DIR        *rldir;
     551 ECB             :     struct dirent *rlde;
     552                 :     bool        force_dir_scan;
     553                 : 
     554                 :     /*
     555                 :      * If a directory scan was requested, clear the stored file names and
     556                 :      * proceed.
     557                 :      */
     558 GIC          67 :     SpinLockAcquire(&PgArch->arch_lck);
     559              67 :     force_dir_scan = PgArch->force_dir_scan;
     560              67 :     PgArch->force_dir_scan = false;
     561              67 :     SpinLockRelease(&PgArch->arch_lck);
     562                 : 
     563              67 :     if (force_dir_scan)
     564               2 :         arch_files->arch_files_size = 0;
     565 ECB             : 
     566                 :     /*
     567                 :      * If we still have stored file names from the previous directory scan,
     568                 :      * try to return one of those.  We check to make sure the status file is
     569                 :      * still present, as the archive_command for a previous file may have
     570                 :      * already marked it done.
     571                 :      */
     572 CBC          67 :     while (arch_files->arch_files_size > 0)
     573 ECB             :     {
     574                 :         struct stat st;
     575                 :         char        status_file[MAXPGPATH];
     576                 :         char       *arch_file;
     577                 : 
     578 CBC           1 :         arch_files->arch_files_size--;
     579 GIC           1 :         arch_file = arch_files->arch_files[arch_files->arch_files_size];
     580 GBC           1 :         StatusFilePath(status_file, arch_file, ".ready");
     581 EUB             : 
     582 GIC           1 :         if (stat(status_file, &st) == 0)
     583                 :         {
     584               1 :             strcpy(xlog, arch_file);
     585               1 :             return true;
     586                 :         }
     587 LBC           0 :         else if (errno != ENOENT)
     588 UIC           0 :             ereport(ERROR,
     589                 :                     (errcode_for_file_access(),
     590                 :                      errmsg("could not stat file \"%s\": %m", status_file)));
     591                 :     }
     592                 : 
     593 ECB             :     /* arch_heap is probably empty, but let's make sure */
     594 CBC          66 :     binaryheap_reset(arch_files->arch_heap);
     595                 : 
     596 ECB             :     /*
     597                 :      * Open the archive status directory and read through the list of files
     598                 :      * with the .ready suffix, looking for the earliest files.
     599                 :      */
     600 GIC          66 :     snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
     601              66 :     rldir = AllocateDir(XLogArchiveStatusDir);
     602                 : 
     603 CBC         327 :     while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
     604                 :     {
     605             261 :         int         basenamelen = (int) strlen(rlde->d_name) - 6;
     606                 :         char        basename[MAX_XFN_CHARS + 1];
     607                 :         char       *arch_file;
     608 ECB             : 
     609 EUB             :         /* Ignore entries with unexpected number of characters */
     610 GIC         261 :         if (basenamelen < MIN_XFN_CHARS ||
     611                 :             basenamelen > MAX_XFN_CHARS)
     612 CBC         237 :             continue;
     613 ECB             : 
     614                 :         /* Ignore entries with unexpected characters */
     615 GIC         110 :         if (strspn(rlde->d_name, VALID_XFN_CHARS) < basenamelen)
     616 LBC           0 :             continue;
     617 ECB             : 
     618                 :         /* Ignore anything not suffixed with .ready */
     619 GIC         110 :         if (strcmp(rlde->d_name + basenamelen, ".ready") != 0)
     620              86 :             continue;
     621                 : 
     622 ECB             :         /* Truncate off the .ready */
     623 GIC          24 :         memcpy(basename, rlde->d_name, basenamelen);
     624              24 :         basename[basenamelen] = '\0';
     625 ECB             : 
     626                 :         /*
     627                 :          * Store the file in our max-heap if it has a high enough priority.
     628                 :          */
     629 GIC          24 :         if (arch_files->arch_heap->bh_size < NUM_FILES_PER_DIRECTORY_SCAN)
     630 ECB             :         {
     631 EUB             :             /* If the heap isn't full yet, quickly add it. */
     632 GIC          24 :             arch_file = arch_files->arch_filenames[arch_files->arch_heap->bh_size];
     633 GBC          24 :             strcpy(arch_file, basename);
     634 GIC          24 :             binaryheap_add_unordered(arch_files->arch_heap, CStringGetDatum(arch_file));
     635                 : 
     636                 :             /* If we just filled the heap, make it a valid one. */
     637              24 :             if (arch_files->arch_heap->bh_size == NUM_FILES_PER_DIRECTORY_SCAN)
     638 UIC           0 :                 binaryheap_build(arch_files->arch_heap);
     639                 :         }
     640 UBC           0 :         else if (ready_file_comparator(binaryheap_first(arch_files->arch_heap),
     641 EUB             :                                        CStringGetDatum(basename), NULL) > 0)
     642                 :         {
     643                 :             /*
     644                 :              * Remove the lowest priority file and add the current one to the
     645 ECB             :              * heap.
     646                 :              */
     647 UIC           0 :             arch_file = DatumGetCString(binaryheap_remove_first(arch_files->arch_heap));
     648 LBC           0 :             strcpy(arch_file, basename);
     649               0 :             binaryheap_add(arch_files->arch_heap, CStringGetDatum(arch_file));
     650                 :         }
     651                 :     }
     652 GIC          66 :     FreeDir(rldir);
     653                 : 
     654                 :     /* If no files were found, simply return. */
     655 CBC          66 :     if (arch_files->arch_heap->bh_size == 0)
     656              43 :         return false;
     657                 : 
     658                 :     /*
     659                 :      * If we didn't fill the heap, we didn't make it a valid one.  Do that
     660                 :      * now.
     661                 :      */
     662              23 :     if (arch_files->arch_heap->bh_size < NUM_FILES_PER_DIRECTORY_SCAN)
     663              23 :         binaryheap_build(arch_files->arch_heap);
     664 ECB             : 
     665                 :     /*
     666                 :      * Fill arch_files array with the files to archive in ascending order of
     667                 :      * priority.
     668                 :      */
     669 GIC          23 :     arch_files->arch_files_size = arch_files->arch_heap->bh_size;
     670 CBC          47 :     for (int i = 0; i < arch_files->arch_files_size; i++)
     671 GIC          24 :         arch_files->arch_files[i] = DatumGetCString(binaryheap_remove_first(arch_files->arch_heap));
     672                 : 
     673                 :     /* Return the highest priority file. */
     674              23 :     arch_files->arch_files_size--;
     675              23 :     strcpy(xlog, arch_files->arch_files[arch_files->arch_files_size]);
     676                 : 
     677              23 :     return true;
     678                 : }
     679                 : 
     680                 : /*
     681                 :  * ready_file_comparator
     682 ECB             :  *
     683                 :  * Compares the archival priority of the given files to archive.  If "a"
     684                 :  * has a higher priority than "b", a negative value will be returned.  If
     685                 :  * "b" has a higher priority than "a", a positive value will be returned.
     686                 :  * If "a" and "b" have equivalent values, 0 will be returned.
     687                 :  */
     688                 : static int
     689 GIC           1 : ready_file_comparator(Datum a, Datum b, void *arg)
     690 ECB             : {
     691 GBC           1 :     char       *a_str = DatumGetCString(a);
     692 GIC           1 :     char       *b_str = DatumGetCString(b);
     693               1 :     bool        a_history = IsTLHistoryFileName(a_str);
     694 CBC           1 :     bool        b_history = IsTLHistoryFileName(b_str);
     695                 : 
     696                 :     /* Timeline history files always have the highest priority. */
     697 GIC           1 :     if (a_history != b_history)
     698 UIC           0 :         return a_history ? -1 : 1;
     699                 : 
     700                 :     /* Priority is given to older files. */
     701 GIC           1 :     return strcmp(a_str, b_str);
     702                 : }
     703                 : 
     704                 : /*
     705 ECB             :  * PgArchForceDirScan
     706                 :  *
     707                 :  * When called, the next call to pgarch_readyXlog() will perform a
     708                 :  * directory scan.  This is useful for ensuring that important files such
     709                 :  * as timeline history files are archived as quickly as possible.
     710                 :  */
     711                 : void
     712 GIC          10 : PgArchForceDirScan(void)
     713                 : {
     714              10 :     SpinLockAcquire(&PgArch->arch_lck);
     715              10 :     PgArch->force_dir_scan = true;
     716              10 :     SpinLockRelease(&PgArch->arch_lck);
     717              10 : }
     718                 : 
     719                 : /*
     720                 :  * pgarch_archiveDone
     721 ECB             :  *
     722                 :  * Emit notification that an xlog file has been successfully archived.
     723                 :  * We do this by renaming the status file from NNN.ready to NNN.done.
     724                 :  * Eventually, a checkpoint process will notice this and delete both the
     725                 :  * NNN.done file and the xlog file itself.
     726                 :  */
     727                 : static void
     728 GIC          24 : pgarch_archiveDone(char *xlog)
     729                 : {
     730                 :     char        rlogready[MAXPGPATH];
     731                 :     char        rlogdone[MAXPGPATH];
     732                 : 
     733              24 :     StatusFilePath(rlogready, xlog, ".ready");
     734              24 :     StatusFilePath(rlogdone, xlog, ".done");
     735                 : 
     736                 :     /*
     737                 :      * To avoid extra overhead, we don't durably rename the .ready file to
     738                 :      * .done.  Archive commands and libraries must gracefully handle attempts
     739                 :      * to re-archive files (e.g., if the server crashes just before this
     740                 :      * function is called), so it should be okay if the .ready file reappears
     741                 :      * after a crash.
     742                 :      */
     743 GNC          24 :     if (rename(rlogready, rlogdone) < 0)
     744 UNC           0 :         ereport(WARNING,
     745                 :                 (errcode_for_file_access(),
     746                 :                  errmsg("could not rename file \"%s\" to \"%s\": %m",
     747                 :                         rlogready, rlogdone)));
     748 CBC          24 : }
     749 EUB             : 
     750                 : 
     751                 : /*
     752                 :  * pgarch_die
     753 ECB             :  *
     754                 :  * Exit-time cleanup handler
     755                 :  */
     756                 : static void
     757 GIC          10 : pgarch_die(int code, Datum arg)
     758                 : {
     759              10 :     PgArch->pgprocno = INVALID_PGPROCNO;
     760              10 : }
     761                 : 
     762 ECB             : /*
     763                 :  * Interrupt handler for WAL archiver process.
     764                 :  *
     765                 :  * This is called in the loops pgarch_MainLoop and pgarch_ArchiverCopyLoop.
     766                 :  * It checks for barrier events, config update and request for logging of
     767                 :  * memory contexts, but not shutdown request because how to handle
     768                 :  * shutdown request is different between those loops.
     769                 :  */
     770                 : static void
     771 GIC          68 : HandlePgArchInterrupts(void)
     772                 : {
     773              68 :     if (ProcSignalBarrierPending)
     774 UIC           0 :         ProcessProcSignalBarrier();
     775                 : 
     776 ECB             :     /* Perform logging of memory contexts of this process */
     777 GIC          68 :     if (LogMemoryContextPending)
     778 LBC           0 :         ProcessLogMemoryContextInterrupt();
     779 EUB             : 
     780 GIC          68 :     if (ConfigReloadPending)
     781                 :     {
     782 CBC           2 :         char       *archiveLib = pstrdup(XLogArchiveLibrary);
     783 EUB             :         bool        archiveLibChanged;
     784                 : 
     785 CBC           2 :         ConfigReloadPending = false;
     786 GIC           2 :         ProcessConfigFile(PGC_SIGHUP);
     787 ECB             : 
     788 GNC           2 :         if (XLogArchiveLibrary[0] != '\0' && XLogArchiveCommand[0] != '\0')
     789 UNC           0 :             ereport(ERROR,
     790                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     791                 :                      errmsg("both archive_command and archive_library set"),
     792                 :                      errdetail("Only one of archive_command, archive_library may be set.")));
     793                 : 
     794 GIC           2 :         archiveLibChanged = strcmp(XLogArchiveLibrary, archiveLib) != 0;
     795               2 :         pfree(archiveLib);
     796 ECB             : 
     797 CBC           2 :         if (archiveLibChanged)
     798                 :         {
     799 ECB             :             /*
     800 EUB             :              * Ideally, we would simply unload the previous archive module and
     801                 :              * load the new one, but there is presently no mechanism for
     802                 :              * unloading a library (see the comment above
     803                 :              * internal_load_library()).  To deal with this, we simply restart
     804                 :              * the archiver.  The new archive module will be loaded when the
     805 ECB             :              * new archiver process starts up.  Note that this triggers the
     806                 :              * module's shutdown callback, if defined.
     807                 :              */
     808 LBC           0 :             ereport(LOG,
     809                 :                     (errmsg("restarting archiver process because value of "
     810                 :                             "\"archive_library\" was changed")));
     811                 : 
     812 UIC           0 :             proc_exit(0);
     813                 :         }
     814                 :     }
     815 GIC          68 : }
     816                 : 
     817                 : /*
     818                 :  * LoadArchiveLibrary
     819 EUB             :  *
     820                 :  * Loads the archiving callbacks into our local ArchiveCallbacks.
     821                 :  */
     822                 : static void
     823 GBC          10 : LoadArchiveLibrary(void)
     824                 : {
     825                 :     ArchiveModuleInit archive_init;
     826 ECB             : 
     827 GNC          10 :     if (XLogArchiveLibrary[0] != '\0' && XLogArchiveCommand[0] != '\0')
     828 UNC           0 :         ereport(ERROR,
     829                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     830                 :                  errmsg("both archive_command and archive_library set"),
     831                 :                  errdetail("Only one of archive_command, archive_library may be set.")));
     832                 : 
     833                 :     /*
     834                 :      * If shell archiving is enabled, use our special initialization function.
     835                 :      * Otherwise, load the library and call its _PG_archive_module_init().
     836                 :      */
     837 GIC          10 :     if (XLogArchiveLibrary[0] == '\0')
     838 CBC           9 :         archive_init = shell_archive_init;
     839                 :     else
     840 GIC           1 :         archive_init = (ArchiveModuleInit)
     841               1 :             load_external_function(XLogArchiveLibrary,
     842 ECB             :                                    "_PG_archive_module_init", false, NULL);
     843 EUB             : 
     844 GIC          10 :     if (archive_init == NULL)
     845 UIC           0 :         ereport(ERROR,
     846                 :                 (errmsg("archive modules have to define the symbol %s", "_PG_archive_module_init")));
     847                 : 
     848 GNC          10 :     ArchiveCallbacks = (*archive_init) ();
     849                 : 
     850              10 :     if (ArchiveCallbacks->archive_file_cb == NULL)
     851 UIC           0 :         ereport(ERROR,
     852 ECB             :                 (errmsg("archive modules must register an archive callback")));
     853                 : 
     854 GNC          10 :     archive_module_state = (ArchiveModuleState *) palloc0(sizeof(ArchiveModuleState));
     855              10 :     if (ArchiveCallbacks->startup_cb != NULL)
     856               1 :         ArchiveCallbacks->startup_cb(archive_module_state);
     857                 : 
     858 GIC          10 :     before_shmem_exit(pgarch_call_module_shutdown_cb, 0);
     859 CBC          10 : }
     860 ECB             : 
     861                 : /*
     862                 :  * Call the shutdown callback of the loaded archive module, if defined.
     863                 :  */
     864 EUB             : static void
     865 GIC          10 : pgarch_call_module_shutdown_cb(int code, Datum arg)
     866                 : {
     867 GNC          10 :     if (ArchiveCallbacks->shutdown_cb != NULL)
     868              10 :         ArchiveCallbacks->shutdown_cb(archive_module_state);
     869 CBC          10 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a