Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c1dc51d

Browse files
committed
pg_ctl: Detect current standby state from pg_control
pg_ctl used to determine whether a server was in standby mode by looking for a recovery.conf file. With this change, it instead looks into pg_control, which is potentially more accurate. There are also occasional discussions about removing recovery.conf, so this removes one dependency. Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
1 parent eb5089a commit c1dc51d

File tree

5 files changed

+62
-18
lines changed

5 files changed

+62
-18
lines changed

src/backend/utils/misc/pg_controldata.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ pg_control_system(PG_FUNCTION_ARGS)
5252

5353
/* read the control file */
5454
ControlFile = get_controlfile(DataDir, NULL);
55+
if (!ControlFile)
56+
ereport(ERROR,
57+
(errmsg("calculated CRC checksum does not match value stored in file")));
5558

5659
values[0] = Int32GetDatum(ControlFile->pg_control_version);
5760
nulls[0] = false;
@@ -128,6 +131,9 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
128131

129132
/* Read the control file. */
130133
ControlFile = get_controlfile(DataDir, NULL);
134+
if (!ControlFile)
135+
ereport(ERROR,
136+
(errmsg("calculated CRC checksum does not match value stored in file")));
131137

132138
/*
133139
* Calculate name of the WAL file containing the latest checkpoint's REDO
@@ -230,6 +236,9 @@ pg_control_recovery(PG_FUNCTION_ARGS)
230236

231237
/* read the control file */
232238
ControlFile = get_controlfile(DataDir, NULL);
239+
if (!ControlFile)
240+
ereport(ERROR,
241+
(errmsg("calculated CRC checksum does not match value stored in file")));
233242

234243
values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
235244
nulls[0] = false;
@@ -295,6 +304,9 @@ pg_control_init(PG_FUNCTION_ARGS)
295304

296305
/* read the control file */
297306
ControlFile = get_controlfile(DataDir, NULL);
307+
if (!ControlFile)
308+
ereport(ERROR,
309+
(errmsg("calculated CRC checksum does not match value stored in file")));
298310

299311
values[0] = Int32GetDatum(ControlFile->maxAlign);
300312
nulls[0] = false;

src/bin/pg_controldata/pg_controldata.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ main(int argc, char *argv[])
156156

157157
/* get a copy of the control file */
158158
ControlFile = get_controlfile(DataDir, progname);
159+
if (!ControlFile)
160+
printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
161+
"Either the file is corrupt, or it has a different layout than this program\n"
162+
"is expecting. The results below are untrustworthy.\n\n"));
159163

160164
/*
161165
* This slightly-chintzy coding will work as long as the control file

src/bin/pg_ctl/pg_ctl.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "postgres_fe.h"
2121

22+
#include "catalog/pg_control.h"
23+
#include "common/controldata_utils.h"
2224
#include "libpq-fe.h"
2325
#include "pqexpbuffer.h"
2426

@@ -96,7 +98,6 @@ static char postopts_file[MAXPGPATH];
9698
static char version_file[MAXPGPATH];
9799
static char pid_file[MAXPGPATH];
98100
static char backup_file[MAXPGPATH];
99-
static char recovery_file[MAXPGPATH];
100101
static char promote_file[MAXPGPATH];
101102

102103
#ifdef WIN32
@@ -158,6 +159,8 @@ static bool postmaster_is_alive(pid_t pid);
158159
static void unlimit_core_size(void);
159160
#endif
160161

162+
static DBState get_control_dbstate(void);
163+
161164

162165
#ifdef WIN32
163166
static void
@@ -988,12 +991,12 @@ do_stop(void)
988991
/*
989992
* If backup_label exists, an online backup is running. Warn the user
990993
* that smart shutdown will wait for it to finish. However, if
991-
* recovery.conf is also present, we're recovering from an online
994+
* the server is in archive recovery, we're recovering from an online
992995
* backup instead of performing one.
993996
*/
994997
if (shutdown_mode == SMART_MODE &&
995998
stat(backup_file, &statbuf) == 0 &&
996-
stat(recovery_file, &statbuf) != 0)
999+
get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
9971000
{
9981001
print_msg(_("WARNING: online backup mode is active\n"
9991002
"Shutdown will not complete until pg_stop_backup() is called.\n\n"));
@@ -1076,12 +1079,12 @@ do_restart(void)
10761079
/*
10771080
* If backup_label exists, an online backup is running. Warn the user
10781081
* that smart shutdown will wait for it to finish. However, if
1079-
* recovery.conf is also present, we're recovering from an online
1082+
* the server is in archive recovery, we're recovering from an online
10801083
* backup instead of performing one.
10811084
*/
10821085
if (shutdown_mode == SMART_MODE &&
10831086
stat(backup_file, &statbuf) == 0 &&
1084-
stat(recovery_file, &statbuf) != 0)
1087+
get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
10851088
{
10861089
print_msg(_("WARNING: online backup mode is active\n"
10871090
"Shutdown will not complete until pg_stop_backup() is called.\n\n"));
@@ -1168,7 +1171,6 @@ do_promote(void)
11681171
{
11691172
FILE *prmfile;
11701173
pgpid_t pid;
1171-
struct stat statbuf;
11721174

11731175
pid = get_pgpid(false);
11741176

@@ -1187,8 +1189,7 @@ do_promote(void)
11871189
exit(1);
11881190
}
11891191

1190-
/* If recovery.conf doesn't exist, the server is not in standby mode */
1191-
if (stat(recovery_file, &statbuf) != 0)
1192+
if (get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
11921193
{
11931194
write_stderr(_("%s: cannot promote server; "
11941195
"server is not in standby mode\n"),
@@ -2115,6 +2116,35 @@ adjust_data_dir(void)
21152116
}
21162117

21172118

2119+
static DBState
2120+
get_control_dbstate(void)
2121+
{
2122+
DBState ret;
2123+
2124+
for (;;)
2125+
{
2126+
ControlFileData *control_file_data = get_controlfile(pg_data, progname);
2127+
2128+
if (control_file_data)
2129+
{
2130+
ret = control_file_data->state;
2131+
pfree(control_file_data);
2132+
return ret;
2133+
}
2134+
2135+
if (wait_seconds > 0)
2136+
{
2137+
pg_usleep(1000000); /* 1 sec */
2138+
wait_seconds--;
2139+
continue;
2140+
}
2141+
2142+
write_stderr(_("%s: control file appears to be corrupt\n"), progname);
2143+
exit(1);
2144+
}
2145+
}
2146+
2147+
21182148
int
21192149
main(int argc, char **argv)
21202150
{
@@ -2401,7 +2431,6 @@ main(int argc, char **argv)
24012431
snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
24022432
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
24032433
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
2404-
snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);
24052434
}
24062435

24072436
switch (ctl_command)

src/common/controldata_utils.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
3333
*
3434
* Get controlfile values. The caller is responsible
3535
* for pfreeing the result.
36+
*
37+
* Returns NULL if the CRC did not match.
3638
*/
3739
ControlFileData *
38-
get_controlfile(char *DataDir, const char *progname)
40+
get_controlfile(const char *DataDir, const char *progname)
3941
{
4042
ControlFileData *ControlFile;
4143
int fd;
@@ -82,13 +84,10 @@ get_controlfile(char *DataDir, const char *progname)
8284
FIN_CRC32C(crc);
8385

8486
if (!EQ_CRC32C(crc, ControlFile->crc))
85-
#ifndef FRONTEND
86-
elog(ERROR, _("calculated CRC checksum does not match value stored in file"));
87-
#else
88-
printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
89-
"Either the file is corrupt, or it has a different layout than this program\n"
90-
"is expecting. The results below are untrustworthy.\n\n"));
91-
#endif
87+
{
88+
pfree(ControlFile);
89+
return NULL;
90+
}
9291

9392
/* Make sure the control file is valid byte order. */
9493
if (ControlFile->pg_control_version % 65536 == 0 &&

src/include/common/controldata_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212

1313
#include "catalog/pg_control.h"
1414

15-
extern ControlFileData *get_controlfile(char *DataDir, const char *progname);
15+
extern ControlFileData *get_controlfile(const char *DataDir, const char *progname);
1616

1717
#endif /* COMMON_CONTROLDATA_UTILS_H */

0 commit comments

Comments
 (0)