From 3514e20367925081162c7114a208f72149cf4ecd Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 29 Jun 2017 09:35:09 +0900 Subject: [PATCH] poke it around until it works less badly --- config.c | 6 +++++- config.h | 3 --- dbutils.c | 26 ++++++++++++++++++++++++++ dbutils.h | 2 +- repmgr--4.0.sql | 5 +++++ repmgr.c | 30 +++++++++++++++++++++++++++++- repmgrd.c | 16 +++++++++++++++- 7 files changed, 81 insertions(+), 7 deletions(-) diff --git a/config.c b/config.c index 7865eba6..5c9c6c2c 100644 --- a/config.c +++ b/config.c @@ -16,6 +16,10 @@ static bool config_file_provided = 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_line(char *buf, char *name, char *value); static void parse_event_notifications_list(t_configuration_options *options, const char *arg); static void tablespace_list_append(t_configuration_options *options, const char *arg); @@ -774,7 +778,7 @@ repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, in * * https://www.postgresql.org/docs/current/static/config-setting.html */ -bool +static bool parse_bool(const char *s, const char *config_item, ItemList *error_list) { PQExpBufferData errors; diff --git a/config.h b/config.h index 9bad4977..3d8cc36f 100644 --- a/config.h +++ b/config.h @@ -158,9 +158,6 @@ int repmgr_atoi(const char *s, ItemList *error_list, int minval); -bool parse_bool(const char *s, - const char *config_item, - ItemList *error_list); bool parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, diff --git a/dbutils.c b/dbutils.c index ee20e126..91698ba6 100644 --- a/dbutils.c +++ b/dbutils.c @@ -2364,6 +2364,32 @@ set_voting_status_initiated(PGconn *conn) } +bool +announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node) +{ + PQExpBufferData query; + PGresult *res; + + bool retval; + + initPQExpBuffer(&query); + + appendPQExpBuffer(&query, + "SELECT repmgr.other_node_is_candidate(%i)", + this_node->node_id); + + res = PQexec(conn, query.data); + termPQExpBuffer(&query); + + retval = (strcmp(PQgetvalue(res, 0, 0), "t") == 0) + ? true + : false; + + PQclear(res); + + return retval; +} + /* ============================ */ /* replication status functions */ /* ============================ */ diff --git a/dbutils.h b/dbutils.h index 745d4012..33c3fa19 100644 --- a/dbutils.h +++ b/dbutils.h @@ -248,7 +248,7 @@ bool is_server_available(const char *conninfo); NodeVotingStatus get_voting_status(PGconn *conn); int request_vote(PGconn *conn, t_node_info *this_node, t_node_info *other_node, XLogRecPtr last_wal_receive_lsn); void set_voting_status_initiated(PGconn *conn); - +bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node); /* replication status functions */ diff --git a/repmgr--4.0.sql b/repmgr--4.0.sql index 3f2b2447..9142a209 100644 --- a/repmgr--4.0.sql +++ b/repmgr--4.0.sql @@ -51,3 +51,8 @@ CREATE FUNCTION set_voting_status_initiated() RETURNS VOID AS '$libdir/repmgr', 'set_voting_status_initiated' LANGUAGE C STRICT; + +CREATE FUNCTION other_node_is_candidate(INT) + RETURNS BOOL + AS '$libdir/repmgr', 'other_node_is_candidate' + LANGUAGE C STRICT; diff --git a/repmgr.c b/repmgr.c index e5ed0c1e..c21ca7f0 100644 --- a/repmgr.c +++ b/repmgr.c @@ -30,6 +30,8 @@ #include "voting.h" +#define UNKNOWN_NODE_ID -1 + #define MAXFNAMELEN 64 #define TRANCHE_NAME "repmgrd" @@ -46,6 +48,7 @@ typedef struct repmgrdSharedState LWLockId lock; /* protects search/modification */ NodeState node_state; NodeVotingStatus voting_status; + int candidate_node_id; } repmgrdSharedState; static repmgrdSharedState *shared_state = NULL; @@ -67,6 +70,8 @@ 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); /* * Module load callback */ @@ -130,7 +135,7 @@ repmgr_shmem_startup(void) if (!found) { - /* First time through ... */ + /* Initialise shared memory struct */ #if (PG_VERSION_NUM >= 90600) shared_state->lock = &(GetNamedLWLockTranche(TRANCHE_NAME))->lock; #else @@ -138,6 +143,7 @@ repmgr_shmem_startup(void) #endif shared_state->voting_status = VS_NO_VOTE; + shared_state->candidate_node_id = UNKNOWN_NODE_ID; } LWLockRelease(AddinShmemInitLock); @@ -225,3 +231,25 @@ set_voting_status_initiated(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } + +Datum +other_node_is_candidate(PG_FUNCTION_ARGS) +{ + int requesting_node_id = PG_GETARG_INT32(0); + + LWLockAcquire(shared_state->lock, LW_SHARED); + + if (shared_state->candidate_node_id != UNKNOWN_NODE_ID) + { + elog(INFO, "node %i requesting candidature, but node %i already candidate", + requesting_node_id, + shared_state->candidate_node_id); + PG_RETURN_BOOL(false); + } + + shared_state->candidate_node_id = requesting_node_id; + LWLockRelease(shared_state->lock); + + elog(INFO, "node %i is candidate", requesting_node_id); + PG_RETURN_BOOL(true); +} diff --git a/repmgrd.c b/repmgrd.c index 05a83bff..8746ead0 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -576,7 +576,8 @@ monitor_streaming_standby(void) } } - +// store lsndiffs, in the event we're not the best node, +// i.e. don't get all the votes, we pass the baton to the best node static NodeVotingStatus do_election(void) { @@ -598,6 +599,8 @@ do_election(void) long unsigned rand_wait = (long) ((rand() % 50) + 10) * 10000; + bool other_node_is_candidate = false; + log_debug("do_election(): sleeping %li", rand_wait); pg_usleep(rand_wait); @@ -646,10 +649,21 @@ do_election(void) continue; } + if (announce_candidature(cell->node_info->conn, &local_node_info, cell->node_info) == false) + { + log_debug("node %i is candidate", cell->node_info->node_id); + other_node_is_candidate = true; + } + cell->node_info->is_visible = true; visible_nodes ++; } + if (other_node_is_candidate == true) + { + return VS_NO_VOTE; + } + // XXX check if > 50% visible /* check again if we've been asked to vote */