standby clone: handle missing "postgresql.auto.conf"

In PostgreSQL 12 and later we need to append replication configuration
to "postgresql.auto.conf" to guarantee it will be read last, and hence
override any preceding replication configuration which may be haunting
the configuration files.

We've been assuming that "postgresql.auto.conf" will always be present,
but at least one corner case has been observed where that was not the
case on the node being cloned from. Moreover it's perfectly acceptable
that this file does not exist (it will be recreated the next time
ALTER SYSTEM is executed), so we should be prepared to handle that case.

In passing, improve handling of more unlikely errors which might be
encountered when processing "postgresql.auto.conf".
This commit is contained in:
Ian Barwick
2020-10-30 12:17:45 +09:00
parent ab1447aeca
commit 7bde686796
4 changed files with 36 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
5.2.1 2020-??-??
config: fix parsing of "replication_type"
standby clone: handle missing "postgresql.auto.conf"
5.2.0 2020-10-22
general: add support for PostgreSQL 13 (Ian)

View File

@@ -107,9 +107,9 @@ ProcessRepmgrConfigFile(const char *config_file, const char *base_dir, ItemList
extern bool
ProcessPostgresConfigFile(const char *config_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list)
ProcessPostgresConfigFile(const char *config_file, const char *base_dir, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list)
{
return ProcessConfigFile(base_dir, config_file, NULL, true, 0, contents, error_list, warning_list);
return ProcessConfigFile(base_dir, config_file, NULL, strict, 0, contents, error_list, warning_list);
}
static bool

View File

@@ -1785,7 +1785,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
FILE *fp;
mode_t um;
struct stat auto_conf_st;
struct stat data_dir_st;
KeyValueList config = {NULL, NULL};
KeyValueListCell *cell = NULL;
@@ -1796,7 +1796,12 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
appendPQExpBuffer(&auto_conf, "%s/%s",
data_dir, PG_AUTOCONF_FILENAME);
success = ProcessPostgresConfigFile(auto_conf.data, NULL, &config, NULL, NULL);
success = ProcessPostgresConfigFile(auto_conf.data,
NULL,
false, /* we don't care if the file does not exist */
&config,
NULL,
NULL);
if (success == false)
{
@@ -1807,7 +1812,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
}
/*
* Append requested items to items extracted from the existing file.
* Append requested items to any items extracted from the existing file.
*/
for (cell = items->head; cell; cell = cell->next)
{
@@ -1836,27 +1841,46 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
cell->key, cell->value);
}
stat(auto_conf.data, &auto_conf_st);
/* stat the data directory for the file mode */
if (stat(data_dir, &data_dir_st) != 0)
{
/*
* This is highly unlikely to happen, but if it does (e.g. freak
* race condition with some rogue process which is messing about
* with the data directory), there's not a lot we can do.
*/
log_error(_("error encountered when checking \"%s\""),
data_dir);
log_detail("%s", strerror(errno));
exit(ERR_BAD_CONFIG);
}
/*
* Set umask so the temporary file is created in the same mode as the original
* postgresql.auto.conf file.
* Set umask so the temporary file is created in the same mode as the data
* directory. In PostgreSQL 11 and later this can be 0700 or 0750.
*/
um = umask(~(auto_conf_st.st_mode));
um = umask(~(data_dir_st.st_mode));
fp = fopen(auto_conf_tmp.data, "w");
umask(um);
if (fp == NULL)
{
fprintf(stderr, "unable to open \"%s\": %s\n",
fprintf(stderr, "unable to open \"%s\" for writing: %s\n",
auto_conf_tmp.data,
strerror(errno));
success = false;
}
else
{
if (fwrite(auto_conf_contents.data, strlen(auto_conf_contents.data), 1, fp) != 1)
{
fprintf(stderr, "unable to write to \"%s\": %s\n",
auto_conf_tmp.data,
strerror(errno));
fclose(fp);
success = false;
}
else
{

View File

@@ -373,6 +373,6 @@ extern bool modify_auto_conf(const char *data_dir, KeyValueList *items);
extern bool ProcessRepmgrConfigFile(const char *config_file, const char *base_dir, ItemList *error_list, ItemList *warning_list);
extern bool ProcessPostgresConfigFile(const char *config_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list);
extern bool ProcessPostgresConfigFile(const char *config_file, const char *base_dir, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list);
#endif /* _REPMGR_CONFIGFILE_H_ */