Skip to content

Commit 14bdb3f

Browse files
committed
Refactor code for restoring files via shell commands
Presently, restore_command uses a different code path than archive_cleanup_command and recovery_end_command. These code paths are similar and can be easily combined, as long as it is possible to identify if a command should: - Issue a FATAL on signal. - Exit immediately on SIGTERM. While on it, this removes src/common/archive.c and its associated header. Since the introduction of c96de2c, BuildRestoreCommand() has become a simple wrapper of replace_percent_placeholders() able to call make_native_path(). This simplifies shell_restore.c as long as RestoreArchivedFile() includes a call to make_native_path(). Author: Nathan Bossart Reviewed-by: Andres Freund, Michael Paquier Discussion: https://postgr.es/m/20221227192449.GA3672473@nathanxps13
1 parent 2f31f40 commit 14bdb3f

File tree

8 files changed

+56
-139
lines changed

8 files changed

+56
-139
lines changed

src/backend/access/transam/shell_restore.c

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@
2020

2121
#include "access/xlogarchive.h"
2222
#include "access/xlogrecovery.h"
23-
#include "common/archive.h"
2423
#include "common/percentrepl.h"
2524
#include "storage/ipc.h"
2625
#include "utils/wait_event.h"
2726

28-
static void ExecuteRecoveryCommand(const char *command,
27+
static bool ExecuteRecoveryCommand(const char *command,
2928
const char *commandName,
3029
bool failOnSignal,
30+
bool exitOnSigterm,
3131
uint32 wait_event_info,
32-
const char *lastRestartPointFileName);
32+
int fail_elevel);
3333

3434
/*
3535
* Attempt to execute a shell-based restore command.
@@ -40,25 +40,17 @@ bool
4040
shell_restore(const char *file, const char *path,
4141
const char *lastRestartPointFileName)
4242
{
43+
char *nativePath = pstrdup(path);
4344
char *cmd;
44-
int rc;
45+
bool ret;
4546

4647
/* Build the restore command to execute */
47-
cmd = BuildRestoreCommand(recoveryRestoreCommand, path, file,
48-
lastRestartPointFileName);
49-
50-
ereport(DEBUG3,
51-
(errmsg_internal("executing restore command \"%s\"", cmd)));
52-
53-
/*
54-
* Copy xlog from archival storage to XLOGDIR
55-
*/
56-
fflush(NULL);
57-
pgstat_report_wait_start(WAIT_EVENT_RESTORE_COMMAND);
58-
rc = system(cmd);
59-
pgstat_report_wait_end();
60-
61-
pfree(cmd);
48+
make_native_path(nativePath);
49+
cmd = replace_percent_placeholders(recoveryRestoreCommand,
50+
"restore_command", "frp", file,
51+
lastRestartPointFileName,
52+
nativePath);
53+
pfree(nativePath);
6254

6355
/*
6456
* Remember, we rollforward UNTIL the restore fails so failure here is
@@ -84,17 +76,13 @@ shell_restore(const char *file, const char *path,
8476
*
8577
* We treat hard shell errors such as "command not found" as fatal, too.
8678
*/
87-
if (rc != 0)
88-
{
89-
if (wait_result_is_signal(rc, SIGTERM))
90-
proc_exit(1);
91-
92-
ereport(wait_result_is_any_signal(rc, true) ? FATAL : DEBUG2,
93-
(errmsg("could not restore file \"%s\" from archive: %s",
94-
file, wait_result_to_str(rc))));
95-
}
79+
ret = ExecuteRecoveryCommand(cmd, "restore_command",
80+
true, /* failOnSignal */
81+
true, /* exitOnSigterm */
82+
WAIT_EVENT_RESTORE_COMMAND, DEBUG2);
83+
pfree(cmd);
9684

97-
return (rc == 0);
85+
return ret;
9886
}
9987

10088
/*
@@ -103,9 +91,14 @@ shell_restore(const char *file, const char *path,
10391
void
10492
shell_archive_cleanup(const char *lastRestartPointFileName)
10593
{
106-
ExecuteRecoveryCommand(archiveCleanupCommand, "archive_cleanup_command",
107-
false, WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND,
108-
lastRestartPointFileName);
94+
char *cmd;
95+
96+
cmd = replace_percent_placeholders(archiveCleanupCommand,
97+
"archive_cleanup_command",
98+
"r", lastRestartPointFileName);
99+
(void) ExecuteRecoveryCommand(cmd, "archive_cleanup_command", false, false,
100+
WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND, WARNING);
101+
pfree(cmd);
109102
}
110103

111104
/*
@@ -114,9 +107,14 @@ shell_archive_cleanup(const char *lastRestartPointFileName)
114107
void
115108
shell_recovery_end(const char *lastRestartPointFileName)
116109
{
117-
ExecuteRecoveryCommand(recoveryEndCommand, "recovery_end_command", true,
118-
WAIT_EVENT_RECOVERY_END_COMMAND,
119-
lastRestartPointFileName);
110+
char *cmd;
111+
112+
cmd = replace_percent_placeholders(recoveryEndCommand,
113+
"recovery_end_command",
114+
"r", lastRestartPointFileName);
115+
(void) ExecuteRecoveryCommand(cmd, "recovery_end_command", true, false,
116+
WAIT_EVENT_RECOVERY_END_COMMAND, WARNING);
117+
pfree(cmd);
120118
}
121119

122120
/*
@@ -125,26 +123,21 @@ shell_recovery_end(const char *lastRestartPointFileName)
125123
* 'command' is the shell command to be executed, 'commandName' is a
126124
* human-readable name describing the command emitted in the logs. If
127125
* 'failOnSignal' is true and the command is killed by a signal, a FATAL
128-
* error is thrown. Otherwise a WARNING is emitted.
126+
* error is thrown. Otherwise, 'fail_elevel' is used for the log message.
127+
* If 'exitOnSigterm' is true and the command is killed by SIGTERM, we exit
128+
* immediately.
129129
*
130-
* This is currently used for recovery_end_command and archive_cleanup_command.
130+
* Returns whether the command succeeded.
131131
*/
132-
static void
132+
static bool
133133
ExecuteRecoveryCommand(const char *command, const char *commandName,
134-
bool failOnSignal, uint32 wait_event_info,
135-
const char *lastRestartPointFileName)
134+
bool failOnSignal, bool exitOnSigterm,
135+
uint32 wait_event_info, int fail_elevel)
136136
{
137-
char *xlogRecoveryCmd;
138137
int rc;
139138

140139
Assert(command && commandName);
141140

142-
/*
143-
* construct the command to be executed
144-
*/
145-
xlogRecoveryCmd = replace_percent_placeholders(command, commandName, "r",
146-
lastRestartPointFileName);
147-
148141
ereport(DEBUG3,
149142
(errmsg_internal("executing %s \"%s\"", commandName, command)));
150143

@@ -153,23 +146,26 @@ ExecuteRecoveryCommand(const char *command, const char *commandName,
153146
*/
154147
fflush(NULL);
155148
pgstat_report_wait_start(wait_event_info);
156-
rc = system(xlogRecoveryCmd);
149+
rc = system(command);
157150
pgstat_report_wait_end();
158151

159-
pfree(xlogRecoveryCmd);
160-
161152
if (rc != 0)
162153
{
154+
if (exitOnSigterm && wait_result_is_signal(rc, SIGTERM))
155+
proc_exit(1);
156+
163157
/*
164158
* If the failure was due to any sort of signal, it's best to punt and
165159
* abort recovery. See comments in shell_restore().
166160
*/
167-
ereport((failOnSignal && wait_result_is_any_signal(rc, true)) ? FATAL : WARNING,
161+
ereport((failOnSignal && wait_result_is_any_signal(rc, true)) ? FATAL : fail_elevel,
168162
/*------
169163
translator: First %s represents a postgresql.conf parameter name like
170164
"recovery_end_command", the 2nd is the value of that parameter, the
171165
third an already translated error message. */
172166
(errmsg("%s \"%s\": %s", commandName,
173167
command, wait_result_to_str(rc))));
174168
}
169+
170+
return (rc == 0);
175171
}

src/backend/access/transam/xlogarchive.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "access/xlog.h"
2323
#include "access/xlog_internal.h"
2424
#include "access/xlogarchive.h"
25-
#include "common/archive.h"
2625
#include "miscadmin.h"
2726
#include "pgstat.h"
2827
#include "postmaster/startup.h"

src/common/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ LIBS += $(PTHREAD_LIBS)
4646
# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
4747

4848
OBJS_COMMON = \
49-
archive.o \
5049
base64.o \
5150
checksum_helper.o \
5251
compression.o \

src/common/archive.c

Lines changed: 0 additions & 60 deletions
This file was deleted.

src/common/meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright (c) 2022-2023, PostgreSQL Global Development Group
22

33
common_sources = files(
4-
'archive.c',
54
'base64.c',
65
'checksum_helper.c',
76
'compression.c',

src/fe_utils/archive.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include <sys/stat.h>
2020

2121
#include "access/xlog_internal.h"
22-
#include "common/archive.h"
2322
#include "common/logging.h"
23+
#include "common/percentrepl.h"
2424
#include "fe_utils/archive.h"
2525

2626

@@ -41,13 +41,18 @@ RestoreArchivedFile(const char *path, const char *xlogfname,
4141
{
4242
char xlogpath[MAXPGPATH];
4343
char *xlogRestoreCmd;
44+
char *nativePath;
4445
int rc;
4546
struct stat stat_buf;
4647

4748
snprintf(xlogpath, MAXPGPATH, "%s/" XLOGDIR "/%s", path, xlogfname);
4849

49-
xlogRestoreCmd = BuildRestoreCommand(restoreCommand, xlogpath,
50-
xlogfname, NULL);
50+
nativePath = pstrdup(xlogpath);
51+
make_native_path(nativePath);
52+
xlogRestoreCmd = replace_percent_placeholders(restoreCommand,
53+
"restore_command", "fp",
54+
xlogfname, nativePath);
55+
pfree(nativePath);
5156

5257
/*
5358
* Execute restore_command, which should copy the missing file from

src/include/common/archive.h

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/tools/msvc/Mkvcbuild.pm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ sub mkvcbuild
133133
}
134134

135135
our @pgcommonallfiles = qw(
136-
archive.c base64.c checksum_helper.c compression.c
136+
base64.c checksum_helper.c compression.c
137137
config_info.c controldata_utils.c d2s.c encnames.c exec.c
138138
f2s.c file_perm.c file_utils.c hashfn.c ip.c jsonapi.c
139139
keywords.c kwlookup.c link-canary.c md5_common.c percentrepl.c

0 commit comments

Comments
 (0)