mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-27 08:56:29 +00:00
Merge branch 'pg93'
This commit is contained in:
@@ -2,4 +2,3 @@
|
|||||||
|
|
||||||
/* Only build repmgr for BDR */
|
/* Only build repmgr for BDR */
|
||||||
#undef BDR_ONLY
|
#undef BDR_ONLY
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->tablespace_mapping.head = NULL;
|
options->tablespace_mapping.head = NULL;
|
||||||
options->tablespace_mapping.tail = NULL;
|
options->tablespace_mapping.tail = NULL;
|
||||||
memset(options->recovery_min_apply_delay, 0, sizeof(options->recovery_min_apply_delay));
|
memset(options->recovery_min_apply_delay, 0, sizeof(options->recovery_min_apply_delay));
|
||||||
|
options->recovery_min_apply_delay_provided = false;
|
||||||
options->use_primary_conninfo_password = false;
|
options->use_primary_conninfo_password = false;
|
||||||
|
|
||||||
/*-----------------
|
/*-----------------
|
||||||
@@ -435,7 +436,10 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else if (strcmp(name, "restore_command") == 0)
|
else if (strcmp(name, "restore_command") == 0)
|
||||||
strncpy(options->restore_command, value, MAXLEN);
|
strncpy(options->restore_command, value, MAXLEN);
|
||||||
else if (strcmp(name, "recovery_min_apply_delay") == 0)
|
else if (strcmp(name, "recovery_min_apply_delay") == 0)
|
||||||
|
{
|
||||||
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
||||||
|
options->recovery_min_apply_delay_provided = true;
|
||||||
|
}
|
||||||
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
||||||
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ typedef struct
|
|||||||
char restore_command[MAXLEN];
|
char restore_command[MAXLEN];
|
||||||
TablespaceList tablespace_mapping;
|
TablespaceList tablespace_mapping;
|
||||||
char recovery_min_apply_delay[MAXLEN];
|
char recovery_min_apply_delay[MAXLEN];
|
||||||
|
bool recovery_min_apply_delay_provided;
|
||||||
bool use_primary_conninfo_password;
|
bool use_primary_conninfo_password;
|
||||||
|
|
||||||
/* node check settings */
|
/* node check settings */
|
||||||
@@ -152,7 +153,7 @@ typedef struct
|
|||||||
/* log settings */ \
|
/* log settings */ \
|
||||||
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
||||||
/* standby action settings */ \
|
/* standby action settings */ \
|
||||||
false, "", "", { NULL, NULL }, "", false, \
|
false, "", "", { NULL, NULL }, "", false, false, \
|
||||||
/* node check settings */ \
|
/* node check settings */ \
|
||||||
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
||||||
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
||||||
|
|||||||
2
configure
vendored
2
configure
vendored
@@ -1841,7 +1841,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
version_num_int=$(echo "$version_num"|
|
version_num_int=$(echo "$version_num"|
|
||||||
$SED -e 's/^\([0-9]*\)\.\([0-9]*\)$/\1\2/')
|
$SED -e 's/^\([0-9]*\)\.\([0-9]*\)$/\1\2/')
|
||||||
|
|
||||||
if test "$version_num_int" -lt '94'; then
|
if test "$version_num_int" -lt '93'; then
|
||||||
as_fn_error $? "repmgr is not compatible with detected PostgreSQL version: $version_num" "$LINENO" 5
|
as_fn_error $? "repmgr is not compatible with detected PostgreSQL version: $version_num" "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
version_num_int=$(echo "$version_num"|
|
version_num_int=$(echo "$version_num"|
|
||||||
$SED -e 's/^\([[0-9]]*\)\.\([[0-9]]*\)$/\1\2/')
|
$SED -e 's/^\([[0-9]]*\)\.\([[0-9]]*\)$/\1\2/')
|
||||||
|
|
||||||
if test "$version_num_int" -lt '94'; then
|
if test "$version_num_int" -lt '93'; then
|
||||||
AC_MSG_ERROR([repmgr is not compatible with detected PostgreSQL version: $version_num])
|
AC_MSG_ERROR([repmgr is not compatible with detected PostgreSQL version: $version_num])
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -3619,10 +3619,6 @@ request_vote(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int
|
|||||||
"SELECT repmgr.request_vote(%i, %i)",
|
"SELECT repmgr.request_vote(%i, %i)",
|
||||||
this_node->node_id,
|
this_node->node_id,
|
||||||
electoral_term);
|
electoral_term);
|
||||||
/* "SELECT repmgr.request_vote(%i, '%X/%X'::pg_lsn)",
|
|
||||||
this_node->node_id,
|
|
||||||
(uint32) (last_wal_receive_lsn >> 32),
|
|
||||||
(uint32) last_wal_receive_lsn);*/
|
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ CREATE TABLE repmgr.events (
|
|||||||
details TEXT NULL
|
details TEXT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
CREATE TABLE repmgr.monitoring_history (
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
primary_node_id INTEGER NOT NULL,
|
primary_node_id INTEGER NOT NULL,
|
||||||
standby_node_id INTEGER NOT NULL,
|
standby_node_id INTEGER NOT NULL,
|
||||||
@@ -32,7 +42,26 @@ CREATE TABLE repmgr.monitoring_history (
|
|||||||
last_wal_standby_location PG_LSN,
|
last_wal_standby_location PG_LSN,
|
||||||
replication_lag BIGINT NOT NULL,
|
replication_lag BIGINT NOT NULL,
|
||||||
apply_lag BIGINT NOT NULL
|
apply_lag BIGINT NOT NULL
|
||||||
);
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location TEXT NOT NULL,
|
||||||
|
last_wal_standby_location TEXT,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
END IF;
|
||||||
|
END$repmgr$;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
CREATE INDEX idx_monitoring_history_time
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||||
|
|
||||||
@@ -73,10 +102,33 @@ CREATE FUNCTION standby_get_last_updated()
|
|||||||
|
|
||||||
/* failover functions */
|
/* failover functions */
|
||||||
|
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
CREATE FUNCTION request_vote(INT,INT)
|
CREATE FUNCTION request_vote(INT,INT)
|
||||||
RETURNS pg_lsn
|
RETURNS pg_lsn
|
||||||
AS 'MODULE_PATHNAME', 'request_vote'
|
AS 'MODULE_PATHNAME', 'request_vote'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
$repmgr_func$;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE FUNCTION request_vote(INT,INT)
|
||||||
|
RETURNS TEXT
|
||||||
|
AS 'MODULE_PATHNAME', 'request_vote'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
$repmgr_func$;
|
||||||
|
END IF;
|
||||||
|
END$repmgr$;
|
||||||
|
|
||||||
|
|
||||||
CREATE FUNCTION get_voting_status()
|
CREATE FUNCTION get_voting_status()
|
||||||
RETURNS INT
|
RETURNS INT
|
||||||
|
|||||||
@@ -1598,6 +1598,7 @@ do_node_rejoin(void)
|
|||||||
t_node_info primary_node_record = T_NODE_INFO_INITIALIZER;
|
t_node_info primary_node_record = T_NODE_INFO_INITIALIZER;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
|
||||||
/* check node is not actually running */
|
/* check node is not actually running */
|
||||||
|
|
||||||
@@ -1646,6 +1647,12 @@ do_node_rejoin(void)
|
|||||||
/* check provided upstream connection */
|
/* check provided upstream connection */
|
||||||
upstream_conn = establish_db_connection_by_params(&source_conninfo, true);
|
upstream_conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||||
|
|
||||||
|
/* sanity-checks for 9.3 */
|
||||||
|
server_version_num = get_server_version(upstream_conn, NULL);
|
||||||
|
|
||||||
|
if (server_version_num < 90400)
|
||||||
|
check_93_config();
|
||||||
|
|
||||||
if (get_primary_node_record(upstream_conn, &primary_node_record) == false)
|
if (get_primary_node_record(upstream_conn, &primary_node_record) == false)
|
||||||
{
|
{
|
||||||
log_error(_("unable to retrieve primary node record"));
|
log_error(_("unable to retrieve primary node record"));
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ static bool check_upstream_config(PGconn *conn, int server_version_num, t_node_i
|
|||||||
static void check_primary_standby_version_match(PGconn *conn, PGconn *primary_conn);
|
static void check_primary_standby_version_match(PGconn *conn, PGconn *primary_conn);
|
||||||
static void check_recovery_type(PGconn *conn);
|
static void check_recovery_type(PGconn *conn);
|
||||||
|
|
||||||
|
|
||||||
static void initialise_direct_clone(t_node_info *node_record);
|
static void initialise_direct_clone(t_node_info *node_record);
|
||||||
static int run_basebackup(t_node_info *node_record);
|
static int run_basebackup(t_node_info *node_record);
|
||||||
static int run_file_backup(t_node_info *node_record);
|
static int run_file_backup(t_node_info *node_record);
|
||||||
@@ -96,6 +95,11 @@ static void get_barman_property(char *dst, char *name, char *local_repmgr_direct
|
|||||||
static int get_tablespace_data_barman(char *, TablespaceDataList *);
|
static int get_tablespace_data_barman(char *, TablespaceDataList *);
|
||||||
static char *make_barman_ssh_command(char *buf);
|
static char *make_barman_ssh_command(char *buf);
|
||||||
|
|
||||||
|
static bool create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir);
|
||||||
|
static void write_primary_conninfo(char *line, t_conninfo_param_list *param_list);
|
||||||
|
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
|
||||||
|
|
||||||
|
|
||||||
static NodeStatus parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint);
|
static NodeStatus parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint);
|
||||||
static CheckStatus parse_node_check_archiver(const char *node_check_output, int *files, int *threshold);
|
static CheckStatus parse_node_check_archiver(const char *node_check_output, int *files, int *threshold);
|
||||||
static CheckStatus parse_node_check_replication_lag(const char *node_check_output, int *seconds, int *threshold);
|
static CheckStatus parse_node_check_replication_lag(const char *node_check_output, int *seconds, int *threshold);
|
||||||
@@ -1539,6 +1543,7 @@ do_standby_follow(void)
|
|||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
|
|
||||||
int timer = 0;
|
int timer = 0;
|
||||||
|
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
|
||||||
PQExpBufferData follow_output;
|
PQExpBufferData follow_output;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
@@ -1557,6 +1562,12 @@ do_standby_follow(void)
|
|||||||
/* check this is a standby */
|
/* check this is a standby */
|
||||||
check_recovery_type(local_conn);
|
check_recovery_type(local_conn);
|
||||||
|
|
||||||
|
/* sanity-checks for 9.3 */
|
||||||
|
server_version_num = get_server_version(local_conn, NULL);
|
||||||
|
|
||||||
|
if (server_version_num < 90400)
|
||||||
|
check_93_config();
|
||||||
|
|
||||||
if (runtime_options.upstream_node_id != NO_UPSTREAM_NODE)
|
if (runtime_options.upstream_node_id != NO_UPSTREAM_NODE)
|
||||||
{
|
{
|
||||||
/* check not self! */
|
/* check not self! */
|
||||||
@@ -1677,13 +1688,11 @@ do_standby_follow(void)
|
|||||||
|
|
||||||
initPQExpBuffer(&follow_output);
|
initPQExpBuffer(&follow_output);
|
||||||
|
|
||||||
success = do_standby_follow_internal(
|
success = do_standby_follow_internal(primary_conn,
|
||||||
primary_conn,
|
|
||||||
&primary_node_record,
|
&primary_node_record,
|
||||||
&follow_output);
|
&follow_output);
|
||||||
|
|
||||||
create_event_notification(
|
create_event_notification(primary_conn,
|
||||||
primary_conn,
|
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"standby_follow",
|
"standby_follow",
|
||||||
@@ -1713,6 +1722,9 @@ do_standby_follow(void)
|
|||||||
/*
|
/*
|
||||||
* Perform the actuall "follow" operation; this is executed by
|
* Perform the actuall "follow" operation; this is executed by
|
||||||
* "node rejoin" too.
|
* "node rejoin" too.
|
||||||
|
*
|
||||||
|
* For PostgreSQL 9.3, ensure check_93_config() was called before calling
|
||||||
|
* this function.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
do_standby_follow_internal(PGconn *primary_conn, t_node_info *primary_node_record, PQExpBufferData *output)
|
do_standby_follow_internal(PGconn *primary_conn, t_node_info *primary_node_record, PQExpBufferData *output)
|
||||||
@@ -3098,6 +3110,10 @@ check_source_server()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* disable configuration file options incompatible with 9.3 */
|
||||||
|
if (source_server_version_num < 90400)
|
||||||
|
check_93_config();
|
||||||
|
|
||||||
check_upstream_config(source_conn, source_server_version_num, &node_record, true);
|
check_upstream_config(source_conn, source_server_version_num, &node_record, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3198,6 +3214,8 @@ check_source_server_via_barman()
|
|||||||
* Perform sanity check on upstream server configuration before starting cloning
|
* Perform sanity check on upstream server configuration before starting cloning
|
||||||
* process
|
* process
|
||||||
*
|
*
|
||||||
|
* For PostreSQL 9.3, ensure check_93_config() is called before calling this.
|
||||||
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
* - check user is qualified to perform base backup
|
* - check user is qualified to perform base backup
|
||||||
*/
|
*/
|
||||||
@@ -3248,6 +3266,12 @@ check_upstream_config(PGconn *conn, int server_version_num, t_node_info *node_in
|
|||||||
xlog_stream = false;
|
xlog_stream = false;
|
||||||
|
|
||||||
/* Check that WAL level is set correctly */
|
/* Check that WAL level is set correctly */
|
||||||
|
if (server_version_num < 90400)
|
||||||
|
{
|
||||||
|
i = guc_set(conn, "wal_level", "=", "hot_standby");
|
||||||
|
wal_error_message = _("parameter \"wal_level\" must be set to \"hot_standby\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char *levels_pre96[] = {
|
char *levels_pre96[] = {
|
||||||
"hot_standby",
|
"hot_standby",
|
||||||
@@ -3272,12 +3296,12 @@ check_upstream_config(PGconn *conn, int server_version_num, t_node_info *node_in
|
|||||||
if (server_version_num < 90600)
|
if (server_version_num < 90600)
|
||||||
{
|
{
|
||||||
levels = (char **) levels_pre96;
|
levels = (char **) levels_pre96;
|
||||||
wal_error_message = _("parameter 'wal_level' must be set to 'hot_standby' or 'logical'");
|
wal_error_message = _("parameter \"wal_level\" must be set to \"hot_standby\" or \"logical\"");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
levels = (char **) levels_96plus;
|
levels = (char **) levels_96plus;
|
||||||
wal_error_message = _("parameter 'wal_level' must be set to 'replica' or 'logical'");
|
wal_error_message = _("parameter \"wal_level\" must be set to \"replica\" or \"logical\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -3596,57 +3620,64 @@ initialise_direct_clone(t_node_info *node_record)
|
|||||||
|
|
||||||
if (config_file_options.tablespace_mapping.head != NULL)
|
if (config_file_options.tablespace_mapping.head != NULL)
|
||||||
{
|
{
|
||||||
TablespaceListCell *cell = false;
|
if (server_version_num < 90400)
|
||||||
KeyValueList not_found = {NULL, NULL};
|
|
||||||
int total = 0,
|
|
||||||
matched = 0;
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
for (cell = config_file_options.tablespace_mapping.head; cell; cell = cell->next)
|
|
||||||
{
|
{
|
||||||
char *old_dir_escaped = escape_string(source_conn, cell->old_dir);
|
log_error(_("tablespace mapping not supported in PostgreSQL 9.3, ignoring"));
|
||||||
char name[MAXLEN] = "";
|
|
||||||
|
|
||||||
success = get_tablespace_name_by_location(source_conn, old_dir_escaped, name);
|
|
||||||
pfree(old_dir_escaped);
|
|
||||||
|
|
||||||
if (success == true)
|
|
||||||
{
|
|
||||||
matched++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
key_value_list_set(
|
|
||||||
¬_found,
|
|
||||||
cell->old_dir,
|
|
||||||
"");
|
|
||||||
}
|
|
||||||
|
|
||||||
total++;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (not_found.head != NULL)
|
|
||||||
{
|
{
|
||||||
PQExpBufferData detail;
|
TablespaceListCell *cell = false;
|
||||||
KeyValueListCell *kv_cell;
|
KeyValueList not_found = {NULL, NULL};
|
||||||
|
int total = 0,
|
||||||
|
matched = 0;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
log_error(_("%i of %i mapped tablespaces not found"),
|
|
||||||
total - matched, total);
|
|
||||||
|
|
||||||
initPQExpBuffer(&detail);
|
for (cell = config_file_options.tablespace_mapping.head; cell; cell = cell->next)
|
||||||
|
|
||||||
for (kv_cell = not_found.head; kv_cell; kv_cell = kv_cell->next)
|
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(
|
char *old_dir_escaped = escape_string(source_conn, cell->old_dir);
|
||||||
&detail,
|
char name[MAXLEN] = "";
|
||||||
" %s\n", kv_cell->key);
|
|
||||||
|
success = get_tablespace_name_by_location(source_conn, old_dir_escaped, name);
|
||||||
|
pfree(old_dir_escaped);
|
||||||
|
|
||||||
|
if (success == true)
|
||||||
|
{
|
||||||
|
matched++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key_value_list_set(¬_found,
|
||||||
|
cell->old_dir,
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
total++;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_detail(_("following tablespaces not found:\n%s"),
|
if (not_found.head != NULL)
|
||||||
detail.data);
|
{
|
||||||
termPQExpBuffer(&detail);
|
PQExpBufferData detail;
|
||||||
|
KeyValueListCell *kv_cell;
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
log_error(_("%i of %i mapped tablespaces not found"),
|
||||||
|
total - matched, total);
|
||||||
|
|
||||||
|
initPQExpBuffer(&detail);
|
||||||
|
|
||||||
|
for (kv_cell = not_found.head; kv_cell; kv_cell = kv_cell->next)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(
|
||||||
|
&detail,
|
||||||
|
" %s\n", kv_cell->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_detail(_("following tablespaces not found:\n%s"),
|
||||||
|
detail.data);
|
||||||
|
termPQExpBuffer(&detail);
|
||||||
|
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4751,6 +4782,225 @@ drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a recovery.conf file for a standby
|
||||||
|
*
|
||||||
|
* A database connection pointer is required for escaping primary_conninfo
|
||||||
|
* parameters. When cloning from Barman and --no-upstream-connection ) this
|
||||||
|
* might not be available.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir)
|
||||||
|
{
|
||||||
|
FILE *recovery_file;
|
||||||
|
char recovery_file_path[MAXPGPATH] = "";
|
||||||
|
char line[MAXLEN] = "";
|
||||||
|
mode_t um;
|
||||||
|
|
||||||
|
maxpath_snprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_COMMAND_FILE);
|
||||||
|
|
||||||
|
/* Set umask to 0600 */
|
||||||
|
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
||||||
|
recovery_file = fopen(recovery_file_path, "w");
|
||||||
|
umask(um);
|
||||||
|
|
||||||
|
if (recovery_file == NULL)
|
||||||
|
{
|
||||||
|
log_error(_("unable to create recovery.conf file at \"%s\""),
|
||||||
|
recovery_file_path);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("create_recovery_file(): creating \"%s\"...",
|
||||||
|
recovery_file_path);
|
||||||
|
|
||||||
|
/* standby_mode = 'on' */
|
||||||
|
maxlen_snprintf(line, "standby_mode = 'on'\n");
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* primary_conninfo = '...' */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the user specified --upstream-conninfo string - copy that
|
||||||
|
*/
|
||||||
|
if (strlen(runtime_options.upstream_conninfo))
|
||||||
|
{
|
||||||
|
char *escaped = escape_recovery_conf_value(runtime_options.upstream_conninfo);
|
||||||
|
|
||||||
|
maxlen_snprintf(line, "primary_conninfo = '%s'\n",
|
||||||
|
escaped);
|
||||||
|
free(escaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* otherwise use the conninfo inferred from the upstream connection and/or
|
||||||
|
* node record
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_primary_conninfo(line, recovery_conninfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* recovery_target_timeline = 'latest' */
|
||||||
|
maxlen_snprintf(line, "recovery_target_timeline = 'latest'\n");
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* recovery_min_apply_delay = ... (optional) */
|
||||||
|
if (config_file_options.recovery_min_apply_delay_provided == true)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "recovery_min_apply_delay = %s\n",
|
||||||
|
config_file_options.recovery_min_apply_delay);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* primary_slot_name = '...' (optional, for 9.4 and later) */
|
||||||
|
if (config_file_options.use_replication_slots)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "primary_slot_name = %s\n",
|
||||||
|
node_record->slot_name);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If restore_command is set, we use it as restore_command in
|
||||||
|
* recovery.conf
|
||||||
|
*/
|
||||||
|
if (strcmp(config_file_options.restore_command, "") != 0)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "restore_command = '%s'\n",
|
||||||
|
config_file_options.restore_command);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
fclose(recovery_file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line)
|
||||||
|
{
|
||||||
|
if (fputs(line, recovery_file) == EOF)
|
||||||
|
{
|
||||||
|
log_error(_("unable to write to recovery file at \"%s\""), recovery_file_path);
|
||||||
|
fclose(recovery_file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_primary_conninfo(char *line, t_conninfo_param_list *param_list)
|
||||||
|
{
|
||||||
|
PQExpBufferData conninfo_buf;
|
||||||
|
bool application_name_provided = false;
|
||||||
|
bool password_provided = false;
|
||||||
|
int c;
|
||||||
|
char *escaped = NULL;
|
||||||
|
t_conninfo_param_list env_conninfo;
|
||||||
|
|
||||||
|
initialize_conninfo_params(&env_conninfo, true);
|
||||||
|
|
||||||
|
initPQExpBuffer(&conninfo_buf);
|
||||||
|
|
||||||
|
for (c = 0; c < param_list->size && param_list->keywords[c] != NULL; c++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip empty settings and ones which don't make any sense in
|
||||||
|
* recovery.conf
|
||||||
|
*/
|
||||||
|
if (strcmp(param_list->keywords[c], "dbname") == 0 ||
|
||||||
|
strcmp(param_list->keywords[c], "replication") == 0 ||
|
||||||
|
(param_list->values[c] == NULL) ||
|
||||||
|
(param_list->values[c] != NULL && param_list->values[c][0] == '\0'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* only include "password" if explicitly requested */
|
||||||
|
if (strcmp(param_list->keywords[c], "password") == 0)
|
||||||
|
{
|
||||||
|
password_provided = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conninfo_buf.len != 0)
|
||||||
|
appendPQExpBufferChar(&conninfo_buf, ' ');
|
||||||
|
|
||||||
|
if (strcmp(param_list->keywords[c], "application_name") == 0)
|
||||||
|
application_name_provided = true;
|
||||||
|
|
||||||
|
appendPQExpBuffer(&conninfo_buf, "%s=", param_list->keywords[c]);
|
||||||
|
appendConnStrVal(&conninfo_buf, param_list->values[c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "application_name" not provided - default to repmgr node name */
|
||||||
|
if (application_name_provided == false)
|
||||||
|
{
|
||||||
|
if (strlen(config_file_options.node_name))
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " application_name=");
|
||||||
|
appendConnStrVal(&conninfo_buf, config_file_options.node_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " application_name=repmgr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no password provided explicitly */
|
||||||
|
if (password_provided == false)
|
||||||
|
{
|
||||||
|
if (config_file_options.use_primary_conninfo_password == true)
|
||||||
|
{
|
||||||
|
const char *password = param_get(&env_conninfo, "password");
|
||||||
|
|
||||||
|
if (password != NULL)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " password=");
|
||||||
|
appendConnStrVal(&conninfo_buf, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped = escape_recovery_conf_value(conninfo_buf.data);
|
||||||
|
maxlen_snprintf(line, "primary_conninfo = '%s'\n", escaped);
|
||||||
|
|
||||||
|
free(escaped);
|
||||||
|
free_conninfo_params(&env_conninfo);
|
||||||
|
termPQExpBuffer(&conninfo_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: consolidate code in below functions */
|
/* TODO: consolidate code in below functions */
|
||||||
static NodeStatus
|
static NodeStatus
|
||||||
parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint)
|
parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint)
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ 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 void check_93_config(void);
|
||||||
extern bool create_repmgr_extension(PGconn *conn);
|
extern bool create_repmgr_extension(PGconn *conn);
|
||||||
extern int test_ssh_connection(char *host, char *remote_user);
|
extern int test_ssh_connection(char *host, char *remote_user);
|
||||||
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
||||||
@@ -211,8 +212,6 @@ extern void print_error_list(ItemList *error_list, int log_level);
|
|||||||
|
|
||||||
extern char *make_pg_path(const char *file);
|
extern char *make_pg_path(const char *file);
|
||||||
|
|
||||||
extern bool create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir);
|
|
||||||
|
|
||||||
extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privileged_conn);
|
extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privileged_conn);
|
||||||
|
|
||||||
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
||||||
|
|||||||
241
repmgr-client.c
241
repmgr-client.c
@@ -1998,6 +1998,30 @@ check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_93_config()
|
||||||
|
*
|
||||||
|
* Disable options not compatible with PostgreSQL 9.3
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
check_93_config(void)
|
||||||
|
{
|
||||||
|
if (config_file_options.recovery_min_apply_delay_provided == true)
|
||||||
|
{
|
||||||
|
config_file_options.recovery_min_apply_delay_provided = false;
|
||||||
|
log_warning(_("configuration file option \"recovery_min_apply_delay\" not compatible with PostgreSQL 9.3, ignoring"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_file_options.use_replication_slots == true)
|
||||||
|
{
|
||||||
|
config_file_options.use_replication_slots = false;
|
||||||
|
log_warning(_("configuration file option \"use_replication_slots\" not compatible with PostgreSQL 9.3, ignoring"));
|
||||||
|
log_hint(_("replication slots are available from PostgreSQL 9.4"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
test_ssh_connection(char *host, char *remote_user)
|
test_ssh_connection(char *host, char *remote_user)
|
||||||
{
|
{
|
||||||
@@ -2272,223 +2296,6 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a recovery.conf file for a standby
|
|
||||||
*
|
|
||||||
* A database connection pointer is required for escaping primary_conninfo
|
|
||||||
* parameters. When cloning from Barman and --no-upstream-connection ) this
|
|
||||||
* might not be available.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir)
|
|
||||||
{
|
|
||||||
FILE *recovery_file;
|
|
||||||
char recovery_file_path[MAXPGPATH] = "";
|
|
||||||
char line[MAXLEN] = "";
|
|
||||||
mode_t um;
|
|
||||||
|
|
||||||
maxpath_snprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_COMMAND_FILE);
|
|
||||||
|
|
||||||
/* Set umask to 0600 */
|
|
||||||
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
|
||||||
recovery_file = fopen(recovery_file_path, "w");
|
|
||||||
umask(um);
|
|
||||||
|
|
||||||
if (recovery_file == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to create recovery.conf file at \"%s\""),
|
|
||||||
recovery_file_path);
|
|
||||||
log_detail("%s", strerror(errno));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("create_recovery_file(): creating \"%s\"...",
|
|
||||||
recovery_file_path);
|
|
||||||
|
|
||||||
/* standby_mode = 'on' */
|
|
||||||
maxlen_snprintf(line, "standby_mode = 'on'\n");
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* primary_conninfo = '...' */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* the user specified --upstream-conninfo string - copy that
|
|
||||||
*/
|
|
||||||
if (strlen(runtime_options.upstream_conninfo))
|
|
||||||
{
|
|
||||||
char *escaped = escape_recovery_conf_value(runtime_options.upstream_conninfo);
|
|
||||||
|
|
||||||
maxlen_snprintf(line, "primary_conninfo = '%s'\n",
|
|
||||||
escaped);
|
|
||||||
free(escaped);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* otherwise use the conninfo inferred from the upstream connection and/or
|
|
||||||
* node record
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
write_primary_conninfo(line, recovery_conninfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* recovery_target_timeline = 'latest' */
|
|
||||||
maxlen_snprintf(line, "recovery_target_timeline = 'latest'\n");
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* recovery_min_apply_delay = ... (optional) */
|
|
||||||
if (*config_file_options.recovery_min_apply_delay)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "recovery_min_apply_delay = %s\n",
|
|
||||||
config_file_options.recovery_min_apply_delay);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* primary_slot_name = '...' (optional, for 9.4 and later) */
|
|
||||||
if (config_file_options.use_replication_slots)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "primary_slot_name = %s\n",
|
|
||||||
node_record->slot_name);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If restore_command is set, we use it as restore_command in
|
|
||||||
* recovery.conf
|
|
||||||
*/
|
|
||||||
if (strcmp(config_file_options.restore_command, "") != 0)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "restore_command = '%s'\n",
|
|
||||||
config_file_options.restore_command);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
fclose(recovery_file);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line)
|
|
||||||
{
|
|
||||||
if (fputs(line, recovery_file) == EOF)
|
|
||||||
{
|
|
||||||
log_error(_("unable to write to recovery file at \"%s\""), recovery_file_path);
|
|
||||||
fclose(recovery_file);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_primary_conninfo(char *line, t_conninfo_param_list *param_list)
|
|
||||||
{
|
|
||||||
PQExpBufferData conninfo_buf;
|
|
||||||
bool application_name_provided = false;
|
|
||||||
bool password_provided = false;
|
|
||||||
int c;
|
|
||||||
char *escaped = NULL;
|
|
||||||
t_conninfo_param_list env_conninfo;
|
|
||||||
|
|
||||||
initialize_conninfo_params(&env_conninfo, true);
|
|
||||||
|
|
||||||
initPQExpBuffer(&conninfo_buf);
|
|
||||||
|
|
||||||
for (c = 0; c < param_list->size && param_list->keywords[c] != NULL; c++)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Skip empty settings and ones which don't make any sense in
|
|
||||||
* recovery.conf
|
|
||||||
*/
|
|
||||||
if (strcmp(param_list->keywords[c], "dbname") == 0 ||
|
|
||||||
strcmp(param_list->keywords[c], "replication") == 0 ||
|
|
||||||
(param_list->values[c] == NULL) ||
|
|
||||||
(param_list->values[c] != NULL && param_list->values[c][0] == '\0'))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* only include "password" if explicitly requested */
|
|
||||||
if (strcmp(param_list->keywords[c], "password") == 0)
|
|
||||||
{
|
|
||||||
password_provided = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conninfo_buf.len != 0)
|
|
||||||
appendPQExpBufferChar(&conninfo_buf, ' ');
|
|
||||||
|
|
||||||
if (strcmp(param_list->keywords[c], "application_name") == 0)
|
|
||||||
application_name_provided = true;
|
|
||||||
|
|
||||||
appendPQExpBuffer(&conninfo_buf, "%s=", param_list->keywords[c]);
|
|
||||||
appendConnStrVal(&conninfo_buf, param_list->values[c]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* "application_name" not provided - default to repmgr node name */
|
|
||||||
if (application_name_provided == false)
|
|
||||||
{
|
|
||||||
if (strlen(config_file_options.node_name))
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " application_name=");
|
|
||||||
appendConnStrVal(&conninfo_buf, config_file_options.node_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " application_name=repmgr");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no password provided explicitly */
|
|
||||||
if (password_provided == false)
|
|
||||||
{
|
|
||||||
if (config_file_options.use_primary_conninfo_password == true)
|
|
||||||
{
|
|
||||||
const char *password = param_get(&env_conninfo, "password");
|
|
||||||
|
|
||||||
if (password != NULL)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " password=");
|
|
||||||
appendConnStrVal(&conninfo_buf, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
escaped = escape_recovery_conf_value(conninfo_buf.data);
|
|
||||||
maxlen_snprintf(line, "primary_conninfo = '%s'\n", escaped);
|
|
||||||
|
|
||||||
free(escaped);
|
|
||||||
free_conninfo_params(&env_conninfo);
|
|
||||||
termPQExpBuffer(&conninfo_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -204,7 +204,4 @@ static const char *action_name(const int action);
|
|||||||
|
|
||||||
static void check_cli_parameters(const int action);
|
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_ */
|
||||||
|
|||||||
36
repmgr.c
36
repmgr.c
@@ -20,6 +20,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
@@ -31,7 +32,11 @@
|
|||||||
#include "storage/shmem.h"
|
#include "storage/shmem.h"
|
||||||
#include "storage/spin.h"
|
#include "storage/spin.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
|
#if (PG_VERSION_NUM >= 90400)
|
||||||
#include "utils/pg_lsn.h"
|
#include "utils/pg_lsn.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
|
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
@@ -280,14 +285,24 @@ request_vote(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
#ifndef BDR_ONLY
|
#ifndef BDR_ONLY
|
||||||
StringInfoData query;
|
StringInfoData query;
|
||||||
|
|
||||||
|
#if (PG_VERSION_NUM >= 90400)
|
||||||
XLogRecPtr our_lsn = InvalidXLogRecPtr;
|
XLogRecPtr our_lsn = InvalidXLogRecPtr;
|
||||||
|
bool isnull;
|
||||||
|
#else
|
||||||
|
char *value = NULL;
|
||||||
|
char lsn_text[64] = "";
|
||||||
|
#endif
|
||||||
|
|
||||||
/* node_id used for logging purposes */
|
/* node_id used for logging purposes */
|
||||||
int requesting_node_id = PG_GETARG_INT32(0);
|
int requesting_node_id = PG_GETARG_INT32(0);
|
||||||
int current_electoral_term = PG_GETARG_INT32(1);
|
int current_electoral_term = PG_GETARG_INT32(1);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
bool isnull;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -326,17 +341,30 @@ request_vote(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
elog(WARNING, "unable to retrieve last received LSN");
|
elog(WARNING, "unable to retrieve last received LSN");
|
||||||
|
|
||||||
|
#if (PG_VERSION_NUM >= 90400)
|
||||||
PG_RETURN_LSN(InvalidOid);
|
PG_RETURN_LSN(InvalidOid);
|
||||||
|
#else
|
||||||
|
PG_RETURN_TEXT_P(cstring_to_text("0/0"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (PG_VERSION_NUM >= 90400)
|
||||||
our_lsn = DatumGetLSN(SPI_getbinval(SPI_tuptable->vals[0],
|
our_lsn = DatumGetLSN(SPI_getbinval(SPI_tuptable->vals[0],
|
||||||
SPI_tuptable->tupdesc,
|
SPI_tuptable->tupdesc,
|
||||||
1, &isnull));
|
1, &isnull));
|
||||||
|
|
||||||
|
|
||||||
elog(DEBUG1, "our LSN is %X/%X",
|
elog(DEBUG1, "our LSN is %X/%X",
|
||||||
(uint32) (our_lsn >> 32),
|
(uint32) (our_lsn >> 32),
|
||||||
(uint32) our_lsn);
|
(uint32) our_lsn);
|
||||||
|
#else
|
||||||
|
value = SPI_getvalue(SPI_tuptable->vals[0],
|
||||||
|
SPI_tuptable->tupdesc,
|
||||||
|
1);
|
||||||
|
strncpy(lsn_text, value, 64);
|
||||||
|
pfree(value);
|
||||||
|
elog(DEBUG1, "our LSN is %s", lsn_text);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* indicate this node has responded to a vote request */
|
/* indicate this node has responded to a vote request */
|
||||||
shared_state->voting_status = VS_VOTE_REQUEST_RECEIVED;
|
shared_state->voting_status = VS_VOTE_REQUEST_RECEIVED;
|
||||||
@@ -347,7 +375,11 @@ request_vote(PG_FUNCTION_ARGS)
|
|||||||
/* should we free "query" here? */
|
/* should we free "query" here? */
|
||||||
SPI_finish();
|
SPI_finish();
|
||||||
|
|
||||||
|
#if (PG_VERSION_NUM >= 90400)
|
||||||
PG_RETURN_LSN(our_lsn);
|
PG_RETURN_LSN(our_lsn);
|
||||||
|
#else
|
||||||
|
PG_RETURN_TEXT_P(cstring_to_text(lsn_text));
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
PG_RETURN(InvalidOid);
|
PG_RETURN(InvalidOid);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
6
repmgr.h
6
repmgr.h
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
#include <postgres_fe.h>
|
#include <postgres_fe.h>
|
||||||
@@ -39,8 +41,8 @@
|
|||||||
#include "dbutils.h"
|
#include "dbutils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#define MIN_SUPPORTED_VERSION "9.4"
|
#define MIN_SUPPORTED_VERSION "9.3"
|
||||||
#define MIN_SUPPORTED_VERSION_NUM 90400
|
#define MIN_SUPPORTED_VERSION_NUM 90300
|
||||||
|
|
||||||
#define REPLICATION_TYPE_PHYSICAL 1
|
#define REPLICATION_TYPE_PHYSICAL 1
|
||||||
#define REPLICATION_TYPE_BDR 2
|
#define REPLICATION_TYPE_BDR 2
|
||||||
|
|||||||
Reference in New Issue
Block a user