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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy