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