LCOV - differential code coverage report
Current view: top level - src/backend/archive - shell_archive.c (source / functions) Coverage Total Hit UIC GBC GIC GNC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 90.3 % 31 28 3 1 13 14 2 12 16
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 4 4 4 4
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * shell_archive.c
       4                 :  *
       5                 :  * This archiving function uses a user-specified shell command (the
       6                 :  * archive_command GUC) to copy write-ahead log files.  It is used as the
       7                 :  * default, but other modules may define their own custom archiving logic.
       8                 :  *
       9                 :  * Copyright (c) 2022-2023, PostgreSQL Global Development Group
      10                 :  *
      11                 :  * IDENTIFICATION
      12                 :  *    src/backend/archive/shell_archive.c
      13                 :  *
      14                 :  *-------------------------------------------------------------------------
      15                 :  */
      16                 : #include "postgres.h"
      17                 : 
      18                 : #include <sys/wait.h>
      19                 : 
      20                 : #include "access/xlog.h"
      21                 : #include "archive/archive_module.h"
      22                 : #include "archive/shell_archive.h"
      23                 : #include "common/percentrepl.h"
      24                 : #include "pgstat.h"
      25                 : 
      26                 : static bool shell_archive_configured(ArchiveModuleState *state);
      27                 : static bool shell_archive_file(ArchiveModuleState *state,
      28                 :                                const char *file,
      29                 :                                const char *path);
      30                 : static void shell_archive_shutdown(ArchiveModuleState *state);
      31                 : 
      32                 : static const ArchiveModuleCallbacks shell_archive_callbacks = {
      33                 :     .startup_cb = NULL,
      34                 :     .check_configured_cb = shell_archive_configured,
      35                 :     .archive_file_cb = shell_archive_file,
      36                 :     .shutdown_cb = shell_archive_shutdown
      37                 : };
      38                 : 
      39                 : const ArchiveModuleCallbacks *
      40 GNC           9 : shell_archive_init(void)
      41                 : {
      42               9 :     return &shell_archive_callbacks;
      43                 : }
      44                 : 
      45                 : static bool
      46              23 : shell_archive_configured(ArchiveModuleState *state)
      47 ECB             : {
      48 GIC          23 :     return XLogArchiveCommand[0] != '\0';
      49 ECB             : }
      50                 : 
      51                 : static bool
      52 GNC          23 : shell_archive_file(ArchiveModuleState *state, const char *file,
      53                 :                    const char *path)
      54 ECB             : {
      55                 :     char       *xlogarchcmd;
      56 GNC          23 :     char       *nativePath = NULL;
      57                 :     int         rc;
      58 ECB             : 
      59 GNC          23 :     if (path)
      60 ECB             :     {
      61 GNC          23 :         nativePath = pstrdup(path);
      62              23 :         make_native_path(nativePath);
      63                 :     }
      64                 : 
      65              23 :     xlogarchcmd = replace_percent_placeholders(XLogArchiveCommand,
      66                 :                                                "archive_command", "fp",
      67                 :                                                file, nativePath);
      68                 : 
      69              23 :     if (nativePath)
      70              23 :         pfree(nativePath);
      71                 : 
      72 GIC          23 :     ereport(DEBUG3,
      73 EUB             :             (errmsg_internal("executing archive command \"%s\"",
      74                 :                              xlogarchcmd)));
      75                 : 
      76 GNC          23 :     fflush(NULL);
      77 GIC          23 :     pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
      78              23 :     rc = system(xlogarchcmd);
      79              23 :     pgstat_report_wait_end();
      80                 : 
      81              23 :     if (rc != 0)
      82                 :     {
      83                 :         /*
      84 EUB             :          * If either the shell itself, or a called command, died on a signal,
      85                 :          * abort the archiver.  We do this because system() ignores SIGINT and
      86                 :          * SIGQUIT while waiting; so a signal is very likely something that
      87                 :          * should have interrupted us too.  Also die if the shell got a hard
      88                 :          * "command not found" type of error.  If we overreact it's no big
      89                 :          * deal, the postmaster will just start the archiver again.
      90                 :          */
      91 GIC           1 :         int         lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
      92                 : 
      93 GBC           1 :         if (WIFEXITED(rc))
      94                 :         {
      95 GIC           1 :             ereport(lev,
      96                 :                     (errmsg("archive command failed with exit code %d",
      97                 :                             WEXITSTATUS(rc)),
      98                 :                      errdetail("The failed archive command was: %s",
      99                 :                                xlogarchcmd)));
     100 ECB             :         }
     101 UIC           0 :         else if (WIFSIGNALED(rc))
     102                 :         {
     103 ECB             : #if defined(WIN32)
     104                 :             ereport(lev,
     105                 :                     (errmsg("archive command was terminated by exception 0x%X",
     106                 :                             WTERMSIG(rc)),
     107                 :                      errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
     108                 :                      errdetail("The failed archive command was: %s",
     109                 :                                xlogarchcmd)));
     110                 : #else
     111 UIC           0 :             ereport(lev,
     112 ECB             :                     (errmsg("archive command was terminated by signal %d: %s",
     113                 :                             WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
     114                 :                      errdetail("The failed archive command was: %s",
     115                 :                                xlogarchcmd)));
     116                 : #endif
     117                 :         }
     118                 :         else
     119                 :         {
     120 UIC           0 :             ereport(lev,
     121                 :                     (errmsg("archive command exited with unrecognized status %d",
     122                 :                             rc),
     123                 :                      errdetail("The failed archive command was: %s",
     124                 :                                xlogarchcmd)));
     125                 :         }
     126                 : 
     127 GIC           1 :         return false;
     128                 :     }
     129                 : 
     130 GNC          22 :     pfree(xlogarchcmd);
     131                 : 
     132 GIC          22 :     elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
     133              22 :     return true;
     134                 : }
     135                 : 
     136                 : static void
     137 GNC           9 : shell_archive_shutdown(ArchiveModuleState *state)
     138                 : {
     139 GIC           9 :     elog(DEBUG1, "archiver process shutting down");
     140               9 : }
        

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