mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-01-09 14:45:47 +02:00
754 lines
18 KiB
C
754 lines
18 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* configure.c: - manage backup catalog.
|
|
*
|
|
* Copyright (c) 2017-2019, Postgres Professional
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "pg_probackup.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "utils/configuration.h"
|
|
#include "utils/json.h"
|
|
|
|
|
|
static void assign_log_level_console(ConfigOption *opt, const char *arg);
|
|
static void assign_log_level_file(ConfigOption *opt, const char *arg);
|
|
static void assign_compress_alg(ConfigOption *opt, const char *arg);
|
|
|
|
static char *get_log_level_console(ConfigOption *opt);
|
|
static char *get_log_level_file(ConfigOption *opt);
|
|
static char *get_compress_alg(ConfigOption *opt);
|
|
|
|
static void show_configure_start(void);
|
|
static void show_configure_end(void);
|
|
|
|
static void show_configure_plain(ConfigOption *opt);
|
|
static void show_configure_json(ConfigOption *opt);
|
|
|
|
#define RETENTION_REDUNDANCY_DEFAULT 0
|
|
#define RETENTION_WINDOW_DEFAULT 0
|
|
|
|
#define OPTION_INSTANCE_GROUP "Backup instance information"
|
|
#define OPTION_CONN_GROUP "Connection parameters"
|
|
#define OPTION_REPLICA_GROUP "Replica parameters"
|
|
#define OPTION_ARCHIVE_GROUP "Archive parameters"
|
|
#define OPTION_LOG_GROUP "Logging parameters"
|
|
#define OPTION_RETENTION_GROUP "Retention parameters"
|
|
#define OPTION_COMPRESS_GROUP "Compression parameters"
|
|
#define OPTION_REMOTE_GROUP "Remote access parameters"
|
|
|
|
/*
|
|
* Short name should be non-printable ASCII character.
|
|
*/
|
|
ConfigOption instance_options[] =
|
|
{
|
|
/* Instance options */
|
|
{
|
|
's', 'D', "pgdata",
|
|
&instance_config.pgdata, SOURCE_CMD, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'U', 200, "system-identifier",
|
|
&instance_config.system_identifier, SOURCE_FILE_STRICT, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
#if PG_VERSION_NUM >= 110000
|
|
{
|
|
'u', 201, "xlog-seg-size",
|
|
&instance_config.xlog_seg_size, SOURCE_FILE_STRICT, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
#endif
|
|
{
|
|
's', 'E', "external-dirs",
|
|
&instance_config.external_dir_str, SOURCE_CMD, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
/* Connection options */
|
|
{
|
|
's', 'd', "pgdatabase",
|
|
&instance_config.conn_opt.pgdatabase, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'h', "pghost",
|
|
&instance_config.conn_opt.pghost, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'p', "pgport",
|
|
&instance_config.conn_opt.pgport, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'U', "pguser",
|
|
&instance_config.conn_opt.pguser, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
/* Replica options */
|
|
{
|
|
's', 202, "master-db",
|
|
&instance_config.master_conn_opt.pgdatabase, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 203, "master-host",
|
|
&instance_config.master_conn_opt.pghost, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 204, "master-port",
|
|
&instance_config.master_conn_opt.pgport, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 205, "master-user",
|
|
&instance_config.master_conn_opt.pguser, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 206, "replica-timeout",
|
|
&instance_config.replica_timeout, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_REPLICA_GROUP, OPTION_UNIT_S, option_get_value
|
|
},
|
|
/* Archive options */
|
|
{
|
|
'u', 207, "archive-timeout",
|
|
&instance_config.archive_timeout, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_ARCHIVE_GROUP, OPTION_UNIT_S, option_get_value
|
|
},
|
|
{
|
|
's', 208, "archive-host",
|
|
&instance_config.archive.host, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 209, "archive-port",
|
|
&instance_config.archive.port, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 210, "archive-user",
|
|
&instance_config.archive.user, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 211, "restore-command",
|
|
&instance_config.restore_command, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
/* Logging options */
|
|
{
|
|
'f', 212, "log-level-console",
|
|
assign_log_level_console, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, get_log_level_console
|
|
},
|
|
{
|
|
'f', 213, "log-level-file",
|
|
assign_log_level_file, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, get_log_level_file
|
|
},
|
|
{
|
|
's', 214, "log-filename",
|
|
&instance_config.logger.log_filename, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 215, "error-log-filename",
|
|
&instance_config.logger.error_log_filename, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 216, "log-directory",
|
|
&instance_config.logger.log_directory, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'U', 217, "log-rotation-size",
|
|
&instance_config.logger.log_rotation_size, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_LOG_GROUP, OPTION_UNIT_KB, option_get_value
|
|
},
|
|
{
|
|
'U', 218, "log-rotation-age",
|
|
&instance_config.logger.log_rotation_age, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_LOG_GROUP, OPTION_UNIT_MS, option_get_value
|
|
},
|
|
/* Retention options */
|
|
{
|
|
'u', 219, "retention-redundancy",
|
|
&instance_config.retention_redundancy, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 220, "retention-window",
|
|
&instance_config.retention_window, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 221, "wal-depth",
|
|
&instance_config.wal_depth, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
/* Compression options */
|
|
{
|
|
'f', 222, "compress-algorithm",
|
|
assign_compress_alg, SOURCE_CMD, 0,
|
|
OPTION_COMPRESS_GROUP, 0, get_compress_alg
|
|
},
|
|
{
|
|
'u', 223, "compress-level",
|
|
&instance_config.compress_level, SOURCE_CMD, 0,
|
|
OPTION_COMPRESS_GROUP, 0, option_get_value
|
|
},
|
|
/* Remote backup options */
|
|
{
|
|
's', 224, "remote-proto",
|
|
&instance_config.remote.proto, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 225, "remote-host",
|
|
&instance_config.remote.host, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 226, "remote-port",
|
|
&instance_config.remote.port, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 227, "remote-path",
|
|
&instance_config.remote.path, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 228, "remote-user",
|
|
&instance_config.remote.user, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 229, "ssh-options",
|
|
&instance_config.remote.ssh_options, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 230, "ssh-config",
|
|
&instance_config.remote.ssh_config, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{ 0 }
|
|
};
|
|
|
|
/* An instance configuration with default options */
|
|
InstanceConfig instance_config;
|
|
|
|
static PQExpBufferData show_buf;
|
|
static int32 json_level = 0;
|
|
static const char *current_group = NULL;
|
|
|
|
/*
|
|
* Show configure options including default values.
|
|
*/
|
|
void
|
|
do_show_config(void)
|
|
{
|
|
int i;
|
|
|
|
show_configure_start();
|
|
|
|
for (i = 0; instance_options[i].type; i++)
|
|
{
|
|
if (show_format == SHOW_PLAIN)
|
|
show_configure_plain(&instance_options[i]);
|
|
else
|
|
show_configure_json(&instance_options[i]);
|
|
}
|
|
|
|
show_configure_end();
|
|
}
|
|
|
|
/*
|
|
* Save configure options into BACKUP_CATALOG_CONF_FILE. Do not save default
|
|
* values into the file.
|
|
*/
|
|
void
|
|
do_set_config(bool missing_ok)
|
|
{
|
|
char path[MAXPGPATH];
|
|
char path_temp[MAXPGPATH];
|
|
FILE *fp;
|
|
int i;
|
|
|
|
join_path_components(path, backup_instance_path, BACKUP_CATALOG_CONF_FILE);
|
|
snprintf(path_temp, sizeof(path_temp), "%s.tmp", path);
|
|
|
|
if (!missing_ok && !fileExists(path, FIO_LOCAL_HOST))
|
|
elog(ERROR, "Configuration file \"%s\" doesn't exist", path);
|
|
|
|
fp = fopen(path_temp, "wt");
|
|
if (fp == NULL)
|
|
elog(ERROR, "Cannot create configuration file \"%s\": %s",
|
|
BACKUP_CATALOG_CONF_FILE, strerror(errno));
|
|
|
|
current_group = NULL;
|
|
|
|
for (i = 0; instance_options[i].type; i++)
|
|
{
|
|
ConfigOption *opt = &instance_options[i];
|
|
char *value;
|
|
|
|
/* Save only options from command line */
|
|
if (opt->source != SOURCE_CMD &&
|
|
/* ...or options from the previous configure file */
|
|
opt->source != SOURCE_FILE && opt->source != SOURCE_FILE_STRICT)
|
|
continue;
|
|
|
|
value = opt->get_value(opt);
|
|
if (value == NULL)
|
|
continue;
|
|
|
|
if (current_group == NULL || strcmp(opt->group, current_group) != 0)
|
|
{
|
|
current_group = opt->group;
|
|
fprintf(fp, "# %s\n", current_group);
|
|
}
|
|
|
|
if (strchr(value, ' '))
|
|
fprintf(fp, "%s = '%s'\n", opt->lname, value);
|
|
else
|
|
fprintf(fp, "%s = %s\n", opt->lname, value);
|
|
pfree(value);
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
if (rename(path_temp, path) < 0)
|
|
{
|
|
int errno_temp = errno;
|
|
unlink(path_temp);
|
|
elog(ERROR, "Cannot rename configuration file \"%s\" to \"%s\": %s",
|
|
path_temp, path, strerror(errno_temp));
|
|
}
|
|
}
|
|
|
|
void
|
|
init_config(InstanceConfig *config, const char *instance_name)
|
|
{
|
|
MemSet(config, 0, sizeof(InstanceConfig));
|
|
|
|
config->name = pgut_strdup(instance_name);
|
|
|
|
/*
|
|
* Starting from PostgreSQL 11 WAL segment size may vary. Prior to
|
|
* PostgreSQL 10 xlog_seg_size is equal to XLOG_SEG_SIZE.
|
|
*/
|
|
#if PG_VERSION_NUM >= 110000
|
|
config->xlog_seg_size = 0;
|
|
#else
|
|
config->xlog_seg_size = XLOG_SEG_SIZE;
|
|
#endif
|
|
|
|
config->replica_timeout = REPLICA_TIMEOUT_DEFAULT;
|
|
|
|
config->archive_timeout = ARCHIVE_TIMEOUT_DEFAULT;
|
|
|
|
/* Copy logger defaults */
|
|
config->logger = logger_config;
|
|
|
|
config->retention_redundancy = RETENTION_REDUNDANCY_DEFAULT;
|
|
config->retention_window = RETENTION_WINDOW_DEFAULT;
|
|
config->wal_depth = 0;
|
|
|
|
config->compress_alg = COMPRESS_ALG_DEFAULT;
|
|
config->compress_level = COMPRESS_LEVEL_DEFAULT;
|
|
|
|
config->remote.proto = (char*)"ssh";
|
|
}
|
|
|
|
/*
|
|
* read instance config from file
|
|
*/
|
|
InstanceConfig *
|
|
readInstanceConfigFile(const char *instance_name)
|
|
{
|
|
char path[MAXPGPATH];
|
|
InstanceConfig *instance = pgut_new(InstanceConfig);
|
|
char *log_level_console = NULL;
|
|
char *log_level_file = NULL;
|
|
char *compress_alg = NULL;
|
|
int parsed_options;
|
|
|
|
ConfigOption instance_options[] =
|
|
{
|
|
/* Instance options */
|
|
{
|
|
's', 'D', "pgdata",
|
|
&instance->pgdata, SOURCE_CMD, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'U', 200, "system-identifier",
|
|
&instance->system_identifier, SOURCE_FILE_STRICT, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
#if PG_VERSION_NUM >= 110000
|
|
{
|
|
'u', 201, "xlog-seg-size",
|
|
&instance->xlog_seg_size, SOURCE_FILE_STRICT, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
#endif
|
|
{
|
|
's', 'E', "external-dirs",
|
|
&instance->external_dir_str, SOURCE_CMD, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
/* Connection options */
|
|
{
|
|
's', 'd', "pgdatabase",
|
|
&instance->conn_opt.pgdatabase, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'h', "pghost",
|
|
&instance->conn_opt.pghost, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'p', "pgport",
|
|
&instance->conn_opt.pgport, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 'U', "pguser",
|
|
&instance->conn_opt.pguser, SOURCE_CMD, 0,
|
|
OPTION_CONN_GROUP, 0, option_get_value
|
|
},
|
|
/* Replica options */
|
|
{
|
|
's', 202, "master-db",
|
|
&instance->master_conn_opt.pgdatabase, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 203, "master-host",
|
|
&instance->master_conn_opt.pghost, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 204, "master-port",
|
|
&instance->master_conn_opt.pgport, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 205, "master-user",
|
|
&instance->master_conn_opt.pguser, SOURCE_CMD, 0,
|
|
OPTION_REPLICA_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 206, "replica-timeout",
|
|
&instance->replica_timeout, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_REPLICA_GROUP, OPTION_UNIT_S, option_get_value
|
|
},
|
|
/* Archive options */
|
|
{
|
|
'u', 207, "archive-timeout",
|
|
&instance->archive_timeout, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_ARCHIVE_GROUP, OPTION_UNIT_S, option_get_value
|
|
},
|
|
{
|
|
's', 208, "archive-host",
|
|
&instance_config.archive.host, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 209, "archive-port",
|
|
&instance_config.archive.port, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 210, "archive-user",
|
|
&instance_config.archive.user, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 211, "restore-command",
|
|
&instance->restore_command, SOURCE_CMD, 0,
|
|
OPTION_ARCHIVE_GROUP, 0, option_get_value
|
|
},
|
|
|
|
/* Instance options */
|
|
{
|
|
's', 'D', "pgdata",
|
|
&instance->pgdata, SOURCE_CMD, 0,
|
|
OPTION_INSTANCE_GROUP, 0, option_get_value
|
|
},
|
|
|
|
/* Logging options */
|
|
{
|
|
's', 212, "log-level-console",
|
|
&log_level_console, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 213, "log-level-file",
|
|
&log_level_file, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 214, "log-filename",
|
|
&instance->logger.log_filename, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 215, "error-log-filename",
|
|
&instance->logger.error_log_filename, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 216, "log-directory",
|
|
&instance->logger.log_directory, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'U', 217, "log-rotation-size",
|
|
&instance->logger.log_rotation_size, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_LOG_GROUP, OPTION_UNIT_KB, option_get_value
|
|
},
|
|
{
|
|
'U', 218, "log-rotation-age",
|
|
&instance->logger.log_rotation_age, SOURCE_CMD, SOURCE_DEFAULT,
|
|
OPTION_LOG_GROUP, OPTION_UNIT_MS, option_get_value
|
|
},
|
|
/* Retention options */
|
|
{
|
|
'u', 219, "retention-redundancy",
|
|
&instance->retention_redundancy, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 220, "retention-window",
|
|
&instance->retention_window, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 221, "wal-depth",
|
|
&instance->wal_depth, SOURCE_CMD, 0,
|
|
OPTION_RETENTION_GROUP, 0, option_get_value
|
|
},
|
|
/* Compression options */
|
|
{
|
|
's', 222, "compress-algorithm",
|
|
&compress_alg, SOURCE_CMD, 0,
|
|
OPTION_LOG_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
'u', 223, "compress-level",
|
|
&instance->compress_level, SOURCE_CMD, 0,
|
|
OPTION_COMPRESS_GROUP, 0, option_get_value
|
|
},
|
|
/* Remote backup options */
|
|
{
|
|
's', 224, "remote-proto",
|
|
&instance->remote.proto, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 225, "remote-host",
|
|
&instance->remote.host, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 226, "remote-port",
|
|
&instance->remote.port, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 227, "remote-path",
|
|
&instance->remote.path, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 228, "remote-user",
|
|
&instance->remote.user, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 229, "ssh-options",
|
|
&instance->remote.ssh_options, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{
|
|
's', 230, "ssh-config",
|
|
&instance->remote.ssh_config, SOURCE_CMD, 0,
|
|
OPTION_REMOTE_GROUP, 0, option_get_value
|
|
},
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
init_config(instance, instance_name);
|
|
|
|
sprintf(instance->backup_instance_path, "%s/%s/%s",
|
|
backup_path, BACKUPS_DIR, instance_name);
|
|
canonicalize_path(instance->backup_instance_path);
|
|
|
|
sprintf(instance->arclog_path, "%s/%s/%s",
|
|
backup_path, "wal", instance_name);
|
|
canonicalize_path(instance->arclog_path);
|
|
|
|
join_path_components(path, instance->backup_instance_path,
|
|
BACKUP_CATALOG_CONF_FILE);
|
|
|
|
if (fio_access(path, F_OK, FIO_BACKUP_HOST) != 0)
|
|
{
|
|
elog(WARNING, "Control file \"%s\" doesn't exist", path);
|
|
pfree(instance);
|
|
return NULL;
|
|
}
|
|
|
|
parsed_options = config_read_opt(path, instance_options, WARNING, true, true);
|
|
|
|
if (parsed_options == 0)
|
|
{
|
|
elog(WARNING, "Control file \"%s\" is empty", path);
|
|
pfree(instance);
|
|
return NULL;
|
|
}
|
|
|
|
if (log_level_console)
|
|
instance->logger.log_level_console = parse_log_level(log_level_console);
|
|
|
|
if (log_level_file)
|
|
instance->logger.log_level_file = parse_log_level(log_level_file);
|
|
|
|
if (compress_alg)
|
|
instance->compress_alg = parse_compress_alg(compress_alg);
|
|
|
|
#if PG_VERSION_NUM >= 110000
|
|
/* If for some reason xlog-seg-size is missing, then set it to 16MB */
|
|
if (!instance->xlog_seg_size)
|
|
instance->xlog_seg_size = DEFAULT_XLOG_SEG_SIZE;
|
|
#endif
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
static void
|
|
assign_log_level_console(ConfigOption *opt, const char *arg)
|
|
{
|
|
instance_config.logger.log_level_console = parse_log_level(arg);
|
|
}
|
|
|
|
static void
|
|
assign_log_level_file(ConfigOption *opt, const char *arg)
|
|
{
|
|
instance_config.logger.log_level_file = parse_log_level(arg);
|
|
}
|
|
|
|
static void
|
|
assign_compress_alg(ConfigOption *opt, const char *arg)
|
|
{
|
|
instance_config.compress_alg = parse_compress_alg(arg);
|
|
}
|
|
|
|
static char *
|
|
get_log_level_console(ConfigOption *opt)
|
|
{
|
|
return pstrdup(deparse_log_level(instance_config.logger.log_level_console));
|
|
}
|
|
|
|
static char *
|
|
get_log_level_file(ConfigOption *opt)
|
|
{
|
|
return pstrdup(deparse_log_level(instance_config.logger.log_level_file));
|
|
}
|
|
|
|
static char *
|
|
get_compress_alg(ConfigOption *opt)
|
|
{
|
|
return pstrdup(deparse_compress_alg(instance_config.compress_alg));
|
|
}
|
|
|
|
/*
|
|
* Initialize configure visualization.
|
|
*/
|
|
static void
|
|
show_configure_start(void)
|
|
{
|
|
initPQExpBuffer(&show_buf);
|
|
|
|
if (show_format == SHOW_PLAIN)
|
|
current_group = NULL;
|
|
else
|
|
{
|
|
json_level = 0;
|
|
json_add(&show_buf, JT_BEGIN_OBJECT, &json_level);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Finalize configure visualization.
|
|
*/
|
|
static void
|
|
show_configure_end(void)
|
|
{
|
|
if (show_format == SHOW_PLAIN)
|
|
current_group = NULL;
|
|
else
|
|
{
|
|
json_add(&show_buf, JT_END_OBJECT, &json_level);
|
|
appendPQExpBufferChar(&show_buf, '\n');
|
|
}
|
|
|
|
fputs(show_buf.data, stdout);
|
|
termPQExpBuffer(&show_buf);
|
|
}
|
|
|
|
/*
|
|
* Plain output.
|
|
*/
|
|
|
|
static void
|
|
show_configure_plain(ConfigOption *opt)
|
|
{
|
|
char *value;
|
|
|
|
value = opt->get_value(opt);
|
|
if (value == NULL)
|
|
return;
|
|
|
|
if (current_group == NULL || strcmp(opt->group, current_group) != 0)
|
|
{
|
|
current_group = opt->group;
|
|
appendPQExpBuffer(&show_buf, "# %s\n", current_group);
|
|
}
|
|
|
|
appendPQExpBuffer(&show_buf, "%s = %s\n", opt->lname, value);
|
|
pfree(value);
|
|
}
|
|
|
|
/*
|
|
* Json output.
|
|
*/
|
|
|
|
static void
|
|
show_configure_json(ConfigOption *opt)
|
|
{
|
|
char *value;
|
|
|
|
value = opt->get_value(opt);
|
|
if (value == NULL)
|
|
return;
|
|
|
|
json_add_value(&show_buf, opt->lname, value, json_level,
|
|
true);
|
|
pfree(value);
|
|
}
|