mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 16:46:28 +00:00
Parse recovery.conf file
This will be useful for various kinds of diagnostics.
This commit is contained in:
140
configfile.c
140
configfile.c
@@ -24,7 +24,6 @@ static void _parse_line(char *buf, char *name, char *value);
|
|||||||
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
||||||
static void tablespace_list_append(t_configuration_options *options, const char *arg);
|
static void tablespace_list_append(t_configuration_options *options, const char *arg);
|
||||||
|
|
||||||
static char *trim(char *s);
|
|
||||||
|
|
||||||
static void exit_with_config_file_errors(ItemList *config_errors, ItemList *config_warnings, bool terse);
|
static void exit_with_config_file_errors(ItemList *config_errors, ItemList *config_warnings, bool terse);
|
||||||
|
|
||||||
@@ -556,6 +555,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
/* check required parameters */
|
/* check required parameters */
|
||||||
if (node_id_found == false)
|
if (node_id_found == false)
|
||||||
@@ -631,6 +631,103 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
parse_recovery_conf(const char *data_dir, t_recovery_conf *conf)
|
||||||
|
{
|
||||||
|
char recovery_conf_path[MAXPGPATH] = "";
|
||||||
|
FILE *fp;
|
||||||
|
char *s,
|
||||||
|
buf[MAXLINELENGTH];
|
||||||
|
char name[MAXLEN];
|
||||||
|
char value[MAXLEN];
|
||||||
|
|
||||||
|
snprintf(recovery_conf_path, MAXPGPATH,
|
||||||
|
"%s/%s",
|
||||||
|
data_dir,
|
||||||
|
RECOVERY_COMMAND_FILE);
|
||||||
|
|
||||||
|
fp = fopen(recovery_conf_path, "r");
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read file */
|
||||||
|
while ((s = fgets(buf, sizeof buf, fp)) != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Parse name/value pair from line */
|
||||||
|
_parse_line(buf, name, value);
|
||||||
|
|
||||||
|
/* Skip blank lines */
|
||||||
|
if (!strlen(name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip comments */
|
||||||
|
if (name[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* archive recovery settings */
|
||||||
|
if (strcmp(name, "restore_command") == 0)
|
||||||
|
strncpy(conf->restore_command, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "archive_cleanup_command") == 0)
|
||||||
|
strncpy(conf->archive_cleanup_command, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "recovery_end_command") == 0)
|
||||||
|
strncpy(conf->recovery_end_command, value, MAXLEN);
|
||||||
|
/* recovery target settings */
|
||||||
|
else if (strcmp(name, "recovery_target_name") == 0)
|
||||||
|
strncpy(conf->recovery_target_name, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "recovery_target_time") == 0)
|
||||||
|
strncpy(conf->recovery_target_time, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "recovery_target_xid") == 0)
|
||||||
|
strncpy(conf->recovery_target_xid, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "recovery_target_inclusive") == 0)
|
||||||
|
conf->recovery_target_inclusive = parse_bool(value, NULL, NULL);
|
||||||
|
else if (strcmp(name, "recovery_target_timeline") == 0)
|
||||||
|
{
|
||||||
|
if (strncmp(value, "latest", MAXLEN) == 0)
|
||||||
|
{
|
||||||
|
conf->recovery_target_timeline = TARGET_TIMELINE_LATEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conf->recovery_target_timeline = atoi(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "recovery_target_action") == 0)
|
||||||
|
{
|
||||||
|
if (strcmp(value, "pause") == 0)
|
||||||
|
conf->recovery_target_action = RTA_PAUSE;
|
||||||
|
else if (strcmp(value, "promote") == 0)
|
||||||
|
conf->recovery_target_action = RTA_PROMOTE;
|
||||||
|
else if (strcmp(value, "shutdown") == 0)
|
||||||
|
conf->recovery_target_action = RTA_SHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* standby server settings */
|
||||||
|
|
||||||
|
else if (strcmp(name, "standby_mode") == 0)
|
||||||
|
conf->standby_mode = parse_bool(value, NULL, NULL);
|
||||||
|
else if (strcmp(name, "primary_conninfo") == 0)
|
||||||
|
strncpy(conf->primary_conninfo, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "primary_slot_name") == 0)
|
||||||
|
strncpy(conf->trigger_file, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "trigger_file") == 0)
|
||||||
|
strncpy(conf->trigger_file, value, MAXLEN);
|
||||||
|
/* TODO: parse values */
|
||||||
|
/*else if (strcmp(name, "recovery_min_apply_delay") == 0)
|
||||||
|
strncpy(conf->, value, MAXLEN);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_parse_line(char *buf, char *name, char *value)
|
_parse_line(char *buf, char *name, char *value)
|
||||||
{
|
{
|
||||||
@@ -689,32 +786,6 @@ _parse_line(char *buf, char *name, char *value)
|
|||||||
trim(value);
|
trim(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
trim(char *s)
|
|
||||||
{
|
|
||||||
/* Initialize start, end pointers */
|
|
||||||
char *s1 = s,
|
|
||||||
*s2 = &s[strlen(s) - 1];
|
|
||||||
|
|
||||||
/* If string is empty, no action needed */
|
|
||||||
if (s2 < s1)
|
|
||||||
return s;
|
|
||||||
|
|
||||||
/* Trim and delimit right side */
|
|
||||||
while ((isspace(*s2)) && (s2 >= s1))
|
|
||||||
--s2;
|
|
||||||
*(s2 + 1) = '\0';
|
|
||||||
|
|
||||||
/* Trim left side */
|
|
||||||
while ((isspace(*s1)) && (s1 < s2))
|
|
||||||
++s1;
|
|
||||||
|
|
||||||
/* Copy finished string */
|
|
||||||
memmove(s, s1, s2 - s1);
|
|
||||||
s[s2 - s1 + 1] = '\0';
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -884,13 +955,16 @@ parse_bool(const char *s, const char *config_item, ItemList *error_list)
|
|||||||
if (strcasecmp(s, "yes") == 0)
|
if (strcasecmp(s, "yes") == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
initPQExpBuffer(&errors);
|
if (error_list != NULL)
|
||||||
|
{
|
||||||
|
initPQExpBuffer(&errors);
|
||||||
|
|
||||||
appendPQExpBuffer(&errors,
|
appendPQExpBuffer(&errors,
|
||||||
"\"%s\": unable to interpret '%s' as a boolean value",
|
"\"%s\": unable to interpret '%s' as a boolean value",
|
||||||
config_item, s);
|
config_item, s);
|
||||||
item_list_append(error_list, errors.data);
|
item_list_append(error_list, errors.data);
|
||||||
termPQExpBuffer(&errors);
|
termPQExpBuffer(&errors);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
53
configfile.h
53
configfile.h
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
#define CONFIG_FILE_NAME "repmgr.conf"
|
#define CONFIG_FILE_NAME "repmgr.conf"
|
||||||
#define MAXLINELENGTH 4096
|
#define MAXLINELENGTH 4096
|
||||||
|
/* magic number for use in t_recovery_conf */
|
||||||
|
#define TARGET_TIMELINE_LATEST 0
|
||||||
|
|
||||||
extern bool config_file_found;
|
extern bool config_file_found;
|
||||||
extern char config_file_path[MAXPGPATH];
|
extern char config_file_path[MAXPGPATH];
|
||||||
|
|
||||||
@@ -167,6 +170,55 @@ typedef struct
|
|||||||
#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "", false }
|
#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "", false }
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RTA_PAUSE,
|
||||||
|
RTA_PROMOTE,
|
||||||
|
RTA_SHUTDOWN
|
||||||
|
} RecoveryTargetAction;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct to hold the contents of a parsed recovery.conf file.
|
||||||
|
* We're only really interested in those related to streaming
|
||||||
|
* replication (and also "restore_command") but include the
|
||||||
|
* others for completeness.
|
||||||
|
*
|
||||||
|
* NOTE: "recovery_target" not included as it can only have
|
||||||
|
* one value, "immediate".
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* archive recovery settings */
|
||||||
|
char restore_command[MAXLEN];
|
||||||
|
char archive_cleanup_command[MAXLEN];
|
||||||
|
char recovery_end_command[MAXLEN];
|
||||||
|
/* recovery target settings */
|
||||||
|
char recovery_target_name[MAXLEN];
|
||||||
|
char recovery_target_time[MAXLEN];
|
||||||
|
char recovery_target_xid[MAXLEN];
|
||||||
|
bool recovery_target_inclusive;
|
||||||
|
int recovery_target_timeline;
|
||||||
|
RecoveryTargetAction recovery_target_action; /* default: RTA_PAUSE */
|
||||||
|
/* standby server settings */
|
||||||
|
bool standby_mode;
|
||||||
|
char primary_conninfo[MAXLEN];
|
||||||
|
char primary_slot_name[MAXLEN];
|
||||||
|
char trigger_file[MAXLEN];
|
||||||
|
int recovery_min_apply_delay;
|
||||||
|
} t_recovery_conf;
|
||||||
|
|
||||||
|
#define T_RECOVERY_CONF_INITIALIZER { \
|
||||||
|
/* archive recovery settings */ \
|
||||||
|
"", "", "", \
|
||||||
|
/* recovery target settings */ \
|
||||||
|
"", "", "", true, \
|
||||||
|
TARGET_TIMELINE_LATEST, \
|
||||||
|
RTA_PAUSE, \
|
||||||
|
/* standby server settings */ \
|
||||||
|
true, \
|
||||||
|
"", "", "", 0 \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void set_progname(const char *argv0);
|
void set_progname(const char *argv0);
|
||||||
const char *progname(void);
|
const char *progname(void);
|
||||||
@@ -175,6 +227,7 @@ void load_config(const char *config_file, bool verbose, bool terse, t_configura
|
|||||||
void parse_config(t_configuration_options *options, bool terse);
|
void parse_config(t_configuration_options *options, bool terse);
|
||||||
bool reload_config(t_configuration_options *orig_options);
|
bool reload_config(t_configuration_options *orig_options);
|
||||||
|
|
||||||
|
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
||||||
|
|
||||||
int repmgr_atoi(const char *s,
|
int repmgr_atoi(const char *s,
|
||||||
const char *config_item,
|
const char *config_item,
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ do_node_status(void)
|
|||||||
ItemList warnings = { NULL, NULL };
|
ItemList warnings = { NULL, NULL };
|
||||||
RecoveryType recovery_type;
|
RecoveryType recovery_type;
|
||||||
ReplInfo replication_info = T_REPLINFO_INTIALIZER;
|
ReplInfo replication_info = T_REPLINFO_INTIALIZER;
|
||||||
|
t_recovery_conf recovery_conf = T_RECOVERY_CONF_INITIALIZER;
|
||||||
|
|
||||||
|
char data_dir[MAXPGPATH] = "";
|
||||||
|
|
||||||
|
|
||||||
if (runtime_options.is_shutdown == true)
|
if (runtime_options.is_shutdown == true)
|
||||||
{
|
{
|
||||||
@@ -57,6 +61,16 @@ do_node_status(void)
|
|||||||
else
|
else
|
||||||
conn = establish_db_connection_by_params(&source_conninfo, true);
|
conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||||
|
|
||||||
|
if (config_file_options.data_directory[0] != '\0')
|
||||||
|
{
|
||||||
|
strncpy(data_dir, config_file_options.data_directory, MAXPGPATH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* requires superuser */
|
||||||
|
get_pg_setting(conn, "data_directory", data_dir);
|
||||||
|
}
|
||||||
|
|
||||||
server_version_num = get_server_version(conn, NULL);
|
server_version_num = get_server_version(conn, NULL);
|
||||||
|
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
||||||
@@ -180,19 +194,8 @@ do_node_status(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char data_dir[MAXPGPATH] = "";
|
|
||||||
int ready_files;
|
int ready_files;
|
||||||
|
|
||||||
if (config_file_options.data_directory[0] != '\0')
|
|
||||||
{
|
|
||||||
strncpy(data_dir, config_file_options.data_directory, MAXPGPATH);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* requires superuser */
|
|
||||||
get_pg_setting(conn, "data_directory", data_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
ready_files = get_ready_archive_files(conn, data_dir);
|
ready_files = get_ready_archive_files(conn, data_dir);
|
||||||
|
|
||||||
key_value_list_set_format(
|
key_value_list_set_format(
|
||||||
@@ -317,6 +320,10 @@ do_node_status(void)
|
|||||||
key_value_list_set_output_mode(&node_status, "Last replayed LSN", OM_CSV);
|
key_value_list_set_output_mode(&node_status, "Last replayed LSN", OM_CSV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
parse_recovery_conf(data_dir, &recovery_conf);
|
||||||
|
|
||||||
|
/* format output */
|
||||||
initPQExpBuffer(&output);
|
initPQExpBuffer(&output);
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
|
|||||||
28
strutil.c
28
strutil.c
@@ -255,3 +255,31 @@ string_remove_trailing_newlines(char *string)
|
|||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
trim(char *s)
|
||||||
|
{
|
||||||
|
/* Initialize start, end pointers */
|
||||||
|
char *s1 = s,
|
||||||
|
*s2 = &s[strlen(s) - 1];
|
||||||
|
|
||||||
|
/* If string is empty, no action needed */
|
||||||
|
if (s2 < s1)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
/* Trim and delimit right side */
|
||||||
|
while ((isspace(*s2)) && (s2 >= s1))
|
||||||
|
--s2;
|
||||||
|
*(s2 + 1) = '\0';
|
||||||
|
|
||||||
|
/* Trim left side */
|
||||||
|
while ((isspace(*s1)) && (s1 < s2))
|
||||||
|
++s1;
|
||||||
|
|
||||||
|
/* Copy finished string */
|
||||||
|
memmove(s, s1, s2 - s1);
|
||||||
|
s[s2 - s1 + 1] = '\0';
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user