mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Fix compatibility of pg_basebackup -R with 11 and older versions
When 2dedf4d9 has integrated recovery.conf into postgresql.conf, it also changed pg_basebackup -R in the way recovery configuration is generated. However this implementation forgot the fact that pg_basebackup needs to keep compatibility with older server versions as well. Reported-by: Devrim Gündüz Author: Sergei Kornilov, Michael Paquier Discussion: https://postgr.es/m/3458f7cd12d74acd90180a671c8d5a081d60e162.camel@gunduz.org
This commit is contained in:
parent
251cf2e27b
commit
beeb8e2e07
@ -66,6 +66,11 @@ typedef struct TablespaceList
|
||||
*/
|
||||
#define MINIMUM_VERSION_FOR_TEMP_SLOTS 100000
|
||||
|
||||
/*
|
||||
* recovery.conf is integrated into postgresql.conf from version 12.
|
||||
*/
|
||||
#define MINIMUM_VERSION_FOR_RECOVERY_GUC 120000
|
||||
|
||||
/*
|
||||
* Different ways to include WAL
|
||||
*/
|
||||
@ -974,6 +979,7 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
bool basetablespace = PQgetisnull(res, rownum, 0);
|
||||
bool in_tarhdr = true;
|
||||
bool skip_file = false;
|
||||
bool is_recovery_guc_supported = true;
|
||||
bool is_postgresql_auto_conf = false;
|
||||
bool found_postgresql_auto_conf = false;
|
||||
int file_padding_len = 0;
|
||||
@ -984,6 +990,10 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
gzFile ztarfile = NULL;
|
||||
#endif
|
||||
|
||||
/* recovery.conf is integrated into postgresql.conf in 12 and newer */
|
||||
if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
|
||||
is_recovery_guc_supported = false;
|
||||
|
||||
if (basetablespace)
|
||||
{
|
||||
/*
|
||||
@ -1130,11 +1140,20 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
{
|
||||
char header[512];
|
||||
|
||||
if (!found_postgresql_auto_conf)
|
||||
/*
|
||||
* If postgresql.auto.conf has not been found in the streamed
|
||||
* data, add recovery configuration to postgresql.auto.conf if
|
||||
* recovery parameters are GUCs. If the instance connected to
|
||||
* is older than 12, create recovery.conf with this data
|
||||
* otherwise.
|
||||
*/
|
||||
if (!found_postgresql_auto_conf || !is_recovery_guc_supported)
|
||||
{
|
||||
int padding;
|
||||
|
||||
tarCreateHeader(header, "postgresql.auto.conf", NULL,
|
||||
tarCreateHeader(header,
|
||||
is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf",
|
||||
NULL,
|
||||
recoveryconfcontents->len,
|
||||
pg_file_create_mode, 04000, 02000,
|
||||
time(NULL));
|
||||
@ -1142,18 +1161,26 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
|
||||
|
||||
WRITE_TAR_DATA(header, sizeof(header));
|
||||
WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
|
||||
WRITE_TAR_DATA(recoveryconfcontents->data,
|
||||
recoveryconfcontents->len);
|
||||
if (padding)
|
||||
WRITE_TAR_DATA(zerobuf, padding);
|
||||
}
|
||||
|
||||
tarCreateHeader(header, "standby.signal", NULL,
|
||||
0, /* zero-length file */
|
||||
pg_file_create_mode, 04000, 02000,
|
||||
time(NULL));
|
||||
/*
|
||||
* standby.signal is supported only if recovery parameters are
|
||||
* GUCs.
|
||||
*/
|
||||
if (is_recovery_guc_supported)
|
||||
{
|
||||
tarCreateHeader(header, "standby.signal", NULL,
|
||||
0, /* zero-length file */
|
||||
pg_file_create_mode, 04000, 02000,
|
||||
time(NULL));
|
||||
|
||||
WRITE_TAR_DATA(header, sizeof(header));
|
||||
WRITE_TAR_DATA(zerobuf, 511);
|
||||
WRITE_TAR_DATA(header, sizeof(header));
|
||||
WRITE_TAR_DATA(zerobuf, 511);
|
||||
}
|
||||
}
|
||||
|
||||
/* 2 * 512 bytes empty data at end of file */
|
||||
@ -1252,16 +1279,24 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
* We have the complete header structure in tarhdr,
|
||||
* look at the file metadata: we may want append
|
||||
* recovery info into postgresql.auto.conf and skip
|
||||
* standby.signal file. In both cases we must
|
||||
* calculate tar padding
|
||||
* standby.signal file if recovery parameters are
|
||||
* integrated as GUCs, and recovery.conf otherwise. In
|
||||
* both cases we must calculate tar padding.
|
||||
*/
|
||||
skip_file = (strcmp(&tarhdr[0], "standby.signal") == 0);
|
||||
is_postgresql_auto_conf = (strcmp(&tarhdr[0], "postgresql.auto.conf") == 0);
|
||||
if (is_recovery_guc_supported)
|
||||
{
|
||||
skip_file = (strcmp(&tarhdr[0], "standby.signal") == 0);
|
||||
is_postgresql_auto_conf = (strcmp(&tarhdr[0], "postgresql.auto.conf") == 0);
|
||||
}
|
||||
else
|
||||
skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
|
||||
|
||||
filesz = read_tar_number(&tarhdr[124], 12);
|
||||
file_padding_len = ((filesz + 511) & ~511) - filesz;
|
||||
|
||||
if (is_postgresql_auto_conf && writerecoveryconf)
|
||||
if (is_recovery_guc_supported &&
|
||||
is_postgresql_auto_conf &&
|
||||
writerecoveryconf)
|
||||
{
|
||||
/* replace tar header */
|
||||
char header[512];
|
||||
@ -1313,7 +1348,9 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
|
||||
pos += bytes2write;
|
||||
filesz -= bytes2write;
|
||||
}
|
||||
else if (is_postgresql_auto_conf && writerecoveryconf)
|
||||
else if (is_recovery_guc_supported &&
|
||||
is_postgresql_auto_conf &&
|
||||
writerecoveryconf)
|
||||
{
|
||||
/* append recovery config to postgresql.auto.conf */
|
||||
int padding;
|
||||
@ -1690,6 +1727,13 @@ GenerateRecoveryConf(PGconn *conn)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
|
||||
* standby.signal to trigger a standby state at recovery.
|
||||
*/
|
||||
if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
|
||||
appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");
|
||||
|
||||
connOptions = PQconninfo(conn);
|
||||
if (connOptions == NULL)
|
||||
{
|
||||
@ -1756,21 +1800,29 @@ GenerateRecoveryConf(PGconn *conn)
|
||||
|
||||
/*
|
||||
* Write the configuration file into the directory specified in basedir,
|
||||
* with the contents already collected in memory.
|
||||
* Then write the signal file into the basedir also.
|
||||
* with the contents already collected in memory appended. Then write
|
||||
* the signal file into the basedir. If the server does not support
|
||||
* recovery parameters as GUCs, the signal file is not necessary, and
|
||||
* configuration is written to recovery.conf.
|
||||
*/
|
||||
static void
|
||||
WriteRecoveryConf(void)
|
||||
{
|
||||
char filename[MAXPGPATH];
|
||||
FILE *cf;
|
||||
bool is_recovery_guc_supported = true;
|
||||
|
||||
snprintf(filename, MAXPGPATH, "%s/%s", basedir, "postgresql.auto.conf");
|
||||
if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
|
||||
is_recovery_guc_supported = false;
|
||||
|
||||
cf = fopen(filename, "a");
|
||||
snprintf(filename, MAXPGPATH, "%s/%s", basedir,
|
||||
is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf");
|
||||
|
||||
cf = fopen(filename, is_recovery_guc_supported ? "a" : "w");
|
||||
if (cf == NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not open file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
|
||||
progname, filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1784,15 +1836,18 @@ WriteRecoveryConf(void)
|
||||
|
||||
fclose(cf);
|
||||
|
||||
snprintf(filename, MAXPGPATH, "%s/%s", basedir, "standby.signal");
|
||||
cf = fopen(filename, "w");
|
||||
if (cf == NULL)
|
||||
if (is_recovery_guc_supported)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
snprintf(filename, MAXPGPATH, "%s/%s", basedir, "standby.signal");
|
||||
cf = fopen(filename, "w");
|
||||
if (cf == NULL)
|
||||
{
|
||||
fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(cf);
|
||||
fclose(cf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user