Skip to content

Commit aeb4cc9

Browse files
committed
Move the code to archive files via the shell to a separate file.
This is preparatory work for allowing more extensibility in this area. Nathan Bossart Discussion: http://postgr.es/m/668D2428-F73B-475E-87AE-F89D67942270@amazon.com
1 parent 7f67723 commit aeb4cc9

File tree

4 files changed

+145
-119
lines changed

4 files changed

+145
-119
lines changed

src/backend/postmaster/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ OBJS = \
2323
pgarch.o \
2424
pgstat.o \
2525
postmaster.o \
26+
shell_archive.o \
2627
startup.o \
2728
syslogger.o \
2829
walwriter.o

src/backend/postmaster/pgarch.c

Lines changed: 6 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,14 @@
2525
*/
2626
#include "postgres.h"
2727

28-
#include <fcntl.h>
29-
#include <signal.h>
3028
#include <time.h>
3129
#include <sys/stat.h>
32-
#include <sys/time.h>
33-
#include <sys/wait.h>
3430
#include <unistd.h>
3531

3632
#include "access/xlog.h"
3733
#include "access/xlog_internal.h"
3834
#include "lib/binaryheap.h"
3935
#include "libpq/pqsignal.h"
40-
#include "miscadmin.h"
4136
#include "pgstat.h"
4237
#include "postmaster/interrupt.h"
4338
#include "postmaster/pgarch.h"
@@ -504,132 +499,24 @@ pgarch_ArchiverCopyLoop(void)
504499
static bool
505500
pgarch_archiveXlog(char *xlog)
506501
{
507-
char xlogarchcmd[MAXPGPATH];
508502
char pathname[MAXPGPATH];
509503
char activitymsg[MAXFNAMELEN + 16];
510-
char *dp;
511-
char *endp;
512-
const char *sp;
513-
int rc;
504+
bool ret;
514505

515506
snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
516507

517-
/*
518-
* construct the command to be executed
519-
*/
520-
dp = xlogarchcmd;
521-
endp = xlogarchcmd + MAXPGPATH - 1;
522-
*endp = '\0';
523-
524-
for (sp = XLogArchiveCommand; *sp; sp++)
525-
{
526-
if (*sp == '%')
527-
{
528-
switch (sp[1])
529-
{
530-
case 'p':
531-
/* %p: relative path of source file */
532-
sp++;
533-
strlcpy(dp, pathname, endp - dp);
534-
make_native_path(dp);
535-
dp += strlen(dp);
536-
break;
537-
case 'f':
538-
/* %f: filename of source file */
539-
sp++;
540-
strlcpy(dp, xlog, endp - dp);
541-
dp += strlen(dp);
542-
break;
543-
case '%':
544-
/* convert %% to a single % */
545-
sp++;
546-
if (dp < endp)
547-
*dp++ = *sp;
548-
break;
549-
default:
550-
/* otherwise treat the % as not special */
551-
if (dp < endp)
552-
*dp++ = *sp;
553-
break;
554-
}
555-
}
556-
else
557-
{
558-
if (dp < endp)
559-
*dp++ = *sp;
560-
}
561-
}
562-
*dp = '\0';
563-
564-
ereport(DEBUG3,
565-
(errmsg_internal("executing archive command \"%s\"",
566-
xlogarchcmd)));
567-
568508
/* Report archive activity in PS display */
569509
snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
570510
set_ps_display(activitymsg);
571511

572-
pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
573-
rc = system(xlogarchcmd);
574-
pgstat_report_wait_end();
575-
576-
if (rc != 0)
577-
{
578-
/*
579-
* If either the shell itself, or a called command, died on a signal,
580-
* abort the archiver. We do this because system() ignores SIGINT and
581-
* SIGQUIT while waiting; so a signal is very likely something that
582-
* should have interrupted us too. Also die if the shell got a hard
583-
* "command not found" type of error. If we overreact it's no big
584-
* deal, the postmaster will just start the archiver again.
585-
*/
586-
int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
587-
588-
if (WIFEXITED(rc))
589-
{
590-
ereport(lev,
591-
(errmsg("archive command failed with exit code %d",
592-
WEXITSTATUS(rc)),
593-
errdetail("The failed archive command was: %s",
594-
xlogarchcmd)));
595-
}
596-
else if (WIFSIGNALED(rc))
597-
{
598-
#if defined(WIN32)
599-
ereport(lev,
600-
(errmsg("archive command was terminated by exception 0x%X",
601-
WTERMSIG(rc)),
602-
errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
603-
errdetail("The failed archive command was: %s",
604-
xlogarchcmd)));
605-
#else
606-
ereport(lev,
607-
(errmsg("archive command was terminated by signal %d: %s",
608-
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
609-
errdetail("The failed archive command was: %s",
610-
xlogarchcmd)));
611-
#endif
612-
}
613-
else
614-
{
615-
ereport(lev,
616-
(errmsg("archive command exited with unrecognized status %d",
617-
rc),
618-
errdetail("The failed archive command was: %s",
619-
xlogarchcmd)));
620-
}
621-
512+
ret = shell_archive_file(xlog, pathname);
513+
if (ret)
514+
snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
515+
else
622516
snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
623-
set_ps_display(activitymsg);
624-
625-
return false;
626-
}
627-
elog(DEBUG1, "archived write-ahead log file \"%s\"", xlog);
628-
629-
snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
630517
set_ps_display(activitymsg);
631518

632-
return true;
519+
return ret;
633520
}
634521

635522
/*
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* shell_archive.c
4+
*
5+
* Copyright (c) 2022, PostgreSQL Global Development Group
6+
*
7+
* IDENTIFICATION
8+
* src/backend/postmaster/shell_archive.c
9+
*
10+
*-------------------------------------------------------------------------
11+
*/
12+
#include "postgres.h"
13+
14+
#include <sys/wait.h>
15+
16+
#include "access/xlog.h"
17+
#include "pgstat.h"
18+
#include "postmaster/pgarch.h"
19+
20+
bool
21+
shell_archive_file(const char *file, const char *path)
22+
{
23+
char xlogarchcmd[MAXPGPATH];
24+
char *dp;
25+
char *endp;
26+
const char *sp;
27+
int rc;
28+
29+
/*
30+
* construct the command to be executed
31+
*/
32+
dp = xlogarchcmd;
33+
endp = xlogarchcmd + MAXPGPATH - 1;
34+
*endp = '\0';
35+
36+
for (sp = XLogArchiveCommand; *sp; sp++)
37+
{
38+
if (*sp == '%')
39+
{
40+
switch (sp[1])
41+
{
42+
case 'p':
43+
/* %p: relative path of source file */
44+
sp++;
45+
strlcpy(dp, path, endp - dp);
46+
make_native_path(dp);
47+
dp += strlen(dp);
48+
break;
49+
case 'f':
50+
/* %f: filename of source file */
51+
sp++;
52+
strlcpy(dp, file, endp - dp);
53+
dp += strlen(dp);
54+
break;
55+
case '%':
56+
/* convert %% to a single % */
57+
sp++;
58+
if (dp < endp)
59+
*dp++ = *sp;
60+
break;
61+
default:
62+
/* otherwise treat the % as not special */
63+
if (dp < endp)
64+
*dp++ = *sp;
65+
break;
66+
}
67+
}
68+
else
69+
{
70+
if (dp < endp)
71+
*dp++ = *sp;
72+
}
73+
}
74+
*dp = '\0';
75+
76+
ereport(DEBUG3,
77+
(errmsg_internal("executing archive command \"%s\"",
78+
xlogarchcmd)));
79+
80+
pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
81+
rc = system(xlogarchcmd);
82+
pgstat_report_wait_end();
83+
84+
if (rc != 0)
85+
{
86+
/*
87+
* If either the shell itself, or a called command, died on a signal,
88+
* abort the archiver. We do this because system() ignores SIGINT and
89+
* SIGQUIT while waiting; so a signal is very likely something that
90+
* should have interrupted us too. Also die if the shell got a hard
91+
* "command not found" type of error. If we overreact it's no big
92+
* deal, the postmaster will just start the archiver again.
93+
*/
94+
int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
95+
96+
if (WIFEXITED(rc))
97+
{
98+
ereport(lev,
99+
(errmsg("archive command failed with exit code %d",
100+
WEXITSTATUS(rc)),
101+
errdetail("The failed archive command was: %s",
102+
xlogarchcmd)));
103+
}
104+
else if (WIFSIGNALED(rc))
105+
{
106+
#if defined(WIN32)
107+
ereport(lev,
108+
(errmsg("archive command was terminated by exception 0x%X",
109+
WTERMSIG(rc)),
110+
errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
111+
errdetail("The failed archive command was: %s",
112+
xlogarchcmd)));
113+
#else
114+
ereport(lev,
115+
(errmsg("archive command was terminated by signal %d: %s",
116+
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
117+
errdetail("The failed archive command was: %s",
118+
xlogarchcmd)));
119+
#endif
120+
}
121+
else
122+
{
123+
ereport(lev,
124+
(errmsg("archive command exited with unrecognized status %d",
125+
rc),
126+
errdetail("The failed archive command was: %s",
127+
xlogarchcmd)));
128+
}
129+
130+
return false;
131+
}
132+
133+
elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
134+
return true;
135+
}

src/include/postmaster/pgarch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,7 @@ extern void PgArchiverMain(void) pg_attribute_noreturn();
3333
extern void PgArchWakeup(void);
3434
extern void PgArchForceDirScan(void);
3535

36+
/* in shell_archive.c */
37+
extern bool shell_archive_file(const char *file, const char *path);
38+
3639
#endif /* _PGARCH_H */

0 commit comments

Comments
 (0)