mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-27 00:46:29 +00:00
pgindent run
This commit is contained in:
1
compat.c
1
compat.c
@@ -104,4 +104,3 @@ appendShellString(PQExpBuffer buf, const char *str)
|
|||||||
|
|
||||||
appendPQExpBufferChar(buf, '\'');
|
appendPQExpBufferChar(buf, '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
compat.h
6
compat.h
@@ -23,10 +23,8 @@
|
|||||||
#ifndef _COMPAT_H_
|
#ifndef _COMPAT_H_
|
||||||
#define _COMPAT_H_
|
#define _COMPAT_H_
|
||||||
|
|
||||||
extern void
|
extern void appendConnStrVal(PQExpBuffer buf, const char *str);
|
||||||
appendConnStrVal(PQExpBuffer buf, const char *str);
|
|
||||||
|
|
||||||
extern void
|
extern void appendShellString(PQExpBuffer buf, const char *str);
|
||||||
appendShellString(PQExpBuffer buf, const char *str);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
186
configfile.c
186
configfile.c
@@ -24,25 +24,25 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
const static char *_progname = NULL;
|
const static char *_progname = NULL;
|
||||||
char config_file_path[MAXPGPATH] = "";
|
char config_file_path[MAXPGPATH] = "";
|
||||||
static bool config_file_provided = false;
|
static bool config_file_provided = false;
|
||||||
bool config_file_found = false;
|
bool config_file_found = false;
|
||||||
|
|
||||||
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||||
static bool parse_bool(const char *s,
|
static bool parse_bool(const char *s,
|
||||||
const char *config_item,
|
const char *config_item,
|
||||||
ItemList *error_list);
|
ItemList *error_list);
|
||||||
|
|
||||||
static void _parse_line(char *buf, char *name, char *value);
|
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 clear_event_notification_list(t_configuration_options *options);
|
static void clear_event_notification_list(t_configuration_options *options);
|
||||||
|
|
||||||
static void parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemList *errors);
|
static void parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemList *errors);
|
||||||
|
|
||||||
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 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);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -63,10 +63,10 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
struct stat stat_config;
|
struct stat stat_config;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a configuration file was provided, check it exists, otherwise
|
* If a configuration file was provided, check it exists, otherwise emit
|
||||||
* emit an error and terminate. We assume that if a user explicitly
|
* an error and terminate. We assume that if a user explicitly provides a
|
||||||
* provides a configuration file, they'll want to make sure it's
|
* configuration file, they'll want to make sure it's used and not fall
|
||||||
* used and not fall back to any of the defaults.
|
* back to any of the defaults.
|
||||||
*/
|
*/
|
||||||
if (config_file != NULL && config_file[0] != '\0')
|
if (config_file != NULL && config_file[0] != '\0')
|
||||||
{
|
{
|
||||||
@@ -76,8 +76,8 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
if (stat(config_file_path, &stat_config) != 0)
|
if (stat(config_file_path, &stat_config) != 0)
|
||||||
{
|
{
|
||||||
log_error(_("provided configuration file \"%s\" not found: %s"),
|
log_error(_("provided configuration file \"%s\" not found: %s"),
|
||||||
config_file,
|
config_file,
|
||||||
strerror(errno)
|
strerror(errno)
|
||||||
);
|
);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -92,18 +92,19 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*-----------
|
||||||
* If no configuration file was provided, attempt to find a default file
|
* If no configuration file was provided, attempt to find a default file
|
||||||
* in this order:
|
* in this order:
|
||||||
* - current directory
|
* - current directory
|
||||||
* - /etc/repmgr.conf
|
* - /etc/repmgr.conf
|
||||||
* - default sysconfdir
|
* - default sysconfdir
|
||||||
*
|
*
|
||||||
* here we just check for the existence of the file; parse_config()
|
* here we just check for the existence of the file; parse_config() will
|
||||||
* will handle read errors etc.
|
* handle read errors etc.
|
||||||
*
|
*
|
||||||
* XXX modify this section so package maintainers can provide a patch
|
* XXX modify this section so package maintainers can provide a patch
|
||||||
* specifying location of a distribution-specific configuration file
|
* specifying location of a distribution-specific configuration file
|
||||||
|
*-----------
|
||||||
*/
|
*/
|
||||||
if (config_file_provided == false)
|
if (config_file_provided == false)
|
||||||
{
|
{
|
||||||
@@ -159,7 +160,7 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
goto end_search;
|
goto end_search;
|
||||||
}
|
}
|
||||||
|
|
||||||
end_search:
|
end_search:
|
||||||
if (config_file_found == true)
|
if (config_file_found == true)
|
||||||
{
|
{
|
||||||
if (verbose == true)
|
if (verbose == true)
|
||||||
@@ -186,8 +187,8 @@ void
|
|||||||
parse_config(t_configuration_options *options, bool terse)
|
parse_config(t_configuration_options *options, bool terse)
|
||||||
{
|
{
|
||||||
/* Collate configuration file errors here for friendlier reporting */
|
/* Collate configuration file errors here for friendlier reporting */
|
||||||
static ItemList config_errors = { NULL, NULL };
|
static ItemList config_errors = {NULL, NULL};
|
||||||
static ItemList config_warnings = { NULL, NULL };
|
static ItemList config_warnings = {NULL, NULL};
|
||||||
|
|
||||||
_parse_config(options, &config_errors, &config_warnings);
|
_parse_config(options, &config_errors, &config_warnings);
|
||||||
|
|
||||||
@@ -273,7 +274,8 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
/* default to 6 reconnection attempts at intervals of 10 seconds */
|
/* default to 6 reconnection attempts at intervals of 10 seconds */
|
||||||
options->reconnect_attempts = DEFAULT_RECONNECTION_ATTEMPTS;
|
options->reconnect_attempts = DEFAULT_RECONNECTION_ATTEMPTS;
|
||||||
options->reconnect_interval = DEFAULT_RECONNECTION_INTERVAL;
|
options->reconnect_interval = DEFAULT_RECONNECTION_INTERVAL;
|
||||||
options->monitoring_history = false; /* new in 4.0, replaces --monitoring-history */
|
options->monitoring_history = false; /* new in 4.0, replaces
|
||||||
|
* --monitoring-history */
|
||||||
options->degraded_monitoring_timeout = -1;
|
options->degraded_monitoring_timeout = -1;
|
||||||
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
||||||
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
||||||
@@ -326,16 +328,16 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
{
|
{
|
||||||
log_verbose(LOG_NOTICE,
|
log_verbose(LOG_NOTICE,
|
||||||
_("no configuration file provided and no default file found - "
|
_("no configuration file provided and no default file found - "
|
||||||
"continuing with default values"));
|
"continuing with default values"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = fopen(config_file_path, "r");
|
fp = fopen(config_file_path, "r");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A configuration file has been found, either provided by the user
|
* A configuration file has been found, either provided by the user or
|
||||||
* or found in one of the default locations. If we can't open it,
|
* found in one of the default locations. If we can't open it, fail with
|
||||||
* fail with an error.
|
* an error.
|
||||||
*/
|
*/
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
@@ -347,7 +349,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error(_("unable to open default configuration file \"%s\"; terminating"),
|
log_error(_("unable to open default configuration file \"%s\"; terminating"),
|
||||||
config_file_path);
|
config_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -356,7 +358,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
/* Read file */
|
/* Read file */
|
||||||
while ((s = fgets(buf, sizeof buf, fp)) != NULL)
|
while ((s = fgets(buf, sizeof buf, fp)) != NULL)
|
||||||
{
|
{
|
||||||
bool known_parameter = true;
|
bool known_parameter = true;
|
||||||
|
|
||||||
/* Parse name/value pair from line */
|
/* Parse name/value pair from line */
|
||||||
_parse_line(buf, name, value);
|
_parse_line(buf, name, value);
|
||||||
@@ -387,7 +389,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
strncpy(options->replication_user, value, NAMEDATALEN);
|
strncpy(options->replication_user, value, NAMEDATALEN);
|
||||||
else
|
else
|
||||||
item_list_append(error_list,
|
item_list_append(error_list,
|
||||||
_( "value for \"replication_user\" must contain fewer than " STR(NAMEDATALEN) " characters"));
|
_("value for \"replication_user\" must contain fewer than " STR(NAMEDATALEN) " characters"));
|
||||||
}
|
}
|
||||||
else if (strcmp(name, "pg_bindir") == 0)
|
else if (strcmp(name, "pg_bindir") == 0)
|
||||||
strncpy(options->pg_bindir, value, MAXPGPATH);
|
strncpy(options->pg_bindir, value, MAXPGPATH);
|
||||||
@@ -524,7 +526,10 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else if (strcmp(name, "promote_delay") == 0)
|
else if (strcmp(name, "promote_delay") == 0)
|
||||||
options->promote_delay = repmgr_atoi(value, name, error_list, 1);
|
options->promote_delay = repmgr_atoi(value, name, error_list, 1);
|
||||||
|
|
||||||
/* Following parameters have been deprecated or renamed from 3.x - issue a warning */
|
/*
|
||||||
|
* Following parameters have been deprecated or renamed from 3.x -
|
||||||
|
* issue a warning
|
||||||
|
*/
|
||||||
else if (strcmp(name, "cluster") == 0)
|
else if (strcmp(name, "cluster") == 0)
|
||||||
{
|
{
|
||||||
item_list_append(warning_list,
|
item_list_append(warning_list,
|
||||||
@@ -578,14 +583,18 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
known_parameter = false;
|
known_parameter = false;
|
||||||
log_warning(_("%s/%s: unknown name/value pair provided; ignoring"), name, value);
|
log_warning(_("%s/%s: unknown name/value pair provided; ignoring"), name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Raise an error if a known parameter is provided with an empty value.
|
* Raise an error if a known parameter is provided with an empty
|
||||||
* Currently there's no reason why empty parameters are needed; if
|
* value. Currently there's no reason why empty parameters are needed;
|
||||||
* we want to accept those, we'd need to add stricter default checking,
|
* if we want to accept those, we'd need to add stricter default
|
||||||
* as currently e.g. an empty `node` value will be converted to '0'.
|
* checking, as currently e.g. an empty `node` value will be converted
|
||||||
|
* to '0'.
|
||||||
*/
|
*/
|
||||||
if (known_parameter == true && !strlen(value)) {
|
if (known_parameter == true && !strlen(value))
|
||||||
char error_message_buf[MAXLEN] = "";
|
{
|
||||||
|
char error_message_buf[MAXLEN] = "";
|
||||||
|
|
||||||
maxlen_snprintf(error_message_buf,
|
maxlen_snprintf(error_message_buf,
|
||||||
_("\"%s\": no value provided"),
|
_("\"%s\": no value provided"),
|
||||||
name);
|
name);
|
||||||
@@ -618,10 +627,11 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Sanity check the provided conninfo string
|
/*
|
||||||
|
* Sanity check the provided conninfo string
|
||||||
*
|
*
|
||||||
* NOTE: PQconninfoParse() verifies the string format and checks for valid options
|
* NOTE: PQconninfoParse() verifies the string format and checks for
|
||||||
* but does not sanity check values
|
* valid options but does not sanity check values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PQconninfoOption *conninfo_options = NULL;
|
PQconninfoOption *conninfo_options = NULL;
|
||||||
@@ -630,7 +640,8 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg);
|
conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg);
|
||||||
if (conninfo_options == NULL)
|
if (conninfo_options == NULL)
|
||||||
{
|
{
|
||||||
char error_message_buf[MAXLEN] = "";
|
char error_message_buf[MAXLEN] = "";
|
||||||
|
|
||||||
snprintf(error_message_buf,
|
snprintf(error_message_buf,
|
||||||
MAXLEN,
|
MAXLEN,
|
||||||
_("\"conninfo\": %s (provided: \"%s\")"),
|
_("\"conninfo\": %s (provided: \"%s\")"),
|
||||||
@@ -662,7 +673,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
_("\archive_ready_critical\" must be greater than \"archive_ready_warning\""));
|
_("\archive_ready_critical\" must be greater than \"archive_ready_warning\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if( options->replication_lag_warning >= options->replication_lag_critical)
|
if (options->replication_lag_warning >= options->replication_lag_critical)
|
||||||
{
|
{
|
||||||
item_list_append(error_list,
|
item_list_append(error_list,
|
||||||
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
||||||
@@ -675,7 +686,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
bool
|
bool
|
||||||
parse_recovery_conf(const char *data_dir, t_recovery_conf *conf)
|
parse_recovery_conf(const char *data_dir, t_recovery_conf *conf)
|
||||||
{
|
{
|
||||||
char recovery_conf_path[MAXPGPATH] = "";
|
char recovery_conf_path[MAXPGPATH] = "";
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *s = NULL,
|
char *s = NULL,
|
||||||
buf[MAXLINELENGTH] = "";
|
buf[MAXLINELENGTH] = "";
|
||||||
@@ -780,9 +791,9 @@ _parse_line(char *buf, char *name, char *value)
|
|||||||
if (buf[i] == '=')
|
if (buf[i] == '=')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch(buf[i])
|
switch (buf[i])
|
||||||
{
|
{
|
||||||
/* Ignore whitespace */
|
/* Ignore whitespace */
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
@@ -799,9 +810,9 @@ _parse_line(char *buf, char *name, char *value)
|
|||||||
*/
|
*/
|
||||||
for (; i < MAXLEN; ++i)
|
for (; i < MAXLEN; ++i)
|
||||||
{
|
{
|
||||||
if (buf[i+1] == ' ')
|
if (buf[i + 1] == ' ')
|
||||||
continue;
|
continue;
|
||||||
if (buf[i+1] == '\t')
|
if (buf[i + 1] == '\t')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -828,17 +839,17 @@ _parse_line(char *buf, char *name, char *value)
|
|||||||
static void
|
static void
|
||||||
parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemList *errors)
|
parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemList *errors)
|
||||||
{
|
{
|
||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
int targ = strtol(value, &ptr, 10);
|
int targ = strtol(value, &ptr, 10);
|
||||||
|
|
||||||
if (targ < 1)
|
if (targ < 1)
|
||||||
{
|
{
|
||||||
if (errors != NULL)
|
if (errors != NULL)
|
||||||
{
|
{
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
errors,
|
errors,
|
||||||
_("invalid value provided for \"%s\""),
|
_("invalid value provided for \"%s\""),
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -852,9 +863,9 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
if (errors != NULL)
|
if (errors != NULL)
|
||||||
{
|
{
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
errors,
|
errors,
|
||||||
_("value provided for \"%s\" must be one of ms/s/min/h/d"),
|
_("value provided for \"%s\" must be one of ms/s/min/h/d"),
|
||||||
name);
|
name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -909,11 +920,11 @@ reload_config(t_configuration_options *orig_options)
|
|||||||
{
|
{
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
t_configuration_options new_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options new_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
bool config_changed = false;
|
bool config_changed = false;
|
||||||
bool log_config_changed = false;
|
bool log_config_changed = false;
|
||||||
|
|
||||||
static ItemList config_errors = { NULL, NULL };
|
static ItemList config_errors = {NULL, NULL};
|
||||||
static ItemList config_warnings = { NULL, NULL };
|
static ItemList config_warnings = {NULL, NULL};
|
||||||
|
|
||||||
log_info(_("reloading configuration file"));
|
log_info(_("reloading configuration file"));
|
||||||
|
|
||||||
@@ -980,7 +991,7 @@ reload_config(t_configuration_options *orig_options)
|
|||||||
/* conninfo */
|
/* conninfo */
|
||||||
if (strcmp(orig_options->conninfo, new_options.conninfo) != 0)
|
if (strcmp(orig_options->conninfo, new_options.conninfo) != 0)
|
||||||
{
|
{
|
||||||
/* Test conninfo string works*/
|
/* Test conninfo string works */
|
||||||
conn = establish_db_connection(new_options.conninfo, false);
|
conn = establish_db_connection(new_options.conninfo, false);
|
||||||
if (!conn || (PQstatus(conn) != CONNECTION_OK))
|
if (!conn || (PQstatus(conn) != CONNECTION_OK))
|
||||||
{
|
{
|
||||||
@@ -1228,13 +1239,14 @@ print_item_list(ItemList *item_list)
|
|||||||
int
|
int
|
||||||
repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, int minval)
|
repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, int minval)
|
||||||
{
|
{
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
long longval = 0;
|
long longval = 0;
|
||||||
PQExpBufferData errors;
|
PQExpBufferData errors;
|
||||||
|
|
||||||
initPQExpBuffer(&errors);
|
initPQExpBuffer(&errors);
|
||||||
|
|
||||||
/* It's possible that some versions of strtol() don't treat an empty
|
/*
|
||||||
|
* It's possible that some versions of strtol() don't treat an empty
|
||||||
* string as an error.
|
* string as an error.
|
||||||
*/
|
*/
|
||||||
if (*value == '\0')
|
if (*value == '\0')
|
||||||
@@ -1253,14 +1265,14 @@ repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, in
|
|||||||
_("\"%s\": invalid value (provided: \"%s\")"),
|
_("\"%s\": invalid value (provided: \"%s\")"),
|
||||||
config_item, value);
|
config_item, value);
|
||||||
}
|
}
|
||||||
else if ((int32)longval < longval)
|
else if ((int32) longval < longval)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&errors,
|
appendPQExpBuffer(&errors,
|
||||||
_("\"%s\": must be a positive signed 32 bit integer, i.e. 2147483647 or less (provided: \"%s\")"),
|
_("\"%s\": must be a positive signed 32 bit integer, i.e. 2147483647 or less (provided: \"%s\")"),
|
||||||
config_item,
|
config_item,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
else if ((int32)longval < minval)
|
else if ((int32) longval < minval)
|
||||||
/* Disallow negative values for most parameters */
|
/* Disallow negative values for most parameters */
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&errors,
|
appendPQExpBuffer(&errors,
|
||||||
@@ -1399,7 +1411,7 @@ tablespace_list_append(t_configuration_options *options, const char *arg)
|
|||||||
if (!*cell->old_dir || !*cell->new_dir)
|
if (!*cell->old_dir || !*cell->new_dir)
|
||||||
{
|
{
|
||||||
log_error(_("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\""),
|
log_error(_("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\""),
|
||||||
arg);
|
arg);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1505,20 +1517,21 @@ clear_event_notification_list(t_configuration_options *options)
|
|||||||
bool
|
bool
|
||||||
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
||||||
{
|
{
|
||||||
int options_len = 0;
|
int options_len = 0;
|
||||||
char *options_string = NULL;
|
char *options_string = NULL;
|
||||||
char *options_string_ptr = NULL;
|
char *options_string_ptr = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add parsed options to this list, then copy to an array
|
* Add parsed options to this list, then copy to an array to pass to
|
||||||
* to pass to getopt
|
* getopt
|
||||||
*/
|
*/
|
||||||
static ItemList option_argv = { NULL, NULL };
|
static ItemList option_argv = {NULL, NULL};
|
||||||
|
|
||||||
char *argv_item = NULL;
|
char *argv_item = NULL;
|
||||||
int c, argc_item = 1;
|
int c,
|
||||||
|
argc_item = 1;
|
||||||
|
|
||||||
char **argv_array = NULL;
|
char **argv_array = NULL;
|
||||||
ItemListCell *cell = NULL;
|
ItemListCell *cell = NULL;
|
||||||
|
|
||||||
int optindex = 0;
|
int optindex = 0;
|
||||||
@@ -1536,8 +1549,8 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From PostgreSQL 10, --xlog-method is renamed --wal-method
|
* From PostgreSQL 10, --xlog-method is renamed --wal-method and there's
|
||||||
* and there's also --no-slot, which we'll want to consider.
|
* also --no-slot, which we'll want to consider.
|
||||||
*/
|
*/
|
||||||
static struct option long_options_10[] =
|
static struct option long_options_10[] =
|
||||||
{
|
{
|
||||||
@@ -1576,8 +1589,8 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Array of argument values to pass to getopt_long - this will need to
|
* Array of argument values to pass to getopt_long - this will need to
|
||||||
* include an empty string as the first value (normally this would be
|
* include an empty string as the first value (normally this would be the
|
||||||
* the program name)
|
* program name)
|
||||||
*/
|
*/
|
||||||
argv_array = pg_malloc0(sizeof(char *) * (argc_item + 2));
|
argv_array = pg_malloc0(sizeof(char *) * (argc_item + 2));
|
||||||
|
|
||||||
@@ -1591,7 +1604,7 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti
|
|||||||
*/
|
*/
|
||||||
for (cell = option_argv.head; cell; cell = cell->next)
|
for (cell = option_argv.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
int argv_len = strlen(cell->string) + 1;
|
int argv_len = strlen(cell->string) + 1;
|
||||||
|
|
||||||
argv_array[c] = pg_malloc0(argv_len);
|
argv_array[c] = pg_malloc0(argv_len);
|
||||||
|
|
||||||
@@ -1647,8 +1660,9 @@ parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_opti
|
|||||||
pfree(options_string);
|
pfree(options_string);
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < argc_item + 2; i ++)
|
|
||||||
|
for (i = 0; i < argc_item + 2; i++)
|
||||||
pfree(argv_array[i]);
|
pfree(argv_array[i]);
|
||||||
}
|
}
|
||||||
pfree(argv_array);
|
pfree(argv_array);
|
||||||
|
|||||||
70
configfile.h
70
configfile.h
@@ -28,18 +28,19 @@
|
|||||||
/* magic number for use in t_recovery_conf */
|
/* magic number for use in t_recovery_conf */
|
||||||
#define TARGET_TIMELINE_LATEST 0
|
#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];
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
FAILOVER_MANUAL,
|
FAILOVER_MANUAL,
|
||||||
FAILOVER_AUTOMATIC
|
FAILOVER_AUTOMATIC
|
||||||
} failover_mode_opt;
|
} failover_mode_opt;
|
||||||
|
|
||||||
typedef struct EventNotificationListCell
|
typedef struct EventNotificationListCell
|
||||||
{
|
{
|
||||||
struct EventNotificationListCell *next;
|
struct EventNotificationListCell *next;
|
||||||
char event_type[MAXLEN];
|
char event_type[MAXLEN];
|
||||||
} EventNotificationListCell;
|
} EventNotificationListCell;
|
||||||
|
|
||||||
typedef struct EventNotificationList
|
typedef struct EventNotificationList
|
||||||
@@ -67,7 +68,7 @@ typedef struct TablespaceList
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* node information */
|
/* node information */
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
char replication_user[NAMEDATALEN];
|
char replication_user[NAMEDATALEN];
|
||||||
@@ -98,7 +99,7 @@ typedef struct
|
|||||||
int replication_lag_critical;
|
int replication_lag_critical;
|
||||||
|
|
||||||
/* repmgrd settings */
|
/* repmgrd settings */
|
||||||
failover_mode_opt failover;
|
failover_mode_opt failover;
|
||||||
char location[MAXLEN];
|
char location[MAXLEN];
|
||||||
int priority;
|
int priority;
|
||||||
char promote_command[MAXLEN];
|
char promote_command[MAXLEN];
|
||||||
@@ -136,7 +137,7 @@ typedef struct
|
|||||||
|
|
||||||
/* undocumented test settings */
|
/* undocumented test settings */
|
||||||
int promote_delay;
|
int promote_delay;
|
||||||
} t_configuration_options;
|
} t_configuration_options;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following will initialize the structure with a minimal set of options;
|
* The following will initialize the structure with a minimal set of options;
|
||||||
@@ -180,13 +181,14 @@ typedef struct
|
|||||||
{
|
{
|
||||||
char slot[MAXLEN];
|
char slot[MAXLEN];
|
||||||
char xlog_method[MAXLEN];
|
char xlog_method[MAXLEN];
|
||||||
bool no_slot; /* from PostgreSQL 10 */
|
bool no_slot; /* from PostgreSQL 10 */
|
||||||
} t_basebackup_options;
|
} t_basebackup_options;
|
||||||
|
|
||||||
#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "", false }
|
#define T_BASEBACKUP_OPTIONS_INITIALIZER { "", "", false }
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
RTA_PAUSE,
|
RTA_PAUSE,
|
||||||
RTA_PROMOTE,
|
RTA_PROMOTE,
|
||||||
RTA_SHUTDOWN
|
RTA_SHUTDOWN
|
||||||
@@ -204,22 +206,22 @@ typedef enum {
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* archive recovery settings */
|
/* archive recovery settings */
|
||||||
char restore_command[MAXLEN];
|
char restore_command[MAXLEN];
|
||||||
char archive_cleanup_command[MAXLEN];
|
char archive_cleanup_command[MAXLEN];
|
||||||
char recovery_end_command[MAXLEN];
|
char recovery_end_command[MAXLEN];
|
||||||
/* recovery target settings */
|
/* recovery target settings */
|
||||||
char recovery_target_name[MAXLEN];
|
char recovery_target_name[MAXLEN];
|
||||||
char recovery_target_time[MAXLEN];
|
char recovery_target_time[MAXLEN];
|
||||||
char recovery_target_xid[MAXLEN];
|
char recovery_target_xid[MAXLEN];
|
||||||
bool recovery_target_inclusive;
|
bool recovery_target_inclusive;
|
||||||
int recovery_target_timeline;
|
int recovery_target_timeline;
|
||||||
RecoveryTargetAction recovery_target_action; /* default: RTA_PAUSE */
|
RecoveryTargetAction recovery_target_action; /* default: RTA_PAUSE */
|
||||||
/* standby server settings */
|
/* standby server settings */
|
||||||
bool standby_mode;
|
bool standby_mode;
|
||||||
char primary_conninfo[MAXLEN];
|
char primary_conninfo[MAXLEN];
|
||||||
char primary_slot_name[MAXLEN];
|
char primary_slot_name[MAXLEN];
|
||||||
char trigger_file[MAXLEN];
|
char trigger_file[MAXLEN];
|
||||||
char recovery_min_apply_delay[MAXLEN];
|
char recovery_min_apply_delay[MAXLEN];
|
||||||
} t_recovery_conf;
|
} t_recovery_conf;
|
||||||
|
|
||||||
#define T_RECOVERY_CONF_INITIALIZER { \
|
#define T_RECOVERY_CONF_INITIALIZER { \
|
||||||
@@ -245,19 +247,19 @@ bool reload_config(t_configuration_options *orig_options);
|
|||||||
|
|
||||||
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
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,
|
||||||
ItemList *error_list,
|
ItemList *error_list,
|
||||||
int minval);
|
int minval);
|
||||||
|
|
||||||
|
|
||||||
bool parse_pg_basebackup_options(const char *pg_basebackup_options,
|
bool parse_pg_basebackup_options(const char *pg_basebackup_options,
|
||||||
t_basebackup_options *backup_options,
|
t_basebackup_options *backup_options,
|
||||||
int server_version_num,
|
int server_version_num,
|
||||||
ItemList *error_list);
|
ItemList *error_list);
|
||||||
|
|
||||||
/* called by repmgr-client and repmgrd */
|
/* called by repmgr-client and repmgrd */
|
||||||
void exit_with_cli_errors(ItemList *error_list);
|
void exit_with_cli_errors(ItemList *error_list);
|
||||||
void print_item_list(ItemList *item_list);
|
void print_item_list(ItemList *item_list);
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ uint64
|
|||||||
get_system_identifier(const char *data_directory)
|
get_system_identifier(const char *data_directory)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info = NULL;
|
ControlFileInfo *control_file_info = NULL;
|
||||||
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ DBState
|
|||||||
get_db_state(const char *data_directory)
|
get_db_state(const char *data_directory)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info = NULL;
|
ControlFileInfo *control_file_info = NULL;
|
||||||
DBState state;
|
DBState state;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ extern XLogRecPtr
|
|||||||
get_latest_checkpoint_location(const char *data_directory)
|
get_latest_checkpoint_location(const char *data_directory)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info = NULL;
|
ControlFileInfo *control_file_info = NULL;
|
||||||
XLogRecPtr checkPoint = InvalidXLogRecPtr;
|
XLogRecPtr checkPoint = InvalidXLogRecPtr;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ int
|
|||||||
get_data_checksum_version(const char *data_directory)
|
get_data_checksum_version(const char *data_directory)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info = NULL;
|
ControlFileInfo *control_file_info = NULL;
|
||||||
int data_checksum_version = -1;
|
int data_checksum_version = -1;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ get_data_checksum_version(const char *data_directory)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data_checksum_version = (int)control_file_info->control_file->data_checksum_version;
|
data_checksum_version = (int) control_file_info->control_file->data_checksum_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(control_file_info->control_file);
|
pfree(control_file_info->control_file);
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool control_file_processed;
|
bool control_file_processed;
|
||||||
ControlFileData *control_file;
|
ControlFileData *control_file;
|
||||||
} ControlFileInfo;
|
} ControlFileInfo;
|
||||||
|
|
||||||
extern DBState get_db_state(const char *data_directory);
|
extern DBState get_db_state(const char *data_directory);
|
||||||
extern const char * describe_db_state(DBState state);
|
extern const char *describe_db_state(DBState state);
|
||||||
extern int get_data_checksum_version(const char *data_directory);
|
extern int get_data_checksum_version(const char *data_directory);
|
||||||
extern uint64 get_system_identifier(const char *data_directory);
|
extern uint64 get_system_identifier(const char *data_directory);
|
||||||
extern XLogRecPtr get_latest_checkpoint_location(const char *data_directory);
|
extern XLogRecPtr get_latest_checkpoint_location(const char *data_directory);
|
||||||
|
|
||||||
#endif /* _CONTROLDATA_H_ */
|
#endif /* _CONTROLDATA_H_ */
|
||||||
|
|||||||
262
dbutils.h
262
dbutils.h
@@ -33,52 +33,60 @@
|
|||||||
|
|
||||||
#define ERRBUFF_SIZE 512
|
#define ERRBUFF_SIZE 512
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
PRIMARY,
|
PRIMARY,
|
||||||
STANDBY,
|
STANDBY,
|
||||||
BDR
|
BDR
|
||||||
} t_server_type;
|
} t_server_type;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
REPMGR_INSTALLED = 0,
|
REPMGR_INSTALLED = 0,
|
||||||
REPMGR_AVAILABLE,
|
REPMGR_AVAILABLE,
|
||||||
REPMGR_UNAVAILABLE,
|
REPMGR_UNAVAILABLE,
|
||||||
REPMGR_UNKNOWN
|
REPMGR_UNKNOWN
|
||||||
} ExtensionStatus;
|
} ExtensionStatus;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
RECTYPE_UNKNOWN = -1,
|
RECTYPE_UNKNOWN = -1,
|
||||||
RECTYPE_PRIMARY,
|
RECTYPE_PRIMARY,
|
||||||
RECTYPE_STANDBY
|
RECTYPE_STANDBY
|
||||||
} RecoveryType;
|
} RecoveryType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
RECORD_ERROR = -1,
|
RECORD_ERROR = -1,
|
||||||
RECORD_FOUND,
|
RECORD_FOUND,
|
||||||
RECORD_NOT_FOUND
|
RECORD_NOT_FOUND
|
||||||
} RecordStatus;
|
} RecordStatus;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
MS_NORMAL = 0,
|
MS_NORMAL = 0,
|
||||||
MS_DEGRADED = 1
|
MS_DEGRADED = 1
|
||||||
} MonitoringState;
|
} MonitoringState;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
NODE_STATUS_UNKNOWN = -1,
|
NODE_STATUS_UNKNOWN = -1,
|
||||||
NODE_STATUS_UP,
|
NODE_STATUS_UP,
|
||||||
NODE_STATUS_DOWN,
|
NODE_STATUS_DOWN,
|
||||||
NODE_STATUS_UNCLEAN_SHUTDOWN
|
NODE_STATUS_UNCLEAN_SHUTDOWN
|
||||||
} NodeStatus;
|
} NodeStatus;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
VR_VOTE_REFUSED = -1,
|
VR_VOTE_REFUSED = -1,
|
||||||
VR_POSITIVE_VOTE,
|
VR_POSITIVE_VOTE,
|
||||||
VR_NEGATIVE_VOTE
|
VR_NEGATIVE_VOTE
|
||||||
} VoteRequestResult;
|
} VoteRequestResult;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
SLOT_UNKNOWN = -1,
|
SLOT_UNKNOWN = -1,
|
||||||
SLOT_INACTIVE,
|
SLOT_INACTIVE,
|
||||||
SLOT_ACTIVE
|
SLOT_ACTIVE
|
||||||
@@ -90,36 +98,36 @@ typedef enum {
|
|||||||
typedef struct s_node_info
|
typedef struct s_node_info
|
||||||
{
|
{
|
||||||
/* contents of "repmgr.nodes" */
|
/* contents of "repmgr.nodes" */
|
||||||
int node_id;
|
int node_id;
|
||||||
int upstream_node_id;
|
int upstream_node_id;
|
||||||
t_server_type type;
|
t_server_type type;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char upstream_node_name[MAXLEN];
|
char upstream_node_name[MAXLEN];
|
||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
char repluser[NAMEDATALEN];
|
char repluser[NAMEDATALEN];
|
||||||
char location[MAXLEN];
|
char location[MAXLEN];
|
||||||
int priority;
|
int priority;
|
||||||
bool active;
|
bool active;
|
||||||
char slot_name[MAXLEN];
|
char slot_name[MAXLEN];
|
||||||
char config_file[MAXPGPATH];
|
char config_file[MAXPGPATH];
|
||||||
/* used during failover to track node status */
|
/* used during failover to track node status */
|
||||||
XLogRecPtr last_wal_receive_lsn;
|
XLogRecPtr last_wal_receive_lsn;
|
||||||
NodeStatus node_status;
|
NodeStatus node_status;
|
||||||
RecoveryType recovery_type;
|
RecoveryType recovery_type;
|
||||||
MonitoringState monitoring_state;
|
MonitoringState monitoring_state;
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
/* for ad-hoc use e.g. when working with a list of nodes */
|
/* for ad-hoc use e.g. when working with a list of nodes */
|
||||||
char details[MAXLEN];
|
char details[MAXLEN];
|
||||||
bool reachable;
|
bool reachable;
|
||||||
bool attached;
|
bool attached;
|
||||||
/* various statistics */
|
/* various statistics */
|
||||||
int max_wal_senders;
|
int max_wal_senders;
|
||||||
int attached_wal_receivers;
|
int attached_wal_receivers;
|
||||||
int max_replication_slots;
|
int max_replication_slots;
|
||||||
int total_replication_slots;
|
int total_replication_slots;
|
||||||
int active_replication_slots;
|
int active_replication_slots;
|
||||||
int inactive_replication_slots;
|
int inactive_replication_slots;
|
||||||
} t_node_info;
|
} t_node_info;
|
||||||
|
|
||||||
|
|
||||||
#define T_NODE_INFO_INITIALIZER { \
|
#define T_NODE_INFO_INITIALIZER { \
|
||||||
@@ -160,7 +168,7 @@ typedef struct NodeInfoList
|
|||||||
{
|
{
|
||||||
NodeInfoListCell *head;
|
NodeInfoListCell *head;
|
||||||
NodeInfoListCell *tail;
|
NodeInfoListCell *tail;
|
||||||
int node_count;
|
int node_count;
|
||||||
} NodeInfoList;
|
} NodeInfoList;
|
||||||
|
|
||||||
#define T_NODE_INFO_LIST_INITIALIZER { \
|
#define T_NODE_INFO_LIST_INITIALIZER { \
|
||||||
@@ -171,9 +179,9 @@ typedef struct NodeInfoList
|
|||||||
|
|
||||||
typedef struct s_event_info
|
typedef struct s_event_info
|
||||||
{
|
{
|
||||||
char *node_name;
|
char *node_name;
|
||||||
char *conninfo_str;
|
char *conninfo_str;
|
||||||
} t_event_info;
|
} t_event_info;
|
||||||
|
|
||||||
#define T_EVENT_INFO_INITIALIZER { \
|
#define T_EVENT_INFO_INITIALIZER { \
|
||||||
NULL, \
|
NULL, \
|
||||||
@@ -186,9 +194,9 @@ typedef struct s_event_info
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
char **keywords;
|
char **keywords;
|
||||||
char **values;
|
char **values;
|
||||||
} t_conninfo_param_list;
|
} t_conninfo_param_list;
|
||||||
|
|
||||||
#define T_CONNINFO_PARAM_LIST_INITIALIZER { \
|
#define T_CONNINFO_PARAM_LIST_INITIALIZER { \
|
||||||
@@ -202,19 +210,19 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
typedef struct s_replication_slot
|
typedef struct s_replication_slot
|
||||||
{
|
{
|
||||||
char slot_name[MAXLEN];
|
char slot_name[MAXLEN];
|
||||||
char slot_type[MAXLEN];
|
char slot_type[MAXLEN];
|
||||||
bool active;
|
bool active;
|
||||||
} t_replication_slot;
|
} t_replication_slot;
|
||||||
|
|
||||||
#define T_REPLICATION_SLOT_INITIALIZER { "", "", false }
|
#define T_REPLICATION_SLOT_INITIALIZER { "", "", false }
|
||||||
|
|
||||||
|
|
||||||
typedef struct s_connection_user
|
typedef struct s_connection_user
|
||||||
{
|
{
|
||||||
char username[MAXLEN];
|
char username[MAXLEN];
|
||||||
bool is_superuser;
|
bool is_superuser;
|
||||||
} t_connection_user;
|
} t_connection_user;
|
||||||
|
|
||||||
#define T_CONNECTION_USER_INITIALIZER { "", false }
|
#define T_CONNECTION_USER_INITIALIZER { "", false }
|
||||||
|
|
||||||
@@ -222,15 +230,15 @@ typedef struct s_connection_user
|
|||||||
/* represents an entry in bdr.bdr_nodes */
|
/* represents an entry in bdr.bdr_nodes */
|
||||||
typedef struct s_bdr_node_info
|
typedef struct s_bdr_node_info
|
||||||
{
|
{
|
||||||
char node_sysid[MAXLEN];
|
char node_sysid[MAXLEN];
|
||||||
uint32 node_timeline;
|
uint32 node_timeline;
|
||||||
uint32 node_dboid;
|
uint32 node_dboid;
|
||||||
char node_status;
|
char node_status;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char node_local_dsn[MAXLEN];
|
char node_local_dsn[MAXLEN];
|
||||||
char node_init_from_dsn[MAXLEN];
|
char node_init_from_dsn[MAXLEN];
|
||||||
bool read_only;
|
bool read_only;
|
||||||
uint32 node_seq_id;
|
uint32 node_seq_id;
|
||||||
} t_bdr_node_info;
|
} t_bdr_node_info;
|
||||||
|
|
||||||
#define T_BDR_NODE_INFO_INITIALIZER { \
|
#define T_BDR_NODE_INFO_INITIALIZER { \
|
||||||
@@ -251,7 +259,7 @@ typedef struct BdrNodeInfoList
|
|||||||
{
|
{
|
||||||
BdrNodeInfoListCell *head;
|
BdrNodeInfoListCell *head;
|
||||||
BdrNodeInfoListCell *tail;
|
BdrNodeInfoListCell *tail;
|
||||||
int node_count;
|
int node_count;
|
||||||
} BdrNodeInfoList;
|
} BdrNodeInfoList;
|
||||||
|
|
||||||
#define T_BDR_NODE_INFO_LIST_INITIALIZER { \
|
#define T_BDR_NODE_INFO_LIST_INITIALIZER { \
|
||||||
@@ -260,7 +268,8 @@ typedef struct BdrNodeInfoList
|
|||||||
0 \
|
0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
char current_timestamp[MAXLEN];
|
char current_timestamp[MAXLEN];
|
||||||
uint64 last_wal_receive_lsn;
|
uint64 last_wal_receive_lsn;
|
||||||
uint64 last_wal_replay_lsn;
|
uint64 last_wal_replay_lsn;
|
||||||
@@ -280,17 +289,17 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char filepath[MAXPGPATH];
|
char filepath[MAXPGPATH];
|
||||||
char filename[MAXPGPATH];
|
char filename[MAXPGPATH];
|
||||||
bool in_data_directory;
|
bool in_data_directory;
|
||||||
} t_configfile_info;
|
} t_configfile_info;
|
||||||
|
|
||||||
#define T_CONFIGFILE_INFO_INITIALIZER { "", "", false }
|
#define T_CONFIGFILE_INFO_INITIALIZER { "", "", false }
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
int entries;
|
int entries;
|
||||||
t_configfile_info **files;
|
t_configfile_info **files;
|
||||||
} t_configfile_list;
|
} t_configfile_list;
|
||||||
|
|
||||||
@@ -298,9 +307,9 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint64 system_identifier;
|
uint64 system_identifier;
|
||||||
TimeLineID timeline;
|
TimeLineID timeline;
|
||||||
XLogRecPtr xlogpos;
|
XLogRecPtr xlogpos;
|
||||||
} t_system_identification;
|
} t_system_identification;
|
||||||
|
|
||||||
#define T_SYSTEM_IDENTIFICATION_INITIALIZER { \
|
#define T_SYSTEM_IDENTIFICATION_INITIALIZER { \
|
||||||
@@ -310,7 +319,7 @@ typedef struct
|
|||||||
}
|
}
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
extern int server_version_num;
|
extern int server_version_num;
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
|
|
||||||
@@ -319,24 +328,25 @@ extern int server_version_num;
|
|||||||
|
|
||||||
/* utility functions */
|
/* utility functions */
|
||||||
|
|
||||||
XLogRecPtr parse_lsn(const char *str);
|
XLogRecPtr parse_lsn(const char *str);
|
||||||
|
|
||||||
extern void wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt, ...)
|
extern void
|
||||||
|
wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
||||||
bool atobool(const char *value);
|
bool atobool(const char *value);
|
||||||
|
|
||||||
/* connection functions */
|
/* connection functions */
|
||||||
PGconn *establish_db_connection(const char *conninfo,
|
PGconn *establish_db_connection(const char *conninfo,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
PGconn *establish_db_connection_quiet(const char *conninfo);
|
PGconn *establish_db_connection_quiet(const char *conninfo);
|
||||||
PGconn *establish_db_connection_as_user(const char *conninfo,
|
PGconn *establish_db_connection_as_user(const char *conninfo,
|
||||||
const char *user,
|
const char *user,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
|
|
||||||
PGconn *establish_db_connection_by_params(t_conninfo_param_list *param_list,
|
PGconn *establish_db_connection_by_params(t_conninfo_param_list *param_list,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
PGconn *establish_primary_db_connection(PGconn *conn,
|
PGconn *establish_primary_db_connection(PGconn *conn,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
|
|
||||||
PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
||||||
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
||||||
@@ -363,35 +373,35 @@ bool rollback_transaction(PGconn *conn);
|
|||||||
bool check_cluster_schema(PGconn *conn);
|
bool check_cluster_schema(PGconn *conn);
|
||||||
|
|
||||||
/* GUC manipulation functions */
|
/* GUC manipulation functions */
|
||||||
bool set_config(PGconn *conn, const char *config_param, const char *config_value);
|
bool set_config(PGconn *conn, const char *config_param, const char *config_value);
|
||||||
bool set_config_bool(PGconn *conn, const char *config_param, bool state);
|
bool set_config_bool(PGconn *conn, const char *config_param, bool state);
|
||||||
int guc_set(PGconn *conn, const char *parameter, const char *op,
|
int guc_set(PGconn *conn, const char *parameter, const char *op,
|
||||||
const char *value);
|
const char *value);
|
||||||
int guc_set_typed(PGconn *conn, const char *parameter, const char *op,
|
int guc_set_typed(PGconn *conn, const char *parameter, const char *op,
|
||||||
const char *value, const char *datatype);
|
const char *value, const char *datatype);
|
||||||
bool get_pg_setting(PGconn *conn, const char *setting, char *output);
|
bool get_pg_setting(PGconn *conn, const char *setting, char *output);
|
||||||
|
|
||||||
/* server information functions */
|
/* server information functions */
|
||||||
bool get_cluster_size(PGconn *conn, char *size);
|
bool get_cluster_size(PGconn *conn, char *size);
|
||||||
int get_server_version(PGconn *conn, char *server_version);
|
int get_server_version(PGconn *conn, char *server_version);
|
||||||
RecoveryType get_recovery_type(PGconn *conn);
|
RecoveryType get_recovery_type(PGconn *conn);
|
||||||
int get_primary_node_id(PGconn *conn);
|
int get_primary_node_id(PGconn *conn);
|
||||||
bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
||||||
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
||||||
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
||||||
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
||||||
|
|
||||||
/* extension functions */
|
/* extension functions */
|
||||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
||||||
|
|
||||||
/* node management functions */
|
/* node management functions */
|
||||||
void checkpoint(PGconn *conn);
|
void checkpoint(PGconn *conn);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* node record functions */
|
/* node record functions */
|
||||||
t_server_type parse_node_type(const char *type);
|
t_server_type parse_node_type(const char *type);
|
||||||
const char *get_node_type_string(t_server_type type);
|
const char *get_node_type_string(t_server_type type);
|
||||||
|
|
||||||
RecordStatus get_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
RecordStatus get_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
RecordStatus get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_info);
|
RecordStatus get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_info);
|
||||||
@@ -445,53 +455,53 @@ int wait_connection_availability(PGconn *conn, long long timeout);
|
|||||||
bool is_server_available(const char *conninfo);
|
bool is_server_available(const char *conninfo);
|
||||||
|
|
||||||
/* monitoring functions */
|
/* monitoring functions */
|
||||||
void add_monitoring_record(
|
void
|
||||||
PGconn *primary_conn,
|
add_monitoring_record(
|
||||||
PGconn *local_conn,
|
PGconn *primary_conn,
|
||||||
int primary_node_id,
|
PGconn *local_conn,
|
||||||
int local_node_id,
|
int primary_node_id,
|
||||||
char *monitor_standby_timestamp,
|
int local_node_id,
|
||||||
XLogRecPtr primary_last_wal_location,
|
char *monitor_standby_timestamp,
|
||||||
XLogRecPtr last_wal_receive_lsn,
|
XLogRecPtr primary_last_wal_location,
|
||||||
char *last_xact_replay_timestamp,
|
XLogRecPtr last_wal_receive_lsn,
|
||||||
long long unsigned int replication_lag_bytes,
|
char *last_xact_replay_timestamp,
|
||||||
long long unsigned int apply_lag_bytes
|
long long unsigned int replication_lag_bytes,
|
||||||
);
|
long long unsigned int apply_lag_bytes
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/* node voting functions */
|
/* node voting functions */
|
||||||
NodeVotingStatus get_voting_status(PGconn *conn);
|
NodeVotingStatus get_voting_status(PGconn *conn);
|
||||||
VoteRequestResult request_vote(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
VoteRequestResult request_vote(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
||||||
int set_voting_status_initiated(PGconn *conn);
|
int set_voting_status_initiated(PGconn *conn);
|
||||||
bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
||||||
void notify_follow_primary(PGconn *conn, int primary_node_id);
|
void notify_follow_primary(PGconn *conn, int primary_node_id);
|
||||||
bool get_new_primary(PGconn *conn, int *primary_node_id);
|
bool get_new_primary(PGconn *conn, int *primary_node_id);
|
||||||
void reset_voting_status(PGconn *conn);
|
void reset_voting_status(PGconn *conn);
|
||||||
|
|
||||||
/* replication status functions */
|
/* replication status functions */
|
||||||
XLogRecPtr get_current_wal_lsn(PGconn *conn);
|
XLogRecPtr get_current_wal_lsn(PGconn *conn);
|
||||||
XLogRecPtr get_last_wal_receive_location(PGconn *conn);
|
XLogRecPtr get_last_wal_receive_location(PGconn *conn);
|
||||||
bool get_replication_info(PGconn *conn, ReplInfo *replication_info);
|
bool get_replication_info(PGconn *conn, ReplInfo *replication_info);
|
||||||
int get_replication_lag_seconds(PGconn *conn);
|
int get_replication_lag_seconds(PGconn *conn);
|
||||||
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
||||||
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
||||||
|
|
||||||
/* BDR functions */
|
/* BDR functions */
|
||||||
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
||||||
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
||||||
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
||||||
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
||||||
bool is_bdr_repmgr(PGconn *conn);
|
bool is_bdr_repmgr(PGconn *conn);
|
||||||
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||||
|
|
||||||
bool bdr_node_exists(PGconn *conn, const char *node_name);
|
bool bdr_node_exists(PGconn *conn, const char *node_name);
|
||||||
ReplSlotStatus get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name);
|
ReplSlotStatus get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name);
|
||||||
void get_bdr_other_node_name(PGconn *conn, int node_id, char *name_buf);
|
void get_bdr_other_node_name(PGconn *conn, int node_id, char *name_buf);
|
||||||
|
|
||||||
bool am_bdr_failover_handler(PGconn *conn, int node_id);
|
bool am_bdr_failover_handler(PGconn *conn, int node_id);
|
||||||
void unset_bdr_failover_handler(PGconn *conn);
|
void unset_bdr_failover_handler(PGconn *conn);
|
||||||
|
|
||||||
#endif /* _REPMGR_DBUTILS_H_ */
|
|
||||||
|
|
||||||
|
#endif /* _REPMGR_DBUTILS_H_ */
|
||||||
|
|||||||
25
dirutil.c
25
dirutil.c
@@ -35,7 +35,7 @@
|
|||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
static int unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
static int unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ create_dir(char *path)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
log_error(_("unable to create directory \"%s\": %s"),
|
log_error(_("unable to create directory \"%s\": %s"),
|
||||||
path, strerror(errno));
|
path, strerror(errno));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ create_pg_dir(char *path, bool force)
|
|||||||
if (!create_dir(path))
|
if (!create_dir(path))
|
||||||
{
|
{
|
||||||
log_error(_("unable to create directory \"%s\"..."),
|
log_error(_("unable to create directory \"%s\"..."),
|
||||||
path);
|
path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -270,7 +270,7 @@ create_pg_dir(char *path, bool force)
|
|||||||
if (!set_dir_permissions(path))
|
if (!set_dir_permissions(path))
|
||||||
{
|
{
|
||||||
log_error(_("unable to change permissions of directory \"%s\":\n %s"),
|
log_error(_("unable to change permissions of directory \"%s\":\n %s"),
|
||||||
path, strerror(errno));
|
path, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -296,16 +296,16 @@ create_pg_dir(char *path, bool force)
|
|||||||
else if (pg_dir && !force)
|
else if (pg_dir && !force)
|
||||||
{
|
{
|
||||||
log_hint(_("This looks like a PostgreSQL directory.\n"
|
log_hint(_("This looks like a PostgreSQL directory.\n"
|
||||||
"If you are sure you want to clone here, "
|
"If you are sure you want to clone here, "
|
||||||
"please check there is no PostgreSQL server "
|
"please check there is no PostgreSQL server "
|
||||||
"running and use the -F/--force option"));
|
"running and use the -F/--force option"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
log_error(_("could not access directory \"%s\": %s"),
|
log_error(_("could not access directory \"%s\": %s"),
|
||||||
path, strerror(errno));
|
path, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -314,11 +314,10 @@ create_pg_dir(char *path, bool force)
|
|||||||
static int
|
static int
|
||||||
unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||||
{
|
{
|
||||||
int rv = remove(fpath);
|
int rv = remove(fpath);
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
perror(fpath);
|
perror(fpath);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
dirutil.h
12
dirutil.h
@@ -19,12 +19,12 @@
|
|||||||
#ifndef _DIRUTIL_H_
|
#ifndef _DIRUTIL_H_
|
||||||
#define _DIRUTIL_H_
|
#define _DIRUTIL_H_
|
||||||
|
|
||||||
extern int mkdir_p(char *path, mode_t omode);
|
extern int mkdir_p(char *path, mode_t omode);
|
||||||
extern bool set_dir_permissions(char *path);
|
extern bool set_dir_permissions(char *path);
|
||||||
|
|
||||||
extern int check_dir(char *path);
|
extern int check_dir(char *path);
|
||||||
extern bool create_dir(char *path);
|
extern bool create_dir(char *path);
|
||||||
extern bool is_pg_dir(char *path);
|
extern bool is_pg_dir(char *path);
|
||||||
extern bool create_pg_dir(char *path, bool force);
|
extern bool create_pg_dir(char *path, bool force);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,5 +44,4 @@
|
|||||||
#define ERR_REGISTRATION_SYNC 20
|
#define ERR_REGISTRATION_SYNC 20
|
||||||
#define ERR_OUT_OF_MEMORY 21
|
#define ERR_OUT_OF_MEMORY 21
|
||||||
|
|
||||||
#endif /* _ERRCODE_H_ */
|
#endif /* _ERRCODE_H_ */
|
||||||
|
|
||||||
|
|||||||
39
log.c
39
log.c
@@ -37,7 +37,8 @@
|
|||||||
/* #define REPMGR_DEBUG */
|
/* #define REPMGR_DEBUG */
|
||||||
|
|
||||||
static int detect_log_facility(const char *facility);
|
static int detect_log_facility(const char *facility);
|
||||||
static void _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_list ap)
|
static void
|
||||||
|
_stderr_log_with_level(const char *level_name, int level, const char *fmt, va_list ap)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||||
|
|
||||||
int log_type = REPMGR_STDERR;
|
int log_type = REPMGR_STDERR;
|
||||||
@@ -45,6 +46,7 @@ int log_level = LOG_NOTICE;
|
|||||||
int last_log_level = LOG_INFO;
|
int last_log_level = LOG_INFO;
|
||||||
int verbose_logging = false;
|
int verbose_logging = false;
|
||||||
int terse_logging = false;
|
int terse_logging = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variable to be set by the main application to ensure any log output
|
* Global variable to be set by the main application to ensure any log output
|
||||||
* emitted before logger_init is called, is output in the correct format
|
* emitted before logger_init is called, is output in the correct format
|
||||||
@@ -52,7 +54,7 @@ int terse_logging = false;
|
|||||||
int logger_output_mode = OM_DAEMON;
|
int logger_output_mode = OM_DAEMON;
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
stderr_log_with_level(const char *level_name, int level, const char *fmt, ...)
|
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
|
||||||
{
|
{
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
|
|
||||||
@@ -67,8 +69,8 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
char buf[100];
|
char buf[100];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the requested level so that if there's a subsequent
|
* Store the requested level so that if there's a subsequent log_hint() or
|
||||||
* log_hint() or log_detail(), we can suppress that if appropriate.
|
* log_detail(), we can suppress that if appropriate.
|
||||||
*/
|
*/
|
||||||
last_log_level = level;
|
last_log_level = level;
|
||||||
|
|
||||||
@@ -80,6 +82,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
{
|
{
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
||||||
time(&t);
|
time(&t);
|
||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
strftime(buf, 100, "[%Y-%m-%d %H:%M:%S]", tm);
|
strftime(buf, 100, "[%Y-%m-%d %H:%M:%S]", tm);
|
||||||
@@ -97,7 +100,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
log_hint(const char *fmt, ...)
|
log_hint(const char *fmt,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -111,7 +114,7 @@ log_hint(const char *fmt, ...)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_detail(const char *fmt, ...)
|
log_detail(const char *fmt,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -125,7 +128,7 @@ log_detail(const char *fmt, ...)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_verbose(int level, const char *fmt, ...)
|
log_verbose(int level, const char *fmt,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -133,7 +136,7 @@ log_verbose(int level, const char *fmt, ...)
|
|||||||
|
|
||||||
if (verbose_logging == true)
|
if (verbose_logging == true)
|
||||||
{
|
{
|
||||||
switch(level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case LOG_EMERG:
|
case LOG_EMERG:
|
||||||
_stderr_log_with_level("EMERG", level, fmt, ap);
|
_stderr_log_with_level("EMERG", level, fmt, ap);
|
||||||
@@ -202,8 +205,8 @@ logger_init(t_configuration_options *opts, const char *ident)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* STDERR only logging requested - finish here without setting up any further
|
* STDERR only logging requested - finish here without setting up any
|
||||||
* logging facility.
|
* further logging facility.
|
||||||
*/
|
*/
|
||||||
if (logger_output_mode == OM_COMMAND_LINE)
|
if (logger_output_mode == OM_COMMAND_LINE)
|
||||||
return true;
|
return true;
|
||||||
@@ -251,9 +254,10 @@ logger_init(t_configuration_options *opts, const char *ident)
|
|||||||
{
|
{
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
|
|
||||||
/* Check if we can write to the specified file before redirecting
|
/*
|
||||||
* stderr - if freopen() fails, stderr output will vanish into
|
* Check if we can write to the specified file before redirecting
|
||||||
* the ether and the user won't know what's going on.
|
* stderr - if freopen() fails, stderr output will vanish into the
|
||||||
|
* ether and the user won't know what's going on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fd = fopen(opts->log_file, "a");
|
fd = fopen(opts->log_file, "a");
|
||||||
@@ -270,9 +274,9 @@ logger_init(t_configuration_options *opts, const char *ident)
|
|||||||
fd = freopen(opts->log_file, "a", stderr);
|
fd = freopen(opts->log_file, "a", stderr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's possible freopen() may still fail due to e.g. a race condition;
|
* It's possible freopen() may still fail due to e.g. a race
|
||||||
* as it's not feasible to restore stderr after a failed freopen(),
|
* condition; as it's not feasible to restore stderr after a failed
|
||||||
* we'll write to stdout as a last resort.
|
* freopen(), we'll write to stdout as a last resort.
|
||||||
*/
|
*/
|
||||||
if (fd == NULL)
|
if (fd == NULL)
|
||||||
{
|
{
|
||||||
@@ -318,7 +322,8 @@ logger_set_verbose(void)
|
|||||||
* options and hints.
|
* options and hints.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void logger_set_terse(void)
|
void
|
||||||
|
logger_set_terse(void)
|
||||||
{
|
{
|
||||||
terse_logging = true;
|
terse_logging = true;
|
||||||
}
|
}
|
||||||
|
|||||||
13
log.h
13
log.h
@@ -122,18 +122,21 @@ int detect_log_level(const char *level);
|
|||||||
|
|
||||||
/* Logger initialisation and shutdown */
|
/* Logger initialisation and shutdown */
|
||||||
|
|
||||||
bool logger_init(t_configuration_options * opts, const char *ident);
|
bool logger_init(t_configuration_options *opts, const char *ident);
|
||||||
|
|
||||||
bool logger_shutdown(void);
|
bool logger_shutdown(void);
|
||||||
|
|
||||||
void logger_set_verbose(void);
|
void logger_set_verbose(void);
|
||||||
void logger_set_terse(void);
|
void logger_set_terse(void);
|
||||||
|
|
||||||
void log_detail(const char *fmt, ...)
|
void
|
||||||
|
log_detail(const char *fmt,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
|
||||||
void log_hint(const char *fmt, ...)
|
void
|
||||||
|
log_hint(const char *fmt,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
|
||||||
void log_verbose(int level, const char *fmt, ...)
|
void
|
||||||
|
log_verbose(int level, const char *fmt,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
||||||
|
|
||||||
extern int log_type;
|
extern int log_type;
|
||||||
@@ -142,4 +145,4 @@ extern int verbose_logging;
|
|||||||
extern int terse_logging;
|
extern int terse_logging;
|
||||||
extern int logger_output_mode;
|
extern int logger_output_mode;
|
||||||
|
|
||||||
#endif /* _REPMGR_LOG_H_ */
|
#endif /* _REPMGR_LOG_H_ */
|
||||||
|
|||||||
@@ -34,14 +34,14 @@
|
|||||||
void
|
void
|
||||||
do_bdr_register(void)
|
do_bdr_register(void)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
BdrNodeInfoList bdr_nodes = T_BDR_NODE_INFO_LIST_INITIALIZER;
|
BdrNodeInfoList bdr_nodes = T_BDR_NODE_INFO_LIST_INITIALIZER;
|
||||||
ExtensionStatus extension_status = REPMGR_UNKNOWN;
|
ExtensionStatus extension_status = REPMGR_UNKNOWN;
|
||||||
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
char dbname[MAXLEN];
|
char dbname[MAXLEN];
|
||||||
|
|
||||||
/* sanity-check configuration for BDR-compatability */
|
/* sanity-check configuration for BDR-compatability */
|
||||||
if (config_file_options.replication_type != REPLICATION_TYPE_BDR)
|
if (config_file_options.replication_type != REPLICATION_TYPE_BDR)
|
||||||
@@ -124,7 +124,7 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
/* check for a matching BDR node */
|
/* check for a matching BDR node */
|
||||||
{
|
{
|
||||||
bool node_exists = bdr_node_exists(conn, config_file_options.node_name);
|
bool node_exists = bdr_node_exists(conn, config_file_options.node_name);
|
||||||
|
|
||||||
if (node_exists == false)
|
if (node_exists == false)
|
||||||
{
|
{
|
||||||
@@ -136,15 +136,15 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* before adding the extension tables to the replication set,
|
* before adding the extension tables to the replication set, if any other
|
||||||
* if any other BDR nodes exist, populate repmgr.nodes with a copy
|
* BDR nodes exist, populate repmgr.nodes with a copy of existing entries
|
||||||
* of existing entries
|
|
||||||
*
|
*
|
||||||
* currently we won't copy the contents of any other tables
|
* currently we won't copy the contents of any other tables
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
|
||||||
get_all_node_records(conn, &local_node_records);
|
get_all_node_records(conn, &local_node_records);
|
||||||
|
|
||||||
if (local_node_records.node_count == 0)
|
if (local_node_records.node_count == 0)
|
||||||
@@ -163,7 +163,7 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
for (bdr_cell = bdr_nodes.head; bdr_cell; bdr_cell = bdr_cell->next)
|
for (bdr_cell = bdr_nodes.head; bdr_cell; bdr_cell = bdr_cell->next)
|
||||||
{
|
{
|
||||||
PGconn *bdr_node_conn = NULL;
|
PGconn *bdr_node_conn = NULL;
|
||||||
NodeInfoList existing_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList existing_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
NodeInfoListCell *cell = NULL;
|
NodeInfoListCell *cell = NULL;
|
||||||
ExtensionStatus other_node_extension_status = REPMGR_UNKNOWN;
|
ExtensionStatus other_node_extension_status = REPMGR_UNKNOWN;
|
||||||
@@ -235,10 +235,11 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
if (record_status == RECORD_FOUND)
|
if (record_status == RECORD_FOUND)
|
||||||
{
|
{
|
||||||
bool node_updated = false;
|
bool node_updated = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point we will have established there are no non-BDR records,
|
* At this point we will have established there are no non-BDR
|
||||||
* so no need to verify the node type
|
* records, so no need to verify the node type
|
||||||
*/
|
*/
|
||||||
if (!runtime_options.force)
|
if (!runtime_options.force)
|
||||||
{
|
{
|
||||||
@@ -250,8 +251,8 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* don't permit changing the node name - this must match the
|
* don't permit changing the node name - this must match the BDR node
|
||||||
* BDR node name set when the node was registered.
|
* name set when the node was registered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (strncmp(node_info.node_name, config_file_options.node_name, MAXLEN) != 0)
|
if (strncmp(node_info.node_name, config_file_options.node_name, MAXLEN) != 0)
|
||||||
@@ -281,7 +282,7 @@ do_bdr_register(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* create new node record */
|
/* create new node record */
|
||||||
bool node_created = create_node_record(conn, "bdr register", &node_info);
|
bool node_created = create_node_record(conn, "bdr register", &node_info);
|
||||||
|
|
||||||
if (node_created == true)
|
if (node_created == true)
|
||||||
{
|
{
|
||||||
@@ -306,12 +307,12 @@ do_bdr_register(void)
|
|||||||
commit_transaction(conn);
|
commit_transaction(conn);
|
||||||
/* Log the event */
|
/* Log the event */
|
||||||
create_event_notification(
|
create_event_notification(
|
||||||
conn,
|
conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"bdr_register",
|
"bdr_register",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
@@ -327,14 +328,14 @@ do_bdr_register(void)
|
|||||||
void
|
void
|
||||||
do_bdr_unregister(void)
|
do_bdr_unregister(void)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
ExtensionStatus extension_status = REPMGR_UNKNOWN;
|
ExtensionStatus extension_status = REPMGR_UNKNOWN;
|
||||||
int target_node_id = UNKNOWN_NODE_ID;
|
int target_node_id = UNKNOWN_NODE_ID;
|
||||||
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
bool node_record_deleted = false;
|
bool node_record_deleted = false;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
char dbname[MAXLEN];
|
char dbname[MAXLEN];
|
||||||
|
|
||||||
/* sanity-check configuration for BDR-compatability */
|
/* sanity-check configuration for BDR-compatability */
|
||||||
|
|
||||||
@@ -411,12 +412,12 @@ do_bdr_unregister(void)
|
|||||||
|
|
||||||
/* Log the event */
|
/* Log the event */
|
||||||
create_event_notification(
|
create_event_notification(
|
||||||
conn,
|
conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"bdr_unregister",
|
"bdr_unregister",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ extern void do_bdr_unregister(void);
|
|||||||
extern void do_bdr_help(void);
|
extern void do_bdr_help(void);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _REPMGR_ACTION_BDR_H_ */
|
#endif /* _REPMGR_ACTION_BDR_H_ */
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
#define SHOW_HEADER_COUNT 7
|
#define SHOW_HEADER_COUNT 7
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
SHOW_ID = 0,
|
SHOW_ID = 0,
|
||||||
SHOW_NAME,
|
SHOW_NAME,
|
||||||
SHOW_ROLE,
|
SHOW_ROLE,
|
||||||
@@ -35,25 +36,27 @@ typedef enum {
|
|||||||
SHOW_UPSTREAM_NAME,
|
SHOW_UPSTREAM_NAME,
|
||||||
SHOW_LOCATION,
|
SHOW_LOCATION,
|
||||||
SHOW_CONNINFO
|
SHOW_CONNINFO
|
||||||
} ShowHeader;
|
} ShowHeader;
|
||||||
|
|
||||||
#define EVENT_HEADER_COUNT 6
|
#define EVENT_HEADER_COUNT 6
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
EV_NODE_ID = 0,
|
EV_NODE_ID = 0,
|
||||||
EV_NODE_NAME,
|
EV_NODE_NAME,
|
||||||
EV_EVENT,
|
EV_EVENT,
|
||||||
EV_SUCCESS,
|
EV_SUCCESS,
|
||||||
EV_TIMESTAMP,
|
EV_TIMESTAMP,
|
||||||
EV_DETAILS
|
EV_DETAILS
|
||||||
} EventHeader;
|
} EventHeader;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ColHeader {
|
struct ColHeader
|
||||||
char title[MAXLEN];
|
{
|
||||||
int max_length;
|
char title[MAXLEN];
|
||||||
int cur_length;
|
int max_length;
|
||||||
|
int cur_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ColHeader headers_show[SHOW_HEADER_COUNT];
|
struct ColHeader headers_show[SHOW_HEADER_COUNT];
|
||||||
@@ -61,8 +64,8 @@ struct ColHeader headers_event[EVENT_HEADER_COUNT];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length);
|
static int build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length);
|
||||||
static int build_cluster_crosscheck(t_node_status_cube ***cube_dest, int *name_length);
|
static int build_cluster_crosscheck(t_node_status_cube ***cube_dest, int *name_length);
|
||||||
static void cube_set_node_status(t_node_status_cube **cube, int n, int node_id, int matrix_node_id, int connection_node_id, int connection_status);
|
static void cube_set_node_status(t_node_status_cube **cube, int n, int node_id, int matrix_node_id, int connection_node_id, int connection_status);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -78,7 +81,7 @@ do_cluster_show(void)
|
|||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
NodeInfoListCell *cell = NULL;
|
NodeInfoListCell *cell = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ItemList warnings = { NULL, NULL };
|
ItemList warnings = {NULL, NULL};
|
||||||
|
|
||||||
/* Connect to local database to obtain cluster connection data */
|
/* Connect to local database to obtain cluster connection data */
|
||||||
log_verbose(LOG_INFO, _("connecting to database\n"));
|
log_verbose(LOG_INFO, _("connecting to database\n"));
|
||||||
@@ -106,8 +109,8 @@ do_cluster_show(void)
|
|||||||
strncpy(headers_show[SHOW_CONNINFO].title, _("Connection string"), MAXLEN);
|
strncpy(headers_show[SHOW_CONNINFO].title, _("Connection string"), MAXLEN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: if repmgr is ever localized into non-ASCII locales,
|
* NOTE: if repmgr is ever localized into non-ASCII locales, use
|
||||||
* use pg_wcssize() or similar to establish printed column length
|
* pg_wcssize() or similar to establish printed column length
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
||||||
@@ -136,171 +139,172 @@ do_cluster_show(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: count nodes marked as "? unreachable" and add a hint about
|
* TODO: count nodes marked as "? unreachable" and add a hint about
|
||||||
* the other cluster commands for better determining whether unreachable.
|
* the other cluster commands for better determining whether
|
||||||
|
* unreachable.
|
||||||
*/
|
*/
|
||||||
switch (cell->node_info->type)
|
switch (cell->node_info->type)
|
||||||
{
|
{
|
||||||
case PRIMARY:
|
case PRIMARY:
|
||||||
{
|
|
||||||
/* node is reachable */
|
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
/* node is reachable */
|
||||||
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
switch (cell->node_info->recovery_type)
|
if (cell->node_info->active == true)
|
||||||
{
|
{
|
||||||
case RECTYPE_PRIMARY:
|
switch (cell->node_info->recovery_type)
|
||||||
appendPQExpBuffer(&details, "* running");
|
{
|
||||||
break;
|
case RECTYPE_PRIMARY:
|
||||||
case RECTYPE_STANDBY:
|
appendPQExpBuffer(&details, "* running");
|
||||||
|
break;
|
||||||
|
case RECTYPE_STANDBY:
|
||||||
|
appendPQExpBuffer(&details, "! running as standby");
|
||||||
|
item_list_append_format(
|
||||||
|
&warnings,
|
||||||
|
"node \"%s\" (ID: %i) is registered as primary but running as standby",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
break;
|
||||||
|
case RECTYPE_UNKNOWN:
|
||||||
|
appendPQExpBuffer(&details, "! unknown");
|
||||||
|
item_list_append_format(
|
||||||
|
&warnings,
|
||||||
|
"node \"%s\" (ID: %i) has unknown replication status",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cell->node_info->recovery_type == RECTYPE_PRIMARY)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&details, "! running");
|
||||||
|
item_list_append_format(
|
||||||
|
&warnings,
|
||||||
|
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
appendPQExpBuffer(&details, "! running as standby");
|
appendPQExpBuffer(&details, "! running as standby");
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
&warnings,
|
&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as primary but running as standby",
|
"node \"%s\" (ID: %i) is registered as an inactive primary but running as standby",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
break;
|
}
|
||||||
case RECTYPE_UNKNOWN:
|
|
||||||
appendPQExpBuffer(&details, "! unknown");
|
|
||||||
item_list_append_format(
|
|
||||||
&warnings,
|
|
||||||
"node \"%s\" (ID: %i) has unknown replication status",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* node is unreachable */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cell->node_info->recovery_type == RECTYPE_PRIMARY)
|
/* node is unreachable but marked active */
|
||||||
|
if (cell->node_info->active == true)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&details, "! running");
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
&warnings,
|
&warnings,
|
||||||
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
"node \"%s\" (ID: %i) is registered as an active primary but is unreachable",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
|
/* node is unreachable and marked as inactive */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&details, "! running as standby");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
item_list_append_format(
|
|
||||||
&warnings,
|
|
||||||
"node \"%s\" (ID: %i) is registered as an inactive primary but running as standby",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* node is unreachable */
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
/* node is unreachable but marked active*/
|
|
||||||
if (cell->node_info->active == true)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "? unreachable");
|
|
||||||
item_list_append_format(
|
|
||||||
&warnings,
|
|
||||||
"node \"%s\" (ID: %i) is registered as an active primary but is unreachable",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
|
||||||
/* node is unreachable and marked as inactive */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "- failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STANDBY:
|
case STANDBY:
|
||||||
{
|
|
||||||
/* node is reachable */
|
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
/* node is reachable */
|
||||||
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
switch (cell->node_info->recovery_type)
|
if (cell->node_info->active == true)
|
||||||
{
|
{
|
||||||
case RECTYPE_STANDBY:
|
switch (cell->node_info->recovery_type)
|
||||||
appendPQExpBuffer(&details, " running");
|
{
|
||||||
break;
|
case RECTYPE_STANDBY:
|
||||||
case RECTYPE_PRIMARY:
|
appendPQExpBuffer(&details, " running");
|
||||||
appendPQExpBuffer(&details, "! running as primary");
|
break;
|
||||||
item_list_append_format(
|
case RECTYPE_PRIMARY:
|
||||||
&warnings,
|
appendPQExpBuffer(&details, "! running as primary");
|
||||||
"node \"%s\" (ID: %i) is registered as standby but running as primary",
|
item_list_append_format(
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
&warnings,
|
||||||
break;
|
"node \"%s\" (ID: %i) is registered as standby but running as primary",
|
||||||
case RECTYPE_UNKNOWN:
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
appendPQExpBuffer(&details, "! unknown");
|
break;
|
||||||
item_list_append_format(
|
case RECTYPE_UNKNOWN:
|
||||||
&warnings,
|
appendPQExpBuffer(&details, "! unknown");
|
||||||
"node \"%s\" (ID: %i) has unknown replication status",
|
item_list_append_format(
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
&warnings,
|
||||||
break;
|
"node \"%s\" (ID: %i) has unknown replication status",
|
||||||
}
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
}
|
break;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
if (cell->node_info->recovery_type == RECTYPE_STANDBY)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "! running");
|
|
||||||
item_list_append_format(
|
|
||||||
&warnings,
|
|
||||||
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&details, "! running as primary");
|
if (cell->node_info->recovery_type == RECTYPE_STANDBY)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&details, "! running");
|
||||||
|
item_list_append_format(
|
||||||
|
&warnings,
|
||||||
|
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&details, "! running as primary");
|
||||||
|
item_list_append_format(
|
||||||
|
&warnings,
|
||||||
|
"node \"%s\" (ID: %i) is running as primary but the repmgr node record is inactive",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* node is unreachable */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* node is unreachable but marked active */
|
||||||
|
if (cell->node_info->active == true)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
&warnings,
|
&warnings,
|
||||||
"node \"%s\" (ID: %i) is running as primary but the repmgr node record is inactive",
|
"node \"%s\" (ID: %i) is registered as an active standby but is unreachable",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&details, "- failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* node is unreachable */
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
/* node is unreachable but marked active*/
|
|
||||||
if (cell->node_info->active == true)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "? unreachable");
|
|
||||||
item_list_append_format(
|
|
||||||
&warnings,
|
|
||||||
"node \"%s\" (ID: %i) is registered as an active standby but is unreachable",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&details, "- failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BDR:
|
case BDR:
|
||||||
{
|
|
||||||
/* node is reachable */
|
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
/* node is reachable */
|
||||||
appendPQExpBuffer(&details, "* running");
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
|
{
|
||||||
|
if (cell->node_info->active == true)
|
||||||
|
appendPQExpBuffer(&details, "* running");
|
||||||
|
else
|
||||||
|
appendPQExpBuffer(&details, "! running");
|
||||||
|
}
|
||||||
|
/* node is unreachable */
|
||||||
else
|
else
|
||||||
appendPQExpBuffer(&details, "! running");
|
{
|
||||||
|
if (cell->node_info->active == true)
|
||||||
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
|
else
|
||||||
|
appendPQExpBuffer(&details, "- failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* node is unreachable */
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cell->node_info->active == true)
|
|
||||||
appendPQExpBuffer(&details, "? unreachable");
|
|
||||||
else
|
|
||||||
appendPQExpBuffer(&details, "- failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
{
|
{
|
||||||
/* this should never happen */
|
/* this should never happen */
|
||||||
appendPQExpBuffer(&details, "? unknown node type");
|
appendPQExpBuffer(&details, "? unknown node type");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(cell->node_info->details, details.data, MAXLEN);
|
strncpy(cell->node_info->details, details.data, MAXLEN);
|
||||||
@@ -344,7 +348,8 @@ do_cluster_show(void)
|
|||||||
|
|
||||||
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < headers_show[i].max_length; j++)
|
for (j = 0; j < headers_show[i].max_length; j++)
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
@@ -361,12 +366,12 @@ do_cluster_show(void)
|
|||||||
{
|
{
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
{
|
{
|
||||||
int connection_status = (cell->node_info->node_status == NODE_STATUS_UP) ? 0 : -1;
|
int connection_status = (cell->node_info->node_status == NODE_STATUS_UP) ? 0 : -1;
|
||||||
int recovery_type = RECTYPE_UNKNOWN;
|
int recovery_type = RECTYPE_UNKNOWN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* here we explicitly convert the RecoveryType to integer values to
|
* here we explicitly convert the RecoveryType to integer values
|
||||||
* avoid implicit dependency on the values in the enum
|
* to avoid implicit dependency on the values in the enum
|
||||||
*/
|
*/
|
||||||
switch (cell->node_info->recovery_type)
|
switch (cell->node_info->recovery_type)
|
||||||
{
|
{
|
||||||
@@ -388,12 +393,12 @@ do_cluster_show(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf( " %-*i ", headers_show[SHOW_ID].max_length, cell->node_info->node_id);
|
printf(" %-*i ", headers_show[SHOW_ID].max_length, cell->node_info->node_id);
|
||||||
printf("| %-*s ", headers_show[SHOW_NAME].max_length, cell->node_info->node_name);
|
printf("| %-*s ", headers_show[SHOW_NAME].max_length, cell->node_info->node_name);
|
||||||
printf("| %-*s ", headers_show[SHOW_ROLE].max_length, get_node_type_string(cell->node_info->type));
|
printf("| %-*s ", headers_show[SHOW_ROLE].max_length, get_node_type_string(cell->node_info->type));
|
||||||
printf("| %-*s ", headers_show[SHOW_STATUS].max_length, cell->node_info->details);
|
printf("| %-*s ", headers_show[SHOW_STATUS].max_length, cell->node_info->details);
|
||||||
printf("| %-*s ", headers_show[SHOW_UPSTREAM_NAME].max_length , cell->node_info->upstream_node_name);
|
printf("| %-*s ", headers_show[SHOW_UPSTREAM_NAME].max_length, cell->node_info->upstream_node_name);
|
||||||
printf("| %-*s ", headers_show[SHOW_LOCATION].max_length , cell->node_info->location);
|
printf("| %-*s ", headers_show[SHOW_LOCATION].max_length, cell->node_info->location);
|
||||||
printf("| %-*s\n", headers_show[SHOW_CONNINFO].max_length, cell->node_info->conninfo);
|
printf("| %-*s\n", headers_show[SHOW_CONNINFO].max_length, cell->node_info->conninfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,11 +434,11 @@ do_cluster_show(void)
|
|||||||
void
|
void
|
||||||
do_cluster_event(void)
|
do_cluster_event(void)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PQExpBufferData where_clause;
|
PQExpBufferData where_clause;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|
||||||
@@ -442,12 +447,12 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
/* LEFT JOIN used here as a node record may have been removed */
|
/* LEFT JOIN used here as a node record may have been removed */
|
||||||
appendPQExpBuffer(
|
appendPQExpBuffer(
|
||||||
&query,
|
&query,
|
||||||
" SELECT e.node_id, n.node_name, e.event, e.successful, \n"
|
" SELECT e.node_id, n.node_name, e.event, e.successful, \n"
|
||||||
" TO_CHAR(e.event_timestamp, 'YYYY-MM-DD HH24:MI:SS') AS timestamp, \n"
|
" TO_CHAR(e.event_timestamp, 'YYYY-MM-DD HH24:MI:SS') AS timestamp, \n"
|
||||||
" e.details \n"
|
" e.details \n"
|
||||||
" FROM repmgr.events e \n"
|
" FROM repmgr.events e \n"
|
||||||
"LEFT JOIN repmgr.nodes n ON e.node_id = n.node_id ");
|
"LEFT JOIN repmgr.nodes n ON e.node_id = n.node_id ");
|
||||||
|
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
||||||
{
|
{
|
||||||
@@ -457,7 +462,7 @@ do_cluster_event(void)
|
|||||||
}
|
}
|
||||||
else if (runtime_options.node_name[0] != '\0')
|
else if (runtime_options.node_name[0] != '\0')
|
||||||
{
|
{
|
||||||
char *escaped = escape_string(conn, runtime_options.node_name);
|
char *escaped = escape_string(conn, runtime_options.node_name);
|
||||||
|
|
||||||
if (escaped == NULL)
|
if (escaped == NULL)
|
||||||
{
|
{
|
||||||
@@ -474,7 +479,7 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
if (runtime_options.event[0] != '\0')
|
if (runtime_options.event[0] != '\0')
|
||||||
{
|
{
|
||||||
char *escaped = escape_string(conn, runtime_options.event);
|
char *escaped = escape_string(conn, runtime_options.event);
|
||||||
|
|
||||||
if (escaped == NULL)
|
if (escaped == NULL)
|
||||||
{
|
{
|
||||||
@@ -516,7 +521,8 @@ do_cluster_event(void)
|
|||||||
exit(ERR_DB_QUERY);
|
exit(ERR_DB_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQntuples(res) == 0) {
|
if (PQntuples(res) == 0)
|
||||||
|
{
|
||||||
/* print this message directly, rather than as a log line */
|
/* print this message directly, rather than as a log line */
|
||||||
printf(_("no matching events found\n"));
|
printf(_("no matching events found\n"));
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@@ -536,14 +542,14 @@ do_cluster_event(void)
|
|||||||
headers_event[i].max_length = strlen(headers_event[i].title);
|
headers_event[i].max_length = strlen(headers_event[i].title);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < PQntuples(res); i++)
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < EVENT_HEADER_COUNT; j++)
|
for (j = 0; j < EVENT_HEADER_COUNT; j++)
|
||||||
{
|
{
|
||||||
headers_event[j].cur_length = strlen(PQgetvalue(res, i, j));
|
headers_event[j].cur_length = strlen(PQgetvalue(res, i, j));
|
||||||
if(headers_event[j].cur_length > headers_event[j].max_length)
|
if (headers_event[j].cur_length > headers_event[j].max_length)
|
||||||
{
|
{
|
||||||
headers_event[j].max_length = headers_event[j].cur_length;
|
headers_event[j].max_length = headers_event[j].cur_length;
|
||||||
}
|
}
|
||||||
@@ -566,7 +572,8 @@ do_cluster_event(void)
|
|||||||
printf("-");
|
printf("-");
|
||||||
for (i = 0; i < EVENT_HEADER_COUNT; i++)
|
for (i = 0; i < EVENT_HEADER_COUNT; i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < headers_event[i].max_length; j++)
|
for (j = 0; j < headers_event[i].max_length; j++)
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
@@ -578,9 +585,9 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
for(i = 0; i < PQntuples(res); i++)
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
printf(" ");
|
printf(" ");
|
||||||
for (j = 0; j < EVENT_HEADER_COUNT; j++)
|
for (j = 0; j < EVENT_HEADER_COUNT; j++)
|
||||||
@@ -590,7 +597,7 @@ do_cluster_event(void)
|
|||||||
PQgetvalue(res, i, j));
|
PQgetvalue(res, i, j));
|
||||||
|
|
||||||
if (j < (EVENT_HEADER_COUNT - 1))
|
if (j < (EVENT_HEADER_COUNT - 1))
|
||||||
printf(" | ");
|
printf(" | ");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -607,7 +614,8 @@ do_cluster_event(void)
|
|||||||
void
|
void
|
||||||
do_cluster_crosscheck(void)
|
do_cluster_crosscheck(void)
|
||||||
{
|
{
|
||||||
int i = 0, n = 0;
|
int i = 0,
|
||||||
|
n = 0;
|
||||||
char c;
|
char c;
|
||||||
const char *node_header = "Name";
|
const char *node_header = "Name";
|
||||||
int name_length = strlen(node_header);
|
int name_length = strlen(node_header);
|
||||||
@@ -630,7 +638,7 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
int column_node_ix;
|
int column_node_ix;
|
||||||
|
|
||||||
printf("%*s | %2d ", name_length,
|
printf("%*s | %2d ", name_length,
|
||||||
cube[i]->node_name,
|
cube[i]->node_name,
|
||||||
@@ -638,26 +646,27 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
for (column_node_ix = 0; column_node_ix < n; column_node_ix++)
|
for (column_node_ix = 0; column_node_ix < n; column_node_ix++)
|
||||||
{
|
{
|
||||||
int max_node_status = -2;
|
int max_node_status = -2;
|
||||||
int node_ix = 0;
|
int node_ix = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The value of entry (i,j) is equal to the
|
* The value of entry (i,j) is equal to the maximum value of all
|
||||||
* maximum value of all the (i,j,k). Indeed:
|
* the (i,j,k). Indeed:
|
||||||
*
|
*
|
||||||
* - if one of the (i,j,k) is 0 (node up), then 0
|
* - if one of the (i,j,k) is 0 (node up), then 0 (the node is
|
||||||
* (the node is up);
|
* up);
|
||||||
*
|
*
|
||||||
* - if the (i,j,k) are either -1 (down) or -2
|
* - if the (i,j,k) are either -1 (down) or -2 (unknown), then -1
|
||||||
* (unknown), then -1 (the node is down);
|
* (the node is down);
|
||||||
*
|
*
|
||||||
* - if all the (i,j,k) are -2 (unknown), then -2
|
* - if all the (i,j,k) are -2 (unknown), then -2 (the node is in
|
||||||
* (the node is in an unknown state).
|
* an unknown state).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for(node_ix = 0; node_ix < n; node_ix ++)
|
for (node_ix = 0; node_ix < n; node_ix++)
|
||||||
{
|
{
|
||||||
int node_status = cube[node_ix]->matrix_list_rec[i]->node_status_list[column_node_ix]->node_status;
|
int node_status = cube[node_ix]->matrix_list_rec[i]->node_status_list[column_node_ix]->node_status;
|
||||||
|
|
||||||
if (node_status > max_node_status)
|
if (node_status > max_node_status)
|
||||||
max_node_status = node_status;
|
max_node_status = node_status;
|
||||||
}
|
}
|
||||||
@@ -685,7 +694,9 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
/* clean up allocated cube array */
|
/* clean up allocated cube array */
|
||||||
{
|
{
|
||||||
int h, j;
|
int h,
|
||||||
|
j;
|
||||||
|
|
||||||
for (h = 0; h < n; h++)
|
for (h = 0; h < n; h++)
|
||||||
{
|
{
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
@@ -710,7 +721,9 @@ do_cluster_crosscheck(void)
|
|||||||
void
|
void
|
||||||
do_cluster_matrix()
|
do_cluster_matrix()
|
||||||
{
|
{
|
||||||
int i = 0, j = 0, n = 0;
|
int i = 0,
|
||||||
|
j = 0,
|
||||||
|
n = 0;
|
||||||
|
|
||||||
const char *node_header = "Name";
|
const char *node_header = "Name";
|
||||||
int name_length = strlen(node_header);
|
int name_length = strlen(node_header);
|
||||||
@@ -730,7 +743,7 @@ do_cluster_matrix()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
printf("%*s | Id ", name_length, node_header);
|
printf("%*s | Id ", name_length, node_header);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
@@ -753,17 +766,17 @@ do_cluster_matrix()
|
|||||||
{
|
{
|
||||||
switch (matrix_rec_list[i]->node_status_list[j]->node_status)
|
switch (matrix_rec_list[i]->node_status_list[j]->node_status)
|
||||||
{
|
{
|
||||||
case -2:
|
case -2:
|
||||||
c = '?';
|
c = '?';
|
||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
c = 'x';
|
c = 'x';
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
c = '*';
|
c = '*';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
exit(ERR_INTERNAL);
|
exit(ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("| %c ", c);
|
printf("| %c ", c);
|
||||||
@@ -789,7 +802,8 @@ do_cluster_matrix()
|
|||||||
static void
|
static void
|
||||||
matrix_set_node_status(t_node_matrix_rec **matrix_rec_list, int n, int node_id, int connection_node_id, int connection_status)
|
matrix_set_node_status(t_node_matrix_rec **matrix_rec_list, int n, int node_id, int connection_node_id, int connection_status)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i,
|
||||||
|
j;
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
@@ -812,10 +826,11 @@ matrix_set_node_status(t_node_matrix_rec **matrix_rec_list, int n, int node_id,
|
|||||||
static int
|
static int
|
||||||
build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
int i = 0, j = 0;
|
int i = 0,
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
j = 0;
|
||||||
int node_count = 0;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
|
int node_count = 0;
|
||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
NodeInfoListCell *cell = NULL;
|
NodeInfoListCell *cell = NULL;
|
||||||
|
|
||||||
@@ -852,9 +867,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
/*
|
/*
|
||||||
* Allocate an empty matrix record list
|
* Allocate an empty matrix record list
|
||||||
*
|
*
|
||||||
* -2 == NULL ?
|
* -2 == NULL ? -1 == Error x 0 == OK *
|
||||||
* -1 == Error x
|
|
||||||
* 0 == OK *
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
matrix_rec_list = (t_node_matrix_rec **) pg_malloc0(sizeof(t_node_matrix_rec) * nodes.node_count);
|
matrix_rec_list = (t_node_matrix_rec **) pg_malloc0(sizeof(t_node_matrix_rec) * nodes.node_count);
|
||||||
@@ -864,7 +877,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
/* Initialise matrix structure for each node */
|
/* Initialise matrix structure for each node */
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
int name_length_cur;
|
int name_length_cur;
|
||||||
NodeInfoListCell *cell_j;
|
NodeInfoListCell *cell_j;
|
||||||
|
|
||||||
matrix_rec_list[i] = (t_node_matrix_rec *) pg_malloc0(sizeof(t_node_matrix_rec));
|
matrix_rec_list[i] = (t_node_matrix_rec *) pg_malloc0(sizeof(t_node_matrix_rec));
|
||||||
@@ -875,7 +888,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
/*
|
/*
|
||||||
* Find the maximum length of a node name
|
* Find the maximum length of a node name
|
||||||
*/
|
*/
|
||||||
name_length_cur = strlen(matrix_rec_list[i]->node_name);
|
name_length_cur = strlen(matrix_rec_list[i]->node_name);
|
||||||
if (name_length_cur > *name_length)
|
if (name_length_cur > *name_length)
|
||||||
*name_length = name_length_cur;
|
*name_length = name_length_cur;
|
||||||
|
|
||||||
@@ -887,7 +900,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
{
|
{
|
||||||
matrix_rec_list[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec));
|
matrix_rec_list[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec));
|
||||||
matrix_rec_list[i]->node_status_list[j]->node_id = cell_j->node_info->node_id;
|
matrix_rec_list[i]->node_status_list[j]->node_id = cell_j->node_info->node_id;
|
||||||
matrix_rec_list[i]->node_status_list[j]->node_status = -2; /* default unknown */
|
matrix_rec_list[i]->node_status_list[j]->node_status = -2; /* default unknown */
|
||||||
|
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
@@ -900,12 +913,14 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
int connection_status = 0;
|
int connection_status = 0;
|
||||||
t_conninfo_param_list remote_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
t_conninfo_param_list remote_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||||
char *host = NULL, *p = NULL;
|
char *host = NULL,
|
||||||
int connection_node_id = cell->node_info->node_id;
|
*p = NULL;
|
||||||
int x, y;
|
int connection_node_id = cell->node_info->node_id;
|
||||||
PGconn *node_conn = NULL;
|
int x,
|
||||||
|
y;
|
||||||
|
PGconn *node_conn = NULL;
|
||||||
|
|
||||||
initialize_conninfo_params(&remote_conninfo, false);
|
initialize_conninfo_params(&remote_conninfo, false);
|
||||||
parse_conninfo_string(cell->node_info->conninfo,
|
parse_conninfo_string(cell->node_info->conninfo,
|
||||||
@@ -948,9 +963,9 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
initPQExpBuffer(&command);
|
initPQExpBuffer(&command);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We'll pass cluster name and database connection string to the remote
|
* We'll pass cluster name and database connection string to the
|
||||||
* repmgr - those are the only values it needs to work, and saves us
|
* remote repmgr - those are the only values it needs to work, and
|
||||||
* making assumptions about the location of repmgr.conf
|
* saves us making assumptions about the location of repmgr.conf
|
||||||
*/
|
*/
|
||||||
appendPQExpBuffer(&command,
|
appendPQExpBuffer(&command,
|
||||||
"\"%s -d '%s' ",
|
"\"%s -d '%s' ",
|
||||||
@@ -975,11 +990,11 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
|
|
||||||
initPQExpBuffer(&command_output);
|
initPQExpBuffer(&command_output);
|
||||||
|
|
||||||
(void)remote_command(
|
(void) remote_command(
|
||||||
host,
|
host,
|
||||||
runtime_options.remote_user,
|
runtime_options.remote_user,
|
||||||
command.data,
|
command.data,
|
||||||
&command_output);
|
&command_output);
|
||||||
|
|
||||||
p = command_output.data;
|
p = command_output.data;
|
||||||
|
|
||||||
@@ -998,7 +1013,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
|||||||
nodes.node_count,
|
nodes.node_count,
|
||||||
connection_node_id,
|
connection_node_id,
|
||||||
x,
|
x,
|
||||||
(y == -1) ? -1 : 0 );
|
(y == -1) ? -1 : 0);
|
||||||
|
|
||||||
while (*p && (*p != '\n'))
|
while (*p && (*p != '\n'))
|
||||||
p++;
|
p++;
|
||||||
@@ -1026,13 +1041,15 @@ static int
|
|||||||
build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
int h, i, j;
|
int h,
|
||||||
|
i,
|
||||||
|
j;
|
||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
NodeInfoListCell *cell = NULL;
|
NodeInfoListCell *cell = NULL;
|
||||||
|
|
||||||
t_node_status_cube **cube;
|
t_node_status_cube **cube;
|
||||||
|
|
||||||
int node_count = 0;
|
int node_count = 0;
|
||||||
|
|
||||||
/* We need to connect to get the list of nodes */
|
/* We need to connect to get the list of nodes */
|
||||||
log_info(_("connecting to database\n"));
|
log_info(_("connecting to database\n"));
|
||||||
@@ -1056,9 +1073,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
/*
|
/*
|
||||||
* Allocate an empty cube matrix structure
|
* Allocate an empty cube matrix structure
|
||||||
*
|
*
|
||||||
* -2 == NULL
|
* -2 == NULL -1 == Error 0 == OK
|
||||||
* -1 == Error
|
|
||||||
* 0 == OK
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cube = (t_node_status_cube **) pg_malloc(sizeof(t_node_status_cube *) * nodes.node_count);
|
cube = (t_node_status_cube **) pg_malloc(sizeof(t_node_status_cube *) * nodes.node_count);
|
||||||
@@ -1067,7 +1082,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
int name_length_cur = 0;
|
int name_length_cur = 0;
|
||||||
NodeInfoListCell *cell_i = NULL;
|
NodeInfoListCell *cell_i = NULL;
|
||||||
|
|
||||||
cube[h] = (t_node_status_cube *) pg_malloc(sizeof(t_node_status_cube));
|
cube[h] = (t_node_status_cube *) pg_malloc(sizeof(t_node_status_cube));
|
||||||
@@ -1077,7 +1092,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
/*
|
/*
|
||||||
* Find the maximum length of a node name
|
* Find the maximum length of a node name
|
||||||
*/
|
*/
|
||||||
name_length_cur = strlen(cube[h]->node_name);
|
name_length_cur = strlen(cube[h]->node_name);
|
||||||
if (name_length_cur > *name_length)
|
if (name_length_cur > *name_length)
|
||||||
*name_length = name_length_cur;
|
*name_length = name_length_cur;
|
||||||
|
|
||||||
@@ -1102,7 +1117,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
{
|
{
|
||||||
cube[h]->matrix_list_rec[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec));
|
cube[h]->matrix_list_rec[i]->node_status_list[j] = (t_node_status_rec *) pg_malloc0(sizeof(t_node_status_rec));
|
||||||
cube[h]->matrix_list_rec[i]->node_status_list[j]->node_id = cell_j->node_info->node_id;
|
cube[h]->matrix_list_rec[i]->node_status_list[j]->node_id = cell_j->node_info->node_id;
|
||||||
cube[h]->matrix_list_rec[i]->node_status_list[j]->node_status = -2; /* default unknown */
|
cube[h]->matrix_list_rec[i]->node_status_list[j]->node_status = -2; /* default unknown */
|
||||||
|
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
@@ -1121,7 +1136,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
int remote_node_id = UNKNOWN_NODE_ID;
|
int remote_node_id = UNKNOWN_NODE_ID;
|
||||||
PQExpBufferData command;
|
PQExpBufferData command;
|
||||||
PQExpBufferData command_output;
|
PQExpBufferData command_output;
|
||||||
|
|
||||||
@@ -1155,14 +1170,14 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
/* fix to work with --node-id */
|
/* fix to work with --node-id */
|
||||||
if (cube[i]->node_id == config_file_options.node_id)
|
if (cube[i]->node_id == config_file_options.node_id)
|
||||||
{
|
{
|
||||||
(void)local_command(
|
(void) local_command(
|
||||||
command.data,
|
command.data,
|
||||||
&command_output);
|
&command_output);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t_conninfo_param_list remote_conninfo;
|
t_conninfo_param_list remote_conninfo;
|
||||||
char *host = NULL;
|
char *host = NULL;
|
||||||
PQExpBufferData quoted_command;
|
PQExpBufferData quoted_command;
|
||||||
|
|
||||||
initPQExpBuffer("ed_command);
|
initPQExpBuffer("ed_command);
|
||||||
@@ -1181,11 +1196,11 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
|
|
||||||
log_verbose(LOG_DEBUG, "build_cluster_crosscheck(): executing\n %s", quoted_command.data);
|
log_verbose(LOG_DEBUG, "build_cluster_crosscheck(): executing\n %s", quoted_command.data);
|
||||||
|
|
||||||
(void)remote_command(
|
(void) remote_command(
|
||||||
host,
|
host,
|
||||||
runtime_options.remote_user,
|
runtime_options.remote_user,
|
||||||
quoted_command.data,
|
quoted_command.data,
|
||||||
&command_output);
|
&command_output);
|
||||||
|
|
||||||
free_conninfo_params(&remote_conninfo);
|
free_conninfo_params(&remote_conninfo);
|
||||||
termPQExpBuffer("ed_command);
|
termPQExpBuffer("ed_command);
|
||||||
@@ -1195,7 +1210,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
|
|
||||||
p = command_output.data;
|
p = command_output.data;
|
||||||
|
|
||||||
if(!strlen(command_output.data))
|
if (!strlen(command_output.data))
|
||||||
{
|
{
|
||||||
termPQExpBuffer(&command_output);
|
termPQExpBuffer(&command_output);
|
||||||
continue;
|
continue;
|
||||||
@@ -1203,9 +1218,9 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
|
|
||||||
for (j = 0; j < (nodes.node_count * nodes.node_count); j++)
|
for (j = 0; j < (nodes.node_count * nodes.node_count); j++)
|
||||||
{
|
{
|
||||||
int matrix_rec_node_id;
|
int matrix_rec_node_id;
|
||||||
int node_status_node_id;
|
int node_status_node_id;
|
||||||
int node_status;
|
int node_status;
|
||||||
|
|
||||||
if (sscanf(p, "%d,%d,%d", &matrix_rec_node_id, &node_status_node_id, &node_status) != 3)
|
if (sscanf(p, "%d,%d,%d", &matrix_rec_node_id, &node_status_node_id, &node_status) != 3)
|
||||||
{
|
{
|
||||||
@@ -1243,7 +1258,9 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
|||||||
static void
|
static void
|
||||||
cube_set_node_status(t_node_status_cube **cube, int n, int execute_node_id, int matrix_node_id, int connection_node_id, int connection_status)
|
cube_set_node_status(t_node_status_cube **cube, int n, int execute_node_id, int matrix_node_id, int connection_node_id, int connection_status)
|
||||||
{
|
{
|
||||||
int h, i, j;
|
int h,
|
||||||
|
i,
|
||||||
|
j;
|
||||||
|
|
||||||
|
|
||||||
for (h = 0; h < n; h++)
|
for (h = 0; h < n; h++)
|
||||||
|
|||||||
@@ -23,21 +23,21 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int node_id;
|
int node_id;
|
||||||
int node_status;
|
int node_status;
|
||||||
} t_node_status_rec;
|
} t_node_status_rec;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
t_node_status_rec **node_status_list;
|
t_node_status_rec **node_status_list;
|
||||||
} t_node_matrix_rec;
|
} t_node_matrix_rec;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
t_node_matrix_rec **matrix_list_rec;
|
t_node_matrix_rec **matrix_list_rec;
|
||||||
} t_node_status_cube;
|
} t_node_status_cube;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -28,4 +28,4 @@ extern void do_node_service(void);
|
|||||||
|
|
||||||
extern void do_node_help(void);
|
extern void do_node_help(void);
|
||||||
|
|
||||||
#endif /* _REPMGR_ACTION_NODE_H_ */
|
#endif /* _REPMGR_ACTION_NODE_H_ */
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ do_primary_register(void)
|
|||||||
|
|
||||||
bool record_created = false;
|
bool record_created = false;
|
||||||
|
|
||||||
PQExpBufferData event_description;
|
PQExpBufferData event_description;
|
||||||
|
|
||||||
log_info(_("connecting to primary database..."));
|
log_info(_("connecting to primary database..."));
|
||||||
|
|
||||||
@@ -83,8 +83,8 @@ do_primary_register(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* In --dry-run mode we can't proceed any further as the following code
|
* In --dry-run mode we can't proceed any further as the following code
|
||||||
* attempts to query the repmgr metadata, which won't exist until
|
* attempts to query the repmgr metadata, which won't exist until the
|
||||||
* the extension is installed
|
* extension is installed
|
||||||
*/
|
*/
|
||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,10 @@ do_primary_register(void)
|
|||||||
{
|
{
|
||||||
if (current_primary_id != config_file_options.node_id)
|
if (current_primary_id != config_file_options.node_id)
|
||||||
{
|
{
|
||||||
/* it's impossible to add a second primary to a streaming replication cluster */
|
/*
|
||||||
|
* it's impossible to add a second primary to a streaming
|
||||||
|
* replication cluster
|
||||||
|
*/
|
||||||
log_error(_("there is already an active registered primary (node ID: %i) in this cluster"), current_primary_id);
|
log_error(_("there is already an active registered primary (node ID: %i) in this cluster"), current_primary_id);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
@@ -115,9 +118,10 @@ do_primary_register(void)
|
|||||||
begin_transaction(conn);
|
begin_transaction(conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for an active primary node record with a different ID. This shouldn't
|
* Check for an active primary node record with a different ID. This
|
||||||
* happen, but could do if an existing primary was shut down without being unregistered.
|
* shouldn't happen, but could do if an existing primary was shut down
|
||||||
*/
|
* without being unregistered.
|
||||||
|
*/
|
||||||
current_primary_id = get_primary_node_id(conn);
|
current_primary_id = get_primary_node_id(conn);
|
||||||
if (current_primary_id != NODE_NOT_FOUND && current_primary_id != config_file_options.node_id)
|
if (current_primary_id != NODE_NOT_FOUND && current_primary_id != config_file_options.node_id)
|
||||||
{
|
{
|
||||||
@@ -130,8 +134,8 @@ do_primary_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether there's an existing record for this node, and
|
* Check whether there's an existing record for this node, and update it
|
||||||
* update it if --force set
|
* if --force set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
record_status = get_node_record(conn, config_file_options.node_id, &node_info);
|
record_status = get_node_record(conn, config_file_options.node_id, &node_info);
|
||||||
@@ -199,12 +203,12 @@ do_primary_register(void)
|
|||||||
|
|
||||||
/* Log the event */
|
/* Log the event */
|
||||||
create_event_notification(
|
create_event_notification(
|
||||||
conn,
|
conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"primary_register",
|
"primary_register",
|
||||||
record_created,
|
record_created,
|
||||||
event_description.data);
|
event_description.data);
|
||||||
|
|
||||||
termPQExpBuffer(&event_description);
|
termPQExpBuffer(&event_description);
|
||||||
|
|
||||||
@@ -241,12 +245,12 @@ do_primary_register(void)
|
|||||||
void
|
void
|
||||||
do_primary_unregister(void)
|
do_primary_unregister(void)
|
||||||
{
|
{
|
||||||
PGconn *primary_conn = NULL;
|
PGconn *primary_conn = NULL;
|
||||||
PGconn *local_conn = NULL;
|
PGconn *local_conn = NULL;
|
||||||
t_node_info local_node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info local_node_info = T_NODE_INFO_INITIALIZER;
|
||||||
|
|
||||||
t_node_info *target_node_info_ptr = NULL;
|
t_node_info *target_node_info_ptr = NULL;
|
||||||
PGconn *target_node_conn = NULL;
|
PGconn *target_node_conn = NULL;
|
||||||
|
|
||||||
NodeInfoList downstream_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList downstream_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
|
||||||
@@ -257,8 +261,8 @@ do_primary_unregister(void)
|
|||||||
get_local_node_record(local_conn, config_file_options.node_id, &local_node_info);
|
get_local_node_record(local_conn, config_file_options.node_id, &local_node_info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain a connection to the current primary node - if this isn't possible,
|
* Obtain a connection to the current primary node - if this isn't
|
||||||
* abort as we won't be able to update the "nodes" table anyway.
|
* possible, abort as we won't be able to update the "nodes" table anyway.
|
||||||
*/
|
*/
|
||||||
primary_conn = establish_primary_db_connection(local_conn, false);
|
primary_conn = establish_primary_db_connection(local_conn, false);
|
||||||
|
|
||||||
@@ -287,7 +291,7 @@ do_primary_unregister(void)
|
|||||||
|
|
||||||
/* Target node is local node? */
|
/* Target node is local node? */
|
||||||
if (target_node_info.node_id == UNKNOWN_NODE_ID
|
if (target_node_info.node_id == UNKNOWN_NODE_ID
|
||||||
|| target_node_info.node_id == config_file_options.node_id)
|
|| target_node_info.node_id == config_file_options.node_id)
|
||||||
{
|
{
|
||||||
target_node_info_ptr = &local_node_info;
|
target_node_info_ptr = &local_node_info;
|
||||||
}
|
}
|
||||||
@@ -306,7 +310,7 @@ do_primary_unregister(void)
|
|||||||
if (downstream_nodes.node_count > 0)
|
if (downstream_nodes.node_count > 0)
|
||||||
{
|
{
|
||||||
NodeInfoListCell *cell = NULL;
|
NodeInfoListCell *cell = NULL;
|
||||||
PQExpBufferData detail;
|
PQExpBufferData detail;
|
||||||
|
|
||||||
if (downstream_nodes.node_count == 1)
|
if (downstream_nodes.node_count == 1)
|
||||||
{
|
{
|
||||||
@@ -361,13 +365,16 @@ do_primary_unregister(void)
|
|||||||
/* If we can connect to the node, perform some sanity checks on it */
|
/* If we can connect to the node, perform some sanity checks on it */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool can_unregister = true;
|
bool can_unregister = true;
|
||||||
RecoveryType recovery_type = get_recovery_type(target_node_conn);
|
RecoveryType recovery_type = get_recovery_type(target_node_conn);
|
||||||
|
|
||||||
/* Node appears to be a standby */
|
/* Node appears to be a standby */
|
||||||
if (recovery_type == RECTYPE_STANDBY)
|
if (recovery_type == RECTYPE_STANDBY)
|
||||||
{
|
{
|
||||||
/* We'll refuse to do anything unless the node record shows it as a primary */
|
/*
|
||||||
|
* We'll refuse to do anything unless the node record shows it as
|
||||||
|
* a primary
|
||||||
|
*/
|
||||||
if (target_node_info_ptr->type != PRIMARY)
|
if (target_node_info_ptr->type != PRIMARY)
|
||||||
{
|
{
|
||||||
log_error(_("node %s (ID: %i) is a %s, unable to unregister"),
|
log_error(_("node %s (ID: %i) is a %s, unable to unregister"),
|
||||||
@@ -376,9 +383,11 @@ do_primary_unregister(void)
|
|||||||
get_node_type_string(target_node_info_ptr->type));
|
get_node_type_string(target_node_info_ptr->type));
|
||||||
can_unregister = false;
|
can_unregister = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If --F/--force not set, hint that it might be appropriate to
|
* If --F/--force not set, hint that it might be appropriate to
|
||||||
* register the node as a standby rather than unregister as primary
|
* register the node as a standby rather than unregister as
|
||||||
|
* primary
|
||||||
*/
|
*/
|
||||||
else if (!runtime_options.force)
|
else if (!runtime_options.force)
|
||||||
{
|
{
|
||||||
@@ -400,8 +409,8 @@ do_primary_unregister(void)
|
|||||||
}
|
}
|
||||||
else if (recovery_type == RECTYPE_PRIMARY)
|
else if (recovery_type == RECTYPE_PRIMARY)
|
||||||
{
|
{
|
||||||
t_node_info primary_node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info primary_node_info = T_NODE_INFO_INITIALIZER;
|
||||||
bool primary_record_found = false;
|
bool primary_record_found = false;
|
||||||
|
|
||||||
primary_record_found = get_primary_node_record(primary_conn, &primary_node_info);
|
primary_record_found = get_primary_node_record(primary_conn, &primary_node_info);
|
||||||
|
|
||||||
@@ -415,8 +424,10 @@ do_primary_unregister(void)
|
|||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
/* This appears to be the cluster primary - cowardly refuse
|
|
||||||
* to delete the record
|
/*
|
||||||
|
* This appears to be the cluster primary - cowardly refuse to
|
||||||
|
* delete the record
|
||||||
*/
|
*/
|
||||||
if (primary_node_info.node_id == target_node_info_ptr->node_id)
|
if (primary_node_info.node_id == target_node_info_ptr->node_id)
|
||||||
{
|
{
|
||||||
@@ -461,8 +472,8 @@ do_primary_unregister(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
bool delete_success = delete_node_record(primary_conn,
|
bool delete_success = delete_node_record(primary_conn,
|
||||||
target_node_info_ptr->node_id);
|
target_node_info_ptr->node_id);
|
||||||
|
|
||||||
if (delete_success == false)
|
if (delete_success == false)
|
||||||
{
|
{
|
||||||
@@ -488,11 +499,11 @@ do_primary_unregister(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_event_notification(primary_conn,
|
create_event_notification(primary_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"primary_unregister",
|
"primary_unregister",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
log_info(_("node %s (ID: %i) was successfully unregistered"),
|
log_info(_("node %s (ID: %i) was successfully unregistered"),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -32,4 +32,4 @@ extern bool do_standby_follow_internal(PGconn *primary_conn, t_node_info *primar
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _REPMGR_ACTION_STANDBY_H_ */
|
#endif /* _REPMGR_ACTION_STANDBY_H_ */
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ typedef struct
|
|||||||
char config_file[MAXPGPATH];
|
char config_file[MAXPGPATH];
|
||||||
bool dry_run;
|
bool dry_run;
|
||||||
bool force;
|
bool force;
|
||||||
char pg_bindir[MAXLEN]; /* overrides setting in repmgr.conf */
|
char pg_bindir[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||||
bool wait;
|
bool wait;
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||||
bool log_to_file;
|
bool log_to_file;
|
||||||
bool terse;
|
bool terse;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
@@ -119,7 +119,7 @@ typedef struct
|
|||||||
/* following options for internal use */
|
/* following options for internal use */
|
||||||
char config_archive_dir[MAXPGPATH];
|
char config_archive_dir[MAXPGPATH];
|
||||||
OutputMode output_mode;
|
OutputMode output_mode;
|
||||||
} t_runtime_options;
|
} t_runtime_options;
|
||||||
|
|
||||||
#define T_RUNTIME_OPTIONS_INITIALIZER { \
|
#define T_RUNTIME_OPTIONS_INITIALIZER { \
|
||||||
/* configuration metadata */ \
|
/* configuration metadata */ \
|
||||||
@@ -160,12 +160,14 @@ typedef struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
barman,
|
barman,
|
||||||
pg_basebackup
|
pg_basebackup
|
||||||
} standy_clone_mode;
|
} standy_clone_mode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
ACTION_UNKNOWN = -1,
|
ACTION_UNKNOWN = -1,
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
ACTION_START,
|
ACTION_START,
|
||||||
@@ -184,21 +186,21 @@ extern t_configuration_options config_file_options;
|
|||||||
t_conninfo_param_list source_conninfo;
|
t_conninfo_param_list source_conninfo;
|
||||||
|
|
||||||
|
|
||||||
extern bool config_file_required;
|
extern bool config_file_required;
|
||||||
extern char pg_bindir[MAXLEN];
|
extern char pg_bindir[MAXLEN];
|
||||||
|
|
||||||
extern t_node_info target_node_info;
|
extern t_node_info target_node_info;
|
||||||
|
|
||||||
|
|
||||||
extern int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string);
|
extern int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string);
|
||||||
extern bool create_repmgr_extension(PGconn *conn);
|
extern bool create_repmgr_extension(PGconn *conn);
|
||||||
extern int test_ssh_connection(char *host, char *remote_user);
|
extern int test_ssh_connection(char *host, char *remote_user);
|
||||||
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
||||||
|
|
||||||
extern standy_clone_mode get_standby_clone_mode(void);
|
extern standy_clone_mode get_standby_clone_mode(void);
|
||||||
|
|
||||||
extern int copy_remote_files(char *host, char *remote_user, char *remote_path,
|
extern int copy_remote_files(char *host, char *remote_user, char *remote_path,
|
||||||
char *local_path, bool is_directory, int server_version_num);
|
char *local_path, bool is_directory, int server_version_num);
|
||||||
|
|
||||||
extern void print_error_list(ItemList *error_list, int log_level);
|
extern void print_error_list(ItemList *error_list, int log_level);
|
||||||
|
|
||||||
@@ -219,4 +221,4 @@ extern bool data_dir_required_for_action(t_server_action action);
|
|||||||
extern void get_node_data_directory(char *data_dir_buf);
|
extern void get_node_data_directory(char *data_dir_buf);
|
||||||
extern void init_node_record(t_node_info *node_record);
|
extern void init_node_record(t_node_info *node_record);
|
||||||
|
|
||||||
#endif /* _REPMGR_CLIENT_GLOBAL_H_ */
|
#endif /* _REPMGR_CLIENT_GLOBAL_H_ */
|
||||||
|
|||||||
985
repmgr-client.c
985
repmgr-client.c
File diff suppressed because it is too large
Load Diff
@@ -141,22 +141,22 @@ static struct option long_options[] =
|
|||||||
|
|
||||||
/* "standby switchover" options */
|
/* "standby switchover" options */
|
||||||
{"remote-config-file", required_argument, NULL, 'C'},
|
{"remote-config-file", required_argument, NULL, 'C'},
|
||||||
{"always-promote", no_argument, NULL, OPT_ALWAYS_PROMOTE },
|
{"always-promote", no_argument, NULL, OPT_ALWAYS_PROMOTE},
|
||||||
{"force-rewind", no_argument, NULL, OPT_FORCE_REWIND },
|
{"force-rewind", no_argument, NULL, OPT_FORCE_REWIND},
|
||||||
{"siblings-follow", no_argument, NULL, OPT_SIBLINGS_FOLLOW },
|
{"siblings-follow", no_argument, NULL, OPT_SIBLINGS_FOLLOW},
|
||||||
|
|
||||||
/* "node status" options */
|
/* "node status" options */
|
||||||
{"is-shutdown-cleanly", no_argument, NULL, OPT_IS_SHUTDOWN_CLEANLY },
|
{"is-shutdown-cleanly", no_argument, NULL, OPT_IS_SHUTDOWN_CLEANLY},
|
||||||
|
|
||||||
/* "node check" options */
|
/* "node check" options */
|
||||||
{"archive-ready", no_argument, NULL, OPT_ARCHIVE_READY },
|
{"archive-ready", no_argument, NULL, OPT_ARCHIVE_READY},
|
||||||
{"downstream", no_argument, NULL, OPT_DOWNSTREAM },
|
{"downstream", no_argument, NULL, OPT_DOWNSTREAM},
|
||||||
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG },
|
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
||||||
{"role", no_argument, NULL, OPT_ROLE },
|
{"role", no_argument, NULL, OPT_ROLE},
|
||||||
{"slots", no_argument, NULL, OPT_SLOTS },
|
{"slots", no_argument, NULL, OPT_SLOTS},
|
||||||
|
|
||||||
/* "node join" options */
|
/* "node join" options */
|
||||||
{"config-files", required_argument, NULL, OPT_CONFIG_FILES },
|
{"config-files", required_argument, NULL, OPT_CONFIG_FILES},
|
||||||
|
|
||||||
/* "node service" options */
|
/* "node service" options */
|
||||||
{"action", required_argument, NULL, OPT_ACTION},
|
{"action", required_argument, NULL, OPT_ACTION},
|
||||||
@@ -165,16 +165,16 @@ static struct option long_options[] =
|
|||||||
{"checkpoint", no_argument, NULL, OPT_CHECKPOINT},
|
{"checkpoint", no_argument, NULL, OPT_CHECKPOINT},
|
||||||
|
|
||||||
/* "cluster event" options */
|
/* "cluster event" options */
|
||||||
{"all", no_argument, NULL, OPT_ALL },
|
{"all", no_argument, NULL, OPT_ALL},
|
||||||
{"event", required_argument, NULL, OPT_EVENT },
|
{"event", required_argument, NULL, OPT_EVENT},
|
||||||
{"limit", required_argument, NULL, OPT_LIMIT },
|
{"limit", required_argument, NULL, OPT_LIMIT},
|
||||||
|
|
||||||
/* Following options for internal use */
|
/* Following options for internal use */
|
||||||
{"config-archive-dir", required_argument, NULL, OPT_CONFIG_ARCHIVE_DIR},
|
{"config-archive-dir", required_argument, NULL, OPT_CONFIG_ARCHIVE_DIR},
|
||||||
|
|
||||||
/* deprecated */
|
/* deprecated */
|
||||||
{"no-conninfo-password", no_argument, NULL, OPT_NO_CONNINFO_PASSWORD},
|
{"no-conninfo-password", no_argument, NULL, OPT_NO_CONNINFO_PASSWORD},
|
||||||
/* legacy alias for -D/--pgdata*/
|
/* legacy alias for -D/--pgdata */
|
||||||
{"data-dir", required_argument, NULL, OPT_DATA_DIR},
|
{"data-dir", required_argument, NULL, OPT_DATA_DIR},
|
||||||
/* --node-id */
|
/* --node-id */
|
||||||
{"node", required_argument, NULL, OPT_NODE},
|
{"node", required_argument, NULL, OPT_NODE},
|
||||||
@@ -204,4 +204,4 @@ static void check_cli_parameters(const int action);
|
|||||||
static void write_primary_conninfo(char *line, t_conninfo_param_list *param_list);
|
static void write_primary_conninfo(char *line, t_conninfo_param_list *param_list);
|
||||||
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
|
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
|
||||||
|
|
||||||
#endif /* _REPMGR_CLIENT_H_ */
|
#endif /* _REPMGR_CLIENT_H_ */
|
||||||
|
|||||||
63
repmgr.c
63
repmgr.c
@@ -49,7 +49,8 @@
|
|||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
LEADER_NODE,
|
LEADER_NODE,
|
||||||
FOLLOWER_NODE,
|
FOLLOWER_NODE,
|
||||||
CANDIDATE_NODE
|
CANDIDATE_NODE
|
||||||
@@ -59,16 +60,16 @@ typedef struct repmgrdSharedState
|
|||||||
{
|
{
|
||||||
LWLockId lock; /* protects search/modification */
|
LWLockId lock; /* protects search/modification */
|
||||||
TimestampTz last_updated;
|
TimestampTz last_updated;
|
||||||
int local_node_id;
|
int local_node_id;
|
||||||
/* streaming failover */
|
/* streaming failover */
|
||||||
NodeState node_state;
|
NodeState node_state;
|
||||||
NodeVotingStatus voting_status;
|
NodeVotingStatus voting_status;
|
||||||
int current_electoral_term;
|
int current_electoral_term;
|
||||||
int candidate_node_id;
|
int candidate_node_id;
|
||||||
bool follow_new_primary;
|
bool follow_new_primary;
|
||||||
/* BDR failover */
|
/* BDR failover */
|
||||||
int bdr_failover_handler;
|
int bdr_failover_handler;
|
||||||
} repmgrdSharedState;
|
} repmgrdSharedState;
|
||||||
|
|
||||||
static repmgrdSharedState *shared_state = NULL;
|
static repmgrdSharedState *shared_state = NULL;
|
||||||
|
|
||||||
@@ -81,40 +82,52 @@ void _PG_fini(void);
|
|||||||
static void repmgr_shmem_startup(void);
|
static void repmgr_shmem_startup(void);
|
||||||
|
|
||||||
Datum set_local_node_id(PG_FUNCTION_ARGS);
|
Datum set_local_node_id(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(set_local_node_id);
|
PG_FUNCTION_INFO_V1(set_local_node_id);
|
||||||
|
|
||||||
Datum standby_set_last_updated(PG_FUNCTION_ARGS);
|
Datum standby_set_last_updated(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(standby_set_last_updated);
|
PG_FUNCTION_INFO_V1(standby_set_last_updated);
|
||||||
|
|
||||||
Datum standby_get_last_updated(PG_FUNCTION_ARGS);
|
Datum standby_get_last_updated(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(standby_get_last_updated);
|
PG_FUNCTION_INFO_V1(standby_get_last_updated);
|
||||||
|
|
||||||
|
|
||||||
Datum request_vote(PG_FUNCTION_ARGS);
|
Datum request_vote(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(request_vote);
|
PG_FUNCTION_INFO_V1(request_vote);
|
||||||
|
|
||||||
Datum get_voting_status(PG_FUNCTION_ARGS);
|
Datum get_voting_status(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(get_voting_status);
|
PG_FUNCTION_INFO_V1(get_voting_status);
|
||||||
|
|
||||||
Datum set_voting_status_initiated(PG_FUNCTION_ARGS);
|
Datum set_voting_status_initiated(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(set_voting_status_initiated);
|
PG_FUNCTION_INFO_V1(set_voting_status_initiated);
|
||||||
|
|
||||||
Datum other_node_is_candidate(PG_FUNCTION_ARGS);
|
Datum other_node_is_candidate(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(other_node_is_candidate);
|
PG_FUNCTION_INFO_V1(other_node_is_candidate);
|
||||||
|
|
||||||
Datum notify_follow_primary(PG_FUNCTION_ARGS);
|
Datum notify_follow_primary(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(notify_follow_primary);
|
PG_FUNCTION_INFO_V1(notify_follow_primary);
|
||||||
|
|
||||||
Datum get_new_primary(PG_FUNCTION_ARGS);
|
Datum get_new_primary(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(get_new_primary);
|
PG_FUNCTION_INFO_V1(get_new_primary);
|
||||||
|
|
||||||
Datum reset_voting_status(PG_FUNCTION_ARGS);
|
Datum reset_voting_status(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(reset_voting_status);
|
PG_FUNCTION_INFO_V1(reset_voting_status);
|
||||||
|
|
||||||
Datum am_bdr_failover_handler(PG_FUNCTION_ARGS);
|
Datum am_bdr_failover_handler(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(am_bdr_failover_handler);
|
PG_FUNCTION_INFO_V1(am_bdr_failover_handler);
|
||||||
|
|
||||||
Datum unset_bdr_failover_handler(PG_FUNCTION_ARGS);
|
Datum unset_bdr_failover_handler(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(unset_bdr_failover_handler);
|
PG_FUNCTION_INFO_V1(unset_bdr_failover_handler);
|
||||||
|
|
||||||
|
|
||||||
@@ -209,7 +222,7 @@ repmgr_shmem_startup(void)
|
|||||||
Datum
|
Datum
|
||||||
set_local_node_id(PG_FUNCTION_ARGS)
|
set_local_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int local_node_id = PG_GETARG_INT32(0);
|
int local_node_id = PG_GETARG_INT32(0);
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -266,15 +279,15 @@ Datum
|
|||||||
request_vote(PG_FUNCTION_ARGS)
|
request_vote(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#ifndef BDR_ONLY
|
#ifndef BDR_ONLY
|
||||||
StringInfoData query;
|
StringInfoData query;
|
||||||
XLogRecPtr our_lsn = InvalidXLogRecPtr;
|
XLogRecPtr our_lsn = InvalidXLogRecPtr;
|
||||||
|
|
||||||
/* node_id used for logging purposes */
|
/* node_id used for logging purposes */
|
||||||
int requesting_node_id = PG_GETARG_INT32(0);
|
int requesting_node_id = PG_GETARG_INT32(0);
|
||||||
int current_electoral_term = PG_GETARG_INT32(1);
|
int current_electoral_term = PG_GETARG_INT32(1);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -299,11 +312,11 @@ request_vote(PG_FUNCTION_ARGS)
|
|||||||
initStringInfo(&query);
|
initStringInfo(&query);
|
||||||
|
|
||||||
appendStringInfo(
|
appendStringInfo(
|
||||||
&query,
|
&query,
|
||||||
#if (PG_VERSION_NUM >= 100000)
|
#if (PG_VERSION_NUM >= 100000)
|
||||||
"SELECT pg_catalog.pg_last_wal_receive_lsn()");
|
"SELECT pg_catalog.pg_last_wal_receive_lsn()");
|
||||||
#else
|
#else
|
||||||
"SELECT pg_catalog.pg_last_xlog_receive_location()");
|
"SELECT pg_catalog.pg_last_xlog_receive_location()");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
elog(DEBUG1, "query: %s", query.data);
|
elog(DEBUG1, "query: %s", query.data);
|
||||||
@@ -331,7 +344,7 @@ request_vote(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
LWLockRelease(shared_state->lock);
|
LWLockRelease(shared_state->lock);
|
||||||
|
|
||||||
// should we free "query" here?
|
/* should we free "query" here? */
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
|
|
||||||
PG_RETURN_LSN(our_lsn);
|
PG_RETURN_LSN(our_lsn);
|
||||||
@@ -365,7 +378,7 @@ Datum
|
|||||||
set_voting_status_initiated(PG_FUNCTION_ARGS)
|
set_voting_status_initiated(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#ifndef BDR_ONLY
|
#ifndef BDR_ONLY
|
||||||
int electoral_term;
|
int electoral_term;
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
LWLockAcquire(shared_state->lock, LW_SHARED);
|
||||||
shared_state->voting_status = VS_VOTE_INITIATED;
|
shared_state->voting_status = VS_VOTE_INITIATED;
|
||||||
@@ -386,8 +399,8 @@ Datum
|
|||||||
other_node_is_candidate(PG_FUNCTION_ARGS)
|
other_node_is_candidate(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#ifndef BDR_ONLY
|
#ifndef BDR_ONLY
|
||||||
int requesting_node_id = PG_GETARG_INT32(0);
|
int requesting_node_id = PG_GETARG_INT32(0);
|
||||||
int electoral_term = PG_GETARG_INT32(1);
|
int electoral_term = PG_GETARG_INT32(1);
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -419,7 +432,7 @@ Datum
|
|||||||
notify_follow_primary(PG_FUNCTION_ARGS)
|
notify_follow_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#ifndef BDR_ONLY
|
#ifndef BDR_ONLY
|
||||||
int primary_node_id = PG_GETARG_INT32(0);
|
int primary_node_id = PG_GETARG_INT32(0);
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -442,7 +455,7 @@ notify_follow_primary(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
get_new_primary(PG_FUNCTION_ARGS)
|
get_new_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int new_primary_node_id = UNKNOWN_NODE_ID;
|
int new_primary_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -481,8 +494,8 @@ reset_voting_status(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
am_bdr_failover_handler(PG_FUNCTION_ARGS)
|
am_bdr_failover_handler(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int node_id = PG_GETARG_INT32(0);
|
int node_id = PG_GETARG_INT32(0);
|
||||||
bool am_handler = false;
|
bool am_handler = false;
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|||||||
24
repmgr.h
24
repmgr.h
@@ -60,17 +60,17 @@
|
|||||||
*/
|
*/
|
||||||
#define DEFAULT_LOCATION "default"
|
#define DEFAULT_LOCATION "default"
|
||||||
#define DEFAULT_PRIORITY 100
|
#define DEFAULT_PRIORITY 100
|
||||||
#define DEFAULT_RECONNECTION_ATTEMPTS 6 /* seconds */
|
#define DEFAULT_RECONNECTION_ATTEMPTS 6 /* seconds */
|
||||||
#define DEFAULT_RECONNECTION_INTERVAL 10 /* seconds */
|
#define DEFAULT_RECONNECTION_INTERVAL 10 /* seconds */
|
||||||
#define DEFAULT_MONITORING_INTERVAL 2 /* seconds */
|
#define DEFAULT_MONITORING_INTERVAL 2 /* seconds */
|
||||||
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PRIMARY_FOLLOW_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PRIMARY_FOLLOW_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_BDR_RECOVERY_TIMEOUT 30 /* seconds */
|
#define DEFAULT_BDR_RECOVERY_TIMEOUT 30 /* seconds */
|
||||||
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
||||||
#define DEFAULT_ARCHIVE_READY_CRITICAL 128 /* WAL files */
|
#define DEFAULT_ARCHIVE_READY_CRITICAL 128 /* WAL files */
|
||||||
#define DEFAULT_REPLICATION_LAG_WARNING 300 /* seconds */
|
#define DEFAULT_REPLICATION_LAG_WARNING 300 /* seconds */
|
||||||
#define DEFAULT_REPLICATION_LAG_CRITICAL 600 /* seconds */
|
#define DEFAULT_REPLICATION_LAG_CRITICAL 600 /* seconds */
|
||||||
|
|
||||||
|
|
||||||
#ifndef RECOVERY_COMMAND_FILE
|
#ifndef RECOVERY_COMMAND_FILE
|
||||||
@@ -83,4 +83,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _REPMGR_H_ */
|
#endif /* _REPMGR_H_ */
|
||||||
|
|||||||
204
repmgrd-bdr.c
204
repmgrd-bdr.c
@@ -39,9 +39,9 @@ do_bdr_node_check(void)
|
|||||||
void
|
void
|
||||||
monitor_bdr(void)
|
monitor_bdr(void)
|
||||||
{
|
{
|
||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
t_bdr_node_info bdr_node_info = T_BDR_NODE_INFO_INITIALIZER;
|
t_bdr_node_info bdr_node_info = T_BDR_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status;
|
RecordStatus record_status;
|
||||||
NodeInfoListCell *cell;
|
NodeInfoListCell *cell;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
instr_time log_status_interval_start;
|
instr_time log_status_interval_start;
|
||||||
@@ -65,8 +65,7 @@ monitor_bdr(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that database is a BDR one
|
* Verify that database is a BDR one TODO: check if supported BDR version?
|
||||||
* TODO: check if supported BDR version?
|
|
||||||
*/
|
*/
|
||||||
log_info(_("connected to database, checking for BDR"));
|
log_info(_("connected to database, checking for BDR"));
|
||||||
|
|
||||||
@@ -81,7 +80,10 @@ monitor_bdr(void)
|
|||||||
log_error(_("repmgr metadata table 'repmgr.%s' is not in the 'repmgr' replication set"),
|
log_error(_("repmgr metadata table 'repmgr.%s' is not in the 'repmgr' replication set"),
|
||||||
"nodes");
|
"nodes");
|
||||||
|
|
||||||
/* TODO: add `repmgr bdr sync` or similar for this situation, and hint here */
|
/*
|
||||||
|
* TODO: add `repmgr bdr sync` or similar for this situation, and hint
|
||||||
|
* here
|
||||||
|
*/
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -100,8 +102,8 @@ monitor_bdr(void)
|
|||||||
record_status = get_node_record(local_conn, config_file_options.node_id, &local_node_info);
|
record_status = get_node_record(local_conn, config_file_options.node_id, &local_node_info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Terminate if we can't find the local node record. This is a "fix-the-config"
|
* Terminate if we can't find the local node record. This is a
|
||||||
* situation, not a lot else we can do.
|
* "fix-the-config" situation, not a lot else we can do.
|
||||||
*/
|
*/
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
@@ -139,7 +141,8 @@ monitor_bdr(void)
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* retrieve list of all nodes - we'll need these if the DB connection goes away
|
* retrieve list of all nodes - we'll need these if the DB connection goes
|
||||||
|
* away
|
||||||
*/
|
*/
|
||||||
get_all_node_records(local_conn, &nodes);
|
get_all_node_records(local_conn, &nodes);
|
||||||
|
|
||||||
@@ -184,80 +187,81 @@ monitor_bdr(void)
|
|||||||
switch (cell->node_info->monitoring_state)
|
switch (cell->node_info->monitoring_state)
|
||||||
{
|
{
|
||||||
case MS_NORMAL:
|
case MS_NORMAL:
|
||||||
{
|
|
||||||
if (is_server_available(cell->node_info->conninfo) == false)
|
|
||||||
{
|
{
|
||||||
/* node is down, we were expecting it to be up */
|
if (is_server_available(cell->node_info->conninfo) == false)
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
|
||||||
{
|
{
|
||||||
instr_time node_unreachable_start;
|
/* node is down, we were expecting it to be up */
|
||||||
INSTR_TIME_SET_CURRENT(node_unreachable_start);
|
|
||||||
|
|
||||||
cell->node_info->node_status = NODE_STATUS_DOWN;
|
|
||||||
|
|
||||||
if (cell->node_info->conn != NULL)
|
|
||||||
{
|
|
||||||
PQfinish(cell->node_info->conn);
|
|
||||||
cell->node_info->conn = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning(_("unable to connect to node %s (ID %i)"),
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
cell->node_info->conn = try_reconnect(cell->node_info);
|
|
||||||
|
|
||||||
/* node has recovered - log and continue */
|
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
int node_unreachable_elapsed = calculate_elapsed(node_unreachable_start);
|
instr_time node_unreachable_start;
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
INSTR_TIME_SET_CURRENT(node_unreachable_start);
|
||||||
|
|
||||||
appendPQExpBuffer(&event_details,
|
cell->node_info->node_status = NODE_STATUS_DOWN;
|
||||||
_("reconnected to node %i after %i seconds"),
|
|
||||||
cell->node_info->node_id,
|
|
||||||
node_unreachable_elapsed);
|
|
||||||
log_notice("%s", event_details.data);
|
|
||||||
|
|
||||||
create_event_notification(cell->node_info->conn,
|
if (cell->node_info->conn != NULL)
|
||||||
&config_file_options,
|
{
|
||||||
config_file_options.node_id,
|
PQfinish(cell->node_info->conn);
|
||||||
"bdr_reconnect",
|
cell->node_info->conn = NULL;
|
||||||
true,
|
}
|
||||||
event_details.data);
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
|
|
||||||
goto loop;
|
log_warning(_("unable to connect to node %s (ID %i)"),
|
||||||
}
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
cell->node_info->conn = try_reconnect(cell->node_info);
|
||||||
|
|
||||||
/* still down after reconnect attempt(s) */
|
/* node has recovered - log and continue */
|
||||||
if (cell->node_info->node_status == NODE_STATUS_DOWN)
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
do_bdr_failover(&nodes, cell->node_info);
|
int node_unreachable_elapsed = calculate_elapsed(node_unreachable_start);
|
||||||
goto loop;
|
|
||||||
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("reconnected to node %i after %i seconds"),
|
||||||
|
cell->node_info->node_id,
|
||||||
|
node_unreachable_elapsed);
|
||||||
|
log_notice("%s", event_details.data);
|
||||||
|
|
||||||
|
create_event_notification(cell->node_info->conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"bdr_reconnect",
|
||||||
|
true,
|
||||||
|
event_details.data);
|
||||||
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* still down after reconnect attempt(s) */
|
||||||
|
if (cell->node_info->node_status == NODE_STATUS_DOWN)
|
||||||
|
{
|
||||||
|
do_bdr_failover(&nodes, cell->node_info);
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
case MS_DEGRADED:
|
case MS_DEGRADED:
|
||||||
{
|
|
||||||
/* degraded monitoring */
|
|
||||||
if (is_server_available(cell->node_info->conninfo) == true)
|
|
||||||
{
|
{
|
||||||
do_bdr_recovery(&nodes, cell->node_info);
|
/* degraded monitoring */
|
||||||
}
|
if (is_server_available(cell->node_info->conninfo) == true)
|
||||||
|
{
|
||||||
|
do_bdr_recovery(&nodes, cell->node_info);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
|
|
||||||
/* emit "still alive" log message at regular intervals, if requested */
|
/* emit "still alive" log message at regular intervals, if requested */
|
||||||
if (config_file_options.log_status_interval > 0)
|
if (config_file_options.log_status_interval > 0)
|
||||||
{
|
{
|
||||||
int log_status_interval_elapsed = calculate_elapsed(log_status_interval_start);
|
int log_status_interval_elapsed = calculate_elapsed(log_status_interval_start);
|
||||||
|
|
||||||
if (log_status_interval_elapsed >= config_file_options.log_status_interval)
|
if (log_status_interval_elapsed >= config_file_options.log_status_interval)
|
||||||
{
|
{
|
||||||
@@ -270,9 +274,9 @@ monitor_bdr(void)
|
|||||||
if (cell->node_info->monitoring_state == MS_DEGRADED)
|
if (cell->node_info->monitoring_state == MS_DEGRADED)
|
||||||
{
|
{
|
||||||
log_detail(
|
log_detail(
|
||||||
_("monitoring node \"%s\" (ID: %i) in degraded mode"),
|
_("monitoring node \"%s\" (ID: %i) in degraded mode"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INSTR_TIME_SET_CURRENT(log_status_interval_start);
|
INSTR_TIME_SET_CURRENT(log_status_interval_start);
|
||||||
@@ -282,8 +286,7 @@ monitor_bdr(void)
|
|||||||
if (got_SIGHUP)
|
if (got_SIGHUP)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* if we can reload, then could need to change
|
* if we can reload, then could need to change local_conn
|
||||||
* local_conn
|
|
||||||
*/
|
*/
|
||||||
if (reload_config(&config_file_options))
|
if (reload_config(&config_file_options))
|
||||||
{
|
{
|
||||||
@@ -350,8 +353,8 @@ do_bdr_failover(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
NodeInfoListCell *cell;
|
NodeInfoListCell *cell;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
||||||
t_node_info target_node = T_NODE_INFO_INITIALIZER;
|
t_node_info target_node = T_NODE_INFO_INITIALIZER;
|
||||||
t_node_info failed_node = T_NODE_INFO_INITIALIZER;
|
t_node_info failed_node = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status;
|
RecordStatus record_status;
|
||||||
|
|
||||||
/* if one of the two nodes is down, cluster will be in a degraded state */
|
/* if one of the two nodes is down, cluster will be in a degraded state */
|
||||||
@@ -372,7 +375,10 @@ do_bdr_failover(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
{
|
{
|
||||||
log_debug("do_bdr_failover() %s", cell->node_info->node_name);
|
log_debug("do_bdr_failover() %s", cell->node_info->node_name);
|
||||||
|
|
||||||
/* don't attempt to connect to the current monitored node, as that's the one which has failed */
|
/*
|
||||||
|
* don't attempt to connect to the current monitored node, as that's
|
||||||
|
* the one which has failed
|
||||||
|
*/
|
||||||
if (cell->node_info->node_id == monitored_node->node_id)
|
if (cell->node_info->node_id == monitored_node->node_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -459,21 +465,21 @@ do_bdr_failover(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
/*
|
/*
|
||||||
* Create an event record
|
* Create an event record
|
||||||
*
|
*
|
||||||
* If we were able to connect to another node, we'll update the
|
* If we were able to connect to another node, we'll update the event log
|
||||||
* event log there.
|
* there.
|
||||||
*
|
*
|
||||||
* In any case the event notification command will be triggered
|
* In any case the event notification command will be triggered with the
|
||||||
* with the event "bdr_failover"
|
* event "bdr_failover"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create_event_notification_extended(
|
create_event_notification_extended(
|
||||||
next_node_conn,
|
next_node_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
monitored_node->node_id,
|
monitored_node->node_id,
|
||||||
"bdr_failover",
|
"bdr_failover",
|
||||||
true,
|
true,
|
||||||
event_details.data,
|
event_details.data,
|
||||||
&event_info);
|
&event_info);
|
||||||
|
|
||||||
log_info("%s", event_details.data);
|
log_info("%s", event_details.data);
|
||||||
|
|
||||||
@@ -490,15 +496,15 @@ do_bdr_failover(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
static void
|
static void
|
||||||
do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
||||||
{
|
{
|
||||||
PGconn *recovered_node_conn;
|
PGconn *recovered_node_conn;
|
||||||
|
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
||||||
int i;
|
int i;
|
||||||
bool slot_reactivated = false;
|
bool slot_reactivated = false;
|
||||||
int node_recovery_elapsed;
|
int node_recovery_elapsed;
|
||||||
|
|
||||||
char node_name[MAXLEN] = "";
|
char node_name[MAXLEN] = "";
|
||||||
|
|
||||||
log_debug("handling recovery for monitored node %i", monitored_node->node_id);
|
log_debug("handling recovery for monitored node %i", monitored_node->node_id);
|
||||||
|
|
||||||
@@ -519,7 +525,7 @@ do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
/*
|
/*
|
||||||
* still unable to connect - the local node is probably down, so we can't
|
* still unable to connect - the local node is probably down, so we can't
|
||||||
* check for reconnection
|
* check for reconnection
|
||||||
*/
|
*/
|
||||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
if (PQstatus(local_conn) != CONNECTION_OK)
|
||||||
{
|
{
|
||||||
local_conn = NULL;
|
local_conn = NULL;
|
||||||
@@ -532,11 +538,11 @@ do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
monitored_node->node_status = NODE_STATUS_UP;
|
monitored_node->node_status = NODE_STATUS_UP;
|
||||||
|
|
||||||
appendPQExpBuffer(
|
appendPQExpBuffer(
|
||||||
&event_details,
|
&event_details,
|
||||||
_("node \"%s\" (ID: %i) has become available after %i seconds"),
|
_("node \"%s\" (ID: %i) has become available after %i seconds"),
|
||||||
monitored_node->node_name,
|
monitored_node->node_name,
|
||||||
monitored_node->node_id,
|
monitored_node->node_id,
|
||||||
node_recovery_elapsed);
|
node_recovery_elapsed);
|
||||||
|
|
||||||
log_notice("%s", event_details.data);
|
log_notice("%s", event_details.data);
|
||||||
|
|
||||||
@@ -560,8 +566,8 @@ do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
log_debug("checking for state of replication slot for node \"%s\"", node_name);
|
log_debug("checking for state of replication slot for node \"%s\"", node_name);
|
||||||
|
|
||||||
slot_status = get_bdr_node_replication_slot_status(
|
slot_status = get_bdr_node_replication_slot_status(
|
||||||
local_conn,
|
local_conn,
|
||||||
node_name);
|
node_name);
|
||||||
|
|
||||||
if (slot_status == SLOT_ACTIVE)
|
if (slot_status == SLOT_ACTIVE)
|
||||||
{
|
{
|
||||||
@@ -621,13 +627,13 @@ do_bdr_recovery(NodeInfoList *nodes, t_node_info *monitored_node)
|
|||||||
event_info.node_name = monitored_node->node_name;
|
event_info.node_name = monitored_node->node_name;
|
||||||
|
|
||||||
create_event_notification_extended(
|
create_event_notification_extended(
|
||||||
local_conn,
|
local_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"bdr_recovery",
|
"bdr_recovery",
|
||||||
true,
|
true,
|
||||||
event_details.data,
|
event_details.data,
|
||||||
&event_info);
|
&event_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,4 @@
|
|||||||
extern void do_bdr_node_check(void);
|
extern void do_bdr_node_check(void);
|
||||||
extern void monitor_bdr(void);
|
extern void monitor_bdr(void);
|
||||||
|
|
||||||
#endif /* _REPMGRD_BDR_H_ */
|
#endif /* _REPMGRD_BDR_H_ */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,10 +19,10 @@
|
|||||||
#ifndef _REPMGRD_PHYSICAL_H_
|
#ifndef _REPMGRD_PHYSICAL_H_
|
||||||
#define _REPMGRD_PHYSICAL_H_
|
#define _REPMGRD_PHYSICAL_H_
|
||||||
|
|
||||||
void do_physical_node_check(void);
|
void do_physical_node_check(void);
|
||||||
|
|
||||||
void monitor_streaming_primary(void);
|
void monitor_streaming_primary(void);
|
||||||
void monitor_streaming_standby(void);
|
void monitor_streaming_standby(void);
|
||||||
void close_connections_physical(void);
|
void close_connections_physical(void);
|
||||||
|
|
||||||
#endif /* _REPMGRD_PHYSICAL_H_ */
|
#endif /* _REPMGRD_PHYSICAL_H_ */
|
||||||
|
|||||||
124
repmgrd.c
124
repmgrd.c
@@ -33,10 +33,10 @@
|
|||||||
#define OPT_HELP 1
|
#define OPT_HELP 1
|
||||||
|
|
||||||
|
|
||||||
static char *config_file = NULL;
|
static char *config_file = NULL;
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
static char *pid_file = NULL;
|
static char *pid_file = NULL;
|
||||||
static bool daemonize = false;
|
static bool daemonize = false;
|
||||||
|
|
||||||
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
|
|
||||||
@@ -46,15 +46,15 @@ PGconn *local_conn = NULL;
|
|||||||
|
|
||||||
|
|
||||||
/* Collate command line errors here for friendlier reporting */
|
/* Collate command line errors here for friendlier reporting */
|
||||||
static ItemList cli_errors = { NULL, NULL };
|
static ItemList cli_errors = {NULL, NULL};
|
||||||
|
|
||||||
bool startup_event_logged = false;
|
bool startup_event_logged = false;
|
||||||
|
|
||||||
MonitoringState monitoring_state = MS_NORMAL;
|
MonitoringState monitoring_state = MS_NORMAL;
|
||||||
instr_time degraded_monitoring_start;
|
instr_time degraded_monitoring_start;
|
||||||
|
|
||||||
static void close_connections(void);
|
static void close_connections(void);
|
||||||
void (*_close_connections)(void) = NULL;
|
void (*_close_connections) (void) = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record receipt of SIGHUP; will cause configuration file to be reread
|
* Record receipt of SIGHUP; will cause configuration file to be reread
|
||||||
@@ -76,9 +76,9 @@ static void handle_sighup(SIGNAL_ARGS);
|
|||||||
static void handle_sigint(SIGNAL_ARGS);
|
static void handle_sigint(SIGNAL_ARGS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int calculate_elapsed(instr_time start_time);
|
int calculate_elapsed(instr_time start_time);
|
||||||
void update_registration(PGconn *conn);
|
void update_registration(PGconn *conn);
|
||||||
void terminate(int retval);
|
void terminate(int retval);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
@@ -116,7 +116,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
srand ( time(NULL) );
|
srand(time(NULL));
|
||||||
|
|
||||||
/* Disallow running as root */
|
/* Disallow running as root */
|
||||||
if (geteuid() == 0)
|
if (geteuid() == 0)
|
||||||
@@ -126,7 +126,7 @@ main(int argc, char **argv)
|
|||||||
"Please log in (using, e.g., \"su\") as the "
|
"Please log in (using, e.g., \"su\") as the "
|
||||||
"(unprivileged) user that owns "
|
"(unprivileged) user that owns "
|
||||||
"the data directory.\n"
|
"the data directory.\n"
|
||||||
),
|
),
|
||||||
progname());
|
progname());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ main(int argc, char **argv)
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* general options */
|
/* general options */
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
/* Actual help option given */
|
/* Actual help option given */
|
||||||
@@ -154,20 +154,22 @@ main(int argc, char **argv)
|
|||||||
exit(SUCCESS);
|
exit(SUCCESS);
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in contrast to repmgr3 and earlier, we only display the repmgr version
|
* in contrast to repmgr3 and earlier, we only display the
|
||||||
* as it's not specific to a particular PostgreSQL version
|
* repmgr version as it's not specific to a particular
|
||||||
|
* PostgreSQL version
|
||||||
*/
|
*/
|
||||||
printf("%s %s\n", progname(), REPMGR_VERSION);
|
printf("%s %s\n", progname(), REPMGR_VERSION);
|
||||||
exit(SUCCESS);
|
exit(SUCCESS);
|
||||||
|
|
||||||
/* configuration options */
|
/* configuration options */
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
config_file = optarg;
|
config_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* daemon options */
|
/* daemon options */
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
daemonize = true;
|
daemonize = true;
|
||||||
@@ -177,40 +179,42 @@ main(int argc, char **argv)
|
|||||||
pid_file = optarg;
|
pid_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
|
|
||||||
/* -L/--log-level */
|
/* -L/--log-level */
|
||||||
case 'L':
|
case 'L':
|
||||||
{
|
|
||||||
int detected_cli_log_level = detect_log_level(optarg);
|
|
||||||
if (detected_cli_log_level != -1)
|
|
||||||
{
|
{
|
||||||
strncpy(cli_log_level, optarg, MAXLEN);
|
int detected_cli_log_level = detect_log_level(optarg);
|
||||||
|
|
||||||
|
if (detected_cli_log_level != -1)
|
||||||
|
{
|
||||||
|
strncpy(cli_log_level, optarg, MAXLEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PQExpBufferData invalid_log_level;
|
||||||
|
|
||||||
|
initPQExpBuffer(&invalid_log_level);
|
||||||
|
appendPQExpBuffer(&invalid_log_level,
|
||||||
|
_("invalid log level \"%s\" provided"),
|
||||||
|
optarg);
|
||||||
|
item_list_append(&cli_errors, invalid_log_level.data);
|
||||||
|
termPQExpBuffer(&invalid_log_level);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
PQExpBufferData invalid_log_level;
|
|
||||||
initPQExpBuffer(&invalid_log_level);
|
|
||||||
appendPQExpBuffer(&invalid_log_level,
|
|
||||||
_("invalid log level \"%s\" provided"),
|
|
||||||
optarg);
|
|
||||||
item_list_append(&cli_errors, invalid_log_level.data);
|
|
||||||
termPQExpBuffer(&invalid_log_level);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* legacy options */
|
/* legacy options */
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
cli_monitoring_history = true;
|
cli_monitoring_history = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unknown_option:
|
unknown_option:
|
||||||
show_usage();
|
show_usage();
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -223,6 +227,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
startup_event_logged = false;
|
startup_event_logged = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the logger we're a daemon - this will ensure any output logged
|
* Tell the logger we're a daemon - this will ensure any output logged
|
||||||
* before the logger is initialized will be formatted correctly
|
* before the logger is initialized will be formatted correctly
|
||||||
@@ -230,15 +235,19 @@ main(int argc, char **argv)
|
|||||||
logger_output_mode = OM_DAEMON;
|
logger_output_mode = OM_DAEMON;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the configuration file, if provided. If no configuration file
|
* Parse the configuration file, if provided. If no configuration file was
|
||||||
* was provided, or one was but was incomplete, parse_config() will
|
* provided, or one was but was incomplete, parse_config() will abort
|
||||||
* abort anyway, with an appropriate message.
|
* anyway, with an appropriate message.
|
||||||
*/
|
*/
|
||||||
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
||||||
|
|
||||||
|
|
||||||
/* Some configuration file items can be overriden by command line options */
|
/* Some configuration file items can be overriden by command line options */
|
||||||
/* Command-line parameter -L/--log-level overrides any setting in config file*/
|
|
||||||
|
/*
|
||||||
|
* Command-line parameter -L/--log-level overrides any setting in config
|
||||||
|
* file
|
||||||
|
*/
|
||||||
if (*cli_log_level != '\0')
|
if (*cli_log_level != '\0')
|
||||||
{
|
{
|
||||||
strncpy(config_file_options.log_level, cli_log_level, MAXLEN);
|
strncpy(config_file_options.log_level, cli_log_level, MAXLEN);
|
||||||
@@ -304,8 +313,8 @@ main(int argc, char **argv)
|
|||||||
* point, but we'll skip that and assume the presence of a node record
|
* point, but we'll skip that and assume the presence of a node record
|
||||||
* means we're dealing with a supported installation.
|
* means we're dealing with a supported installation.
|
||||||
*
|
*
|
||||||
* The absence of a node record will also indicate that either the node
|
* The absence of a node record will also indicate that either the node or
|
||||||
* or repmgr has not been properly configured.
|
* repmgr has not been properly configured.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Retrieve record for this node from the local database */
|
/* Retrieve record for this node from the local database */
|
||||||
@@ -368,7 +377,7 @@ start_monitoring(void)
|
|||||||
local_node_info.node_name,
|
local_node_info.node_name,
|
||||||
local_node_info.node_id);
|
local_node_info.node_id);
|
||||||
|
|
||||||
while(true)
|
while (true)
|
||||||
{
|
{
|
||||||
switch (local_node_info.type)
|
switch (local_node_info.type)
|
||||||
{
|
{
|
||||||
@@ -398,13 +407,15 @@ start_monitoring(void)
|
|||||||
void
|
void
|
||||||
update_registration(PGconn *conn)
|
update_registration(PGconn *conn)
|
||||||
{
|
{
|
||||||
bool success = update_node_record_conn_priority(local_conn,
|
bool success = update_node_record_conn_priority(local_conn,
|
||||||
&config_file_options);
|
&config_file_options);
|
||||||
// check values have actually changed
|
|
||||||
|
/* check values have actually changed */
|
||||||
|
|
||||||
if (success == false)
|
if (success == false)
|
||||||
{
|
{
|
||||||
PQExpBufferData errmsg;
|
PQExpBufferData errmsg;
|
||||||
|
|
||||||
initPQExpBuffer(&errmsg);
|
initPQExpBuffer(&errmsg);
|
||||||
|
|
||||||
appendPQExpBuffer(&errmsg,
|
appendPQExpBuffer(&errmsg,
|
||||||
@@ -620,11 +631,11 @@ show_help(void)
|
|||||||
PGconn *
|
PGconn *
|
||||||
try_reconnect(t_node_info *node_info)
|
try_reconnect(t_node_info *node_info)
|
||||||
{
|
{
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
int max_attempts = config_file_options.reconnect_attempts;
|
int max_attempts = config_file_options.reconnect_attempts;
|
||||||
|
|
||||||
for (i = 0; i < max_attempts; i++)
|
for (i = 0; i < max_attempts; i++)
|
||||||
{
|
{
|
||||||
@@ -635,10 +646,9 @@ try_reconnect(t_node_info *node_info)
|
|||||||
log_notice(_("node has recovered, reconnecting"));
|
log_notice(_("node has recovered, reconnecting"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX we should also handle the case where node is pingable
|
* XXX we should also handle the case where node is pingable but
|
||||||
* but connection denied due to connection exhaustion
|
* connection denied due to connection exhaustion - fall back to
|
||||||
* - fall back to degraded monitoring?
|
* degraded monitoring? - make that configurable
|
||||||
* - make that configurable
|
|
||||||
*/
|
*/
|
||||||
conn = establish_db_connection(node_info->conninfo, false);
|
conn = establish_db_connection(node_info->conninfo, false);
|
||||||
if (PQstatus(conn) == CONNECTION_OK)
|
if (PQstatus(conn) == CONNECTION_OK)
|
||||||
@@ -680,14 +690,14 @@ calculate_elapsed(instr_time start_time)
|
|||||||
|
|
||||||
INSTR_TIME_SUBTRACT(current_time, start_time);
|
INSTR_TIME_SUBTRACT(current_time, start_time);
|
||||||
|
|
||||||
return (int)INSTR_TIME_GET_DOUBLE(current_time);
|
return (int) INSTR_TIME_GET_DOUBLE(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
print_monitoring_state(MonitoringState monitoring_state)
|
print_monitoring_state(MonitoringState monitoring_state)
|
||||||
{
|
{
|
||||||
switch(monitoring_state)
|
switch (monitoring_state)
|
||||||
{
|
{
|
||||||
case MS_NORMAL:
|
case MS_NORMAL:
|
||||||
return "normal";
|
return "normal";
|
||||||
@@ -730,5 +740,3 @@ terminate(int retval)
|
|||||||
|
|
||||||
exit(retval);
|
exit(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
repmgrd.h
16
repmgrd.h
@@ -12,18 +12,18 @@
|
|||||||
|
|
||||||
extern volatile sig_atomic_t got_SIGHUP;
|
extern volatile sig_atomic_t got_SIGHUP;
|
||||||
extern MonitoringState monitoring_state;
|
extern MonitoringState monitoring_state;
|
||||||
extern instr_time degraded_monitoring_start;
|
extern instr_time degraded_monitoring_start;
|
||||||
|
|
||||||
extern t_configuration_options config_file_options;
|
extern t_configuration_options config_file_options;
|
||||||
extern t_node_info local_node_info;
|
extern t_node_info local_node_info;
|
||||||
extern PGconn *local_conn;
|
extern PGconn *local_conn;
|
||||||
extern bool startup_event_logged;
|
extern bool startup_event_logged;
|
||||||
|
|
||||||
PGconn *try_reconnect(t_node_info *node_info);
|
PGconn *try_reconnect(t_node_info *node_info);
|
||||||
|
|
||||||
int calculate_elapsed(instr_time start_time);
|
int calculate_elapsed(instr_time start_time);
|
||||||
const char *print_monitoring_state(MonitoringState monitoring_state);
|
const char *print_monitoring_state(MonitoringState monitoring_state);
|
||||||
|
|
||||||
void update_registration(PGconn *conn);
|
void update_registration(PGconn *conn);
|
||||||
void terminate(int retval);
|
void terminate(int retval);
|
||||||
#endif /* _REPMGRD_H_ */
|
#endif /* _REPMGRD_H_ */
|
||||||
|
|||||||
30
strutil.c
30
strutil.c
@@ -76,7 +76,7 @@ maxpath_snprintf(char *str, const char *format,...)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
append_where_clause(PQExpBufferData *where_clause, const char *format, ...)
|
append_where_clause(PQExpBufferData *where_clause, const char *format,...)
|
||||||
{
|
{
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
char stringbuf[MAXLEN];
|
char stringbuf[MAXLEN];
|
||||||
@@ -85,7 +85,7 @@ append_where_clause(PQExpBufferData *where_clause, const char *format, ...)
|
|||||||
(void) xvsnprintf(stringbuf, MAXLEN, format, arglist);
|
(void) xvsnprintf(stringbuf, MAXLEN, format, arglist);
|
||||||
va_end(arglist);
|
va_end(arglist);
|
||||||
|
|
||||||
if(where_clause->data[0] == '\0')
|
if (where_clause->data[0] == '\0')
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(where_clause,
|
appendPQExpBuffer(where_clause,
|
||||||
" WHERE ");
|
" WHERE ");
|
||||||
@@ -110,10 +110,10 @@ item_list_append(ItemList *item_list, const char *message)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
item_list_append_format(ItemList *item_list, const char *format, ...)
|
item_list_append_format(ItemList *item_list, const char *format,...)
|
||||||
{
|
{
|
||||||
ItemListCell *cell;
|
ItemListCell *cell;
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
|
|
||||||
cell = (ItemListCell *) pg_malloc0(sizeof(ItemListCell));
|
cell = (ItemListCell *) pg_malloc0(sizeof(ItemListCell));
|
||||||
|
|
||||||
@@ -166,11 +166,11 @@ key_value_list_set(KeyValueList *item_list, const char *key, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value, ...)
|
key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value,...)
|
||||||
{
|
{
|
||||||
KeyValueListCell *cell = NULL;
|
KeyValueListCell *cell = NULL;
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
int keylen = 0;
|
int keylen = 0;
|
||||||
|
|
||||||
cell = (KeyValueListCell *) pg_malloc0(sizeof(KeyValueListCell));
|
cell = (KeyValueListCell *) pg_malloc0(sizeof(KeyValueListCell));
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ key_value_list_set_format(KeyValueList *item_list, const char *key, const char *
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
key_value_list_set_output_mode (KeyValueList *item_list, const char *key, OutputMode mode)
|
key_value_list_set_output_mode(KeyValueList *item_list, const char *key, OutputMode mode)
|
||||||
{
|
{
|
||||||
KeyValueListCell *cell = NULL;
|
KeyValueListCell *cell = NULL;
|
||||||
|
|
||||||
@@ -250,11 +250,11 @@ check_status_list_set(CheckStatusList *list, const char *item, CheckStatus statu
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
check_status_list_set_format(CheckStatusList *list, const char *item, CheckStatus status, const char *details, ...)
|
check_status_list_set_format(CheckStatusList *list, const char *item, CheckStatus status, const char *details,...)
|
||||||
{
|
{
|
||||||
CheckStatusListCell *cell;
|
CheckStatusListCell *cell;
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
int itemlen;
|
int itemlen;
|
||||||
|
|
||||||
cell = (CheckStatusListCell *) pg_malloc0(sizeof(CheckStatusListCell));
|
cell = (CheckStatusListCell *) pg_malloc0(sizeof(CheckStatusListCell));
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ escape_recovery_conf_value(const char *src)
|
|||||||
char *
|
char *
|
||||||
escape_string(PGconn *conn, const char *string)
|
escape_string(PGconn *conn, const char *string)
|
||||||
{
|
{
|
||||||
char *escaped_string;
|
char *escaped_string;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
escaped_string = pg_malloc0(MAXLEN);
|
escaped_string = pg_malloc0(MAXLEN);
|
||||||
@@ -372,7 +372,7 @@ escape_string(PGconn *conn, const char *string)
|
|||||||
char *
|
char *
|
||||||
string_skip_prefix(const char *prefix, char *string)
|
string_skip_prefix(const char *prefix, char *string)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = strlen(prefix);
|
n = strlen(prefix);
|
||||||
|
|
||||||
@@ -386,7 +386,7 @@ string_skip_prefix(const char *prefix, char *string)
|
|||||||
char *
|
char *
|
||||||
string_remove_trailing_newlines(char *string)
|
string_remove_trailing_newlines(char *string)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = strlen(string) - 1;
|
n = strlen(string) - 1;
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ parse_follow_command(char *parsed_command, char *template, int node_id)
|
|||||||
end_ptr = parsed_command + MAXPGPATH - 1;
|
end_ptr = parsed_command + MAXPGPATH - 1;
|
||||||
*end_ptr = '\0';
|
*end_ptr = '\0';
|
||||||
|
|
||||||
for(src_ptr = template; *src_ptr; src_ptr++)
|
for (src_ptr = template; *src_ptr; src_ptr++)
|
||||||
{
|
{
|
||||||
if (*src_ptr == '%')
|
if (*src_ptr == '%')
|
||||||
{
|
{
|
||||||
|
|||||||
64
strutil.h
64
strutil.h
@@ -33,14 +33,16 @@
|
|||||||
#define MAXLEN_STR STR(MAXLEN)
|
#define MAXLEN_STR STR(MAXLEN)
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
CHECK_STATUS_OK = 0,
|
CHECK_STATUS_OK = 0,
|
||||||
CHECK_STATUS_WARNING,
|
CHECK_STATUS_WARNING,
|
||||||
CHECK_STATUS_CRITICAL,
|
CHECK_STATUS_CRITICAL,
|
||||||
CHECK_STATUS_UNKNOWN
|
CHECK_STATUS_UNKNOWN
|
||||||
} CheckStatus;
|
} CheckStatus;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
OM_NOT_SET = -1,
|
OM_NOT_SET = -1,
|
||||||
OM_TEXT,
|
OM_TEXT,
|
||||||
OM_CSV,
|
OM_CSV,
|
||||||
@@ -51,7 +53,7 @@ typedef enum {
|
|||||||
typedef struct ItemListCell
|
typedef struct ItemListCell
|
||||||
{
|
{
|
||||||
struct ItemListCell *next;
|
struct ItemListCell *next;
|
||||||
char *string;
|
char *string;
|
||||||
} ItemListCell;
|
} ItemListCell;
|
||||||
|
|
||||||
typedef struct ItemList
|
typedef struct ItemList
|
||||||
@@ -63,9 +65,9 @@ typedef struct ItemList
|
|||||||
typedef struct KeyValueListCell
|
typedef struct KeyValueListCell
|
||||||
{
|
{
|
||||||
struct KeyValueListCell *next;
|
struct KeyValueListCell *next;
|
||||||
char *key;
|
char *key;
|
||||||
char *value;
|
char *value;
|
||||||
OutputMode output_mode;
|
OutputMode output_mode;
|
||||||
} KeyValueListCell;
|
} KeyValueListCell;
|
||||||
|
|
||||||
typedef struct KeyValueList
|
typedef struct KeyValueList
|
||||||
@@ -78,9 +80,9 @@ typedef struct KeyValueList
|
|||||||
typedef struct CheckStatusListCell
|
typedef struct CheckStatusListCell
|
||||||
{
|
{
|
||||||
struct CheckStatusListCell *next;
|
struct CheckStatusListCell *next;
|
||||||
char *item;
|
char *item;
|
||||||
CheckStatus status;
|
CheckStatus status;
|
||||||
char *details;
|
char *details;
|
||||||
} CheckStatusListCell;
|
} CheckStatusListCell;
|
||||||
|
|
||||||
typedef struct CheckStatusList
|
typedef struct CheckStatusList
|
||||||
@@ -100,62 +102,58 @@ maxpath_snprintf(char *str, const char *format,...)
|
|||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
item_list_append(ItemList *item_list, const char *message);
|
item_list_append(ItemList *item_list, const char *message);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
item_list_append_format(ItemList *item_list, const char *format, ...)
|
item_list_append_format(ItemList *item_list, const char *format,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
item_list_free(ItemList *item_list);
|
item_list_free(ItemList *item_list);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
key_value_list_set(KeyValueList *item_list, const char *key, const char *value);
|
key_value_list_set(KeyValueList *item_list, const char *key, const char *value);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value, ...)
|
key_value_list_set_format(KeyValueList *item_list, const char *key, const char *value,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
key_value_list_set_output_mode(KeyValueList *item_list, const char *key, OutputMode mode);
|
key_value_list_set_output_mode(KeyValueList *item_list, const char *key, OutputMode mode);
|
||||||
|
|
||||||
extern const char *
|
extern const char *key_value_list_get(KeyValueList *item_list, const char *key);
|
||||||
key_value_list_get(KeyValueList *item_list, const char *key);
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
key_value_list_free(KeyValueList *item_list);
|
key_value_list_free(KeyValueList *item_list);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
check_status_list_set(CheckStatusList *list, const char *item, CheckStatus status, const char *details);
|
check_status_list_set(CheckStatusList *list, const char *item, CheckStatus status, const char *details);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
check_status_list_set_format(CheckStatusList *list, const char *item, CheckStatus status, const char *details, ...)
|
check_status_list_set_format(CheckStatusList *list, const char *item, CheckStatus status, const char *details,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 4, 5)));
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
check_status_list_free(CheckStatusList *list);
|
check_status_list_free(CheckStatusList *list);
|
||||||
|
|
||||||
extern const char * output_check_status(CheckStatus status);
|
extern const char *output_check_status(CheckStatus status);
|
||||||
|
|
||||||
extern char *
|
extern char *escape_recovery_conf_value(const char *src);
|
||||||
escape_recovery_conf_value(const char *src);
|
|
||||||
|
|
||||||
extern char *
|
extern char *escape_string(PGconn *conn, const char *string);
|
||||||
escape_string(PGconn *conn, const char *string);
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
append_where_clause(PQExpBufferData *where_clause, const char *clause, ...)
|
append_where_clause(PQExpBufferData *where_clause, const char *clause,...)
|
||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
|
||||||
|
|
||||||
extern char *
|
extern char *string_skip_prefix(const char *prefix, char *string);
|
||||||
string_skip_prefix(const char *prefix, char *string);
|
|
||||||
|
|
||||||
extern char
|
extern char
|
||||||
*string_remove_trailing_newlines(char *string);
|
*string_remove_trailing_newlines(char *string);
|
||||||
|
|
||||||
extern char *trim(char *s);
|
extern char *trim(char *s);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
parse_follow_command(char *parsed_command, char *template, int node_id);
|
parse_follow_command(char *parsed_command, char *template, int node_id);
|
||||||
|
|
||||||
#endif /* _STRUTIL_H_ */
|
#endif /* _STRUTIL_H_ */
|
||||||
|
|||||||
5
voting.h
5
voting.h
@@ -18,11 +18,12 @@
|
|||||||
#ifndef _VOTING_H_
|
#ifndef _VOTING_H_
|
||||||
#define _VOTING_H_
|
#define _VOTING_H_
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
VS_UNKNOWN = -1,
|
VS_UNKNOWN = -1,
|
||||||
VS_NO_VOTE,
|
VS_NO_VOTE,
|
||||||
VS_VOTE_REQUEST_RECEIVED,
|
VS_VOTE_REQUEST_RECEIVED,
|
||||||
VS_VOTE_INITIATED
|
VS_VOTE_INITIATED
|
||||||
} NodeVotingStatus;
|
} NodeVotingStatus;
|
||||||
|
|
||||||
#endif /* _VOTING_H_ */
|
#endif /* _VOTING_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user