mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
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
This commit is contained in:
parent
7f6772317b
commit
aeb4cc9ea0
@ -23,6 +23,7 @@ OBJS = \
|
||||
pgarch.o \
|
||||
pgstat.o \
|
||||
postmaster.o \
|
||||
shell_archive.o \
|
||||
startup.o \
|
||||
syslogger.o \
|
||||
walwriter.o
|
||||
|
@ -25,19 +25,14 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "lib/binaryheap.h"
|
||||
#include "libpq/pqsignal.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "postmaster/interrupt.h"
|
||||
#include "postmaster/pgarch.h"
|
||||
@ -504,132 +499,24 @@ pgarch_ArchiverCopyLoop(void)
|
||||
static bool
|
||||
pgarch_archiveXlog(char *xlog)
|
||||
{
|
||||
char xlogarchcmd[MAXPGPATH];
|
||||
char pathname[MAXPGPATH];
|
||||
char activitymsg[MAXFNAMELEN + 16];
|
||||
char *dp;
|
||||
char *endp;
|
||||
const char *sp;
|
||||
int rc;
|
||||
bool ret;
|
||||
|
||||
snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
|
||||
|
||||
/*
|
||||
* construct the command to be executed
|
||||
*/
|
||||
dp = xlogarchcmd;
|
||||
endp = xlogarchcmd + MAXPGPATH - 1;
|
||||
*endp = '\0';
|
||||
|
||||
for (sp = XLogArchiveCommand; *sp; sp++)
|
||||
{
|
||||
if (*sp == '%')
|
||||
{
|
||||
switch (sp[1])
|
||||
{
|
||||
case 'p':
|
||||
/* %p: relative path of source file */
|
||||
sp++;
|
||||
strlcpy(dp, pathname, endp - dp);
|
||||
make_native_path(dp);
|
||||
dp += strlen(dp);
|
||||
break;
|
||||
case 'f':
|
||||
/* %f: filename of source file */
|
||||
sp++;
|
||||
strlcpy(dp, xlog, endp - dp);
|
||||
dp += strlen(dp);
|
||||
break;
|
||||
case '%':
|
||||
/* convert %% to a single % */
|
||||
sp++;
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
break;
|
||||
default:
|
||||
/* otherwise treat the % as not special */
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
}
|
||||
}
|
||||
*dp = '\0';
|
||||
|
||||
ereport(DEBUG3,
|
||||
(errmsg_internal("executing archive command \"%s\"",
|
||||
xlogarchcmd)));
|
||||
|
||||
/* Report archive activity in PS display */
|
||||
snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
|
||||
set_ps_display(activitymsg);
|
||||
|
||||
pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
|
||||
rc = system(xlogarchcmd);
|
||||
pgstat_report_wait_end();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
/*
|
||||
* If either the shell itself, or a called command, died on a signal,
|
||||
* abort the archiver. We do this because system() ignores SIGINT and
|
||||
* SIGQUIT while waiting; so a signal is very likely something that
|
||||
* should have interrupted us too. Also die if the shell got a hard
|
||||
* "command not found" type of error. If we overreact it's no big
|
||||
* deal, the postmaster will just start the archiver again.
|
||||
*/
|
||||
int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
|
||||
|
||||
if (WIFEXITED(rc))
|
||||
{
|
||||
ereport(lev,
|
||||
(errmsg("archive command failed with exit code %d",
|
||||
WEXITSTATUS(rc)),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
}
|
||||
else if (WIFSIGNALED(rc))
|
||||
{
|
||||
#if defined(WIN32)
|
||||
ereport(lev,
|
||||
(errmsg("archive command was terminated by exception 0x%X",
|
||||
WTERMSIG(rc)),
|
||||
errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
#else
|
||||
ereport(lev,
|
||||
(errmsg("archive command was terminated by signal %d: %s",
|
||||
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(lev,
|
||||
(errmsg("archive command exited with unrecognized status %d",
|
||||
rc),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
}
|
||||
|
||||
ret = shell_archive_file(xlog, pathname);
|
||||
if (ret)
|
||||
snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
|
||||
else
|
||||
snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
|
||||
set_ps_display(activitymsg);
|
||||
|
||||
return false;
|
||||
}
|
||||
elog(DEBUG1, "archived write-ahead log file \"%s\"", xlog);
|
||||
|
||||
snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
|
||||
set_ps_display(activitymsg);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
135
src/backend/postmaster/shell_archive.c
Normal file
135
src/backend/postmaster/shell_archive.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* shell_archive.c
|
||||
*
|
||||
* Copyright (c) 2022, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/postmaster/shell_archive.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "pgstat.h"
|
||||
#include "postmaster/pgarch.h"
|
||||
|
||||
bool
|
||||
shell_archive_file(const char *file, const char *path)
|
||||
{
|
||||
char xlogarchcmd[MAXPGPATH];
|
||||
char *dp;
|
||||
char *endp;
|
||||
const char *sp;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* construct the command to be executed
|
||||
*/
|
||||
dp = xlogarchcmd;
|
||||
endp = xlogarchcmd + MAXPGPATH - 1;
|
||||
*endp = '\0';
|
||||
|
||||
for (sp = XLogArchiveCommand; *sp; sp++)
|
||||
{
|
||||
if (*sp == '%')
|
||||
{
|
||||
switch (sp[1])
|
||||
{
|
||||
case 'p':
|
||||
/* %p: relative path of source file */
|
||||
sp++;
|
||||
strlcpy(dp, path, endp - dp);
|
||||
make_native_path(dp);
|
||||
dp += strlen(dp);
|
||||
break;
|
||||
case 'f':
|
||||
/* %f: filename of source file */
|
||||
sp++;
|
||||
strlcpy(dp, file, endp - dp);
|
||||
dp += strlen(dp);
|
||||
break;
|
||||
case '%':
|
||||
/* convert %% to a single % */
|
||||
sp++;
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
break;
|
||||
default:
|
||||
/* otherwise treat the % as not special */
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dp < endp)
|
||||
*dp++ = *sp;
|
||||
}
|
||||
}
|
||||
*dp = '\0';
|
||||
|
||||
ereport(DEBUG3,
|
||||
(errmsg_internal("executing archive command \"%s\"",
|
||||
xlogarchcmd)));
|
||||
|
||||
pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
|
||||
rc = system(xlogarchcmd);
|
||||
pgstat_report_wait_end();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
/*
|
||||
* If either the shell itself, or a called command, died on a signal,
|
||||
* abort the archiver. We do this because system() ignores SIGINT and
|
||||
* SIGQUIT while waiting; so a signal is very likely something that
|
||||
* should have interrupted us too. Also die if the shell got a hard
|
||||
* "command not found" type of error. If we overreact it's no big
|
||||
* deal, the postmaster will just start the archiver again.
|
||||
*/
|
||||
int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
|
||||
|
||||
if (WIFEXITED(rc))
|
||||
{
|
||||
ereport(lev,
|
||||
(errmsg("archive command failed with exit code %d",
|
||||
WEXITSTATUS(rc)),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
}
|
||||
else if (WIFSIGNALED(rc))
|
||||
{
|
||||
#if defined(WIN32)
|
||||
ereport(lev,
|
||||
(errmsg("archive command was terminated by exception 0x%X",
|
||||
WTERMSIG(rc)),
|
||||
errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
#else
|
||||
ereport(lev,
|
||||
(errmsg("archive command was terminated by signal %d: %s",
|
||||
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(lev,
|
||||
(errmsg("archive command exited with unrecognized status %d",
|
||||
rc),
|
||||
errdetail("The failed archive command was: %s",
|
||||
xlogarchcmd)));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
|
||||
return true;
|
||||
}
|
@ -33,4 +33,7 @@ extern void PgArchiverMain(void) pg_attribute_noreturn();
|
||||
extern void PgArchWakeup(void);
|
||||
extern void PgArchForceDirScan(void);
|
||||
|
||||
/* in shell_archive.c */
|
||||
extern bool shell_archive_file(const char *file, const char *path);
|
||||
|
||||
#endif /* _PGARCH_H */
|
||||
|
Loading…
Reference in New Issue
Block a user