poke it around until it works less badly

This commit is contained in:
Ian Barwick
2017-06-29 09:35:09 +09:00
parent fa86fe4ad8
commit 3514e20367
7 changed files with 81 additions and 7 deletions

View File

@@ -16,6 +16,10 @@ static bool config_file_provided = false;
bool config_file_found = false; bool config_file_found = false;
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list); static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
static bool parse_bool(const char *s,
const char *config_item,
ItemList *error_list);
static void _parse_line(char *buf, char *name, char *value); static void _parse_line(char *buf, char *name, char *value);
static void parse_event_notifications_list(t_configuration_options *options, const char *arg); static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
static void tablespace_list_append(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 * 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) parse_bool(const char *s, const char *config_item, ItemList *error_list)
{ {
PQExpBufferData errors; PQExpBufferData errors;

View File

@@ -158,9 +158,6 @@ int repmgr_atoi(const char *s,
ItemList *error_list, ItemList *error_list,
int minval); 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, bool parse_pg_basebackup_options(const char *pg_basebackup_options,
t_basebackup_options *backup_options, t_basebackup_options *backup_options,

View File

@@ -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 */ /* replication status functions */
/* ============================ */ /* ============================ */

View File

@@ -248,7 +248,7 @@ bool is_server_available(const char *conninfo);
NodeVotingStatus get_voting_status(PGconn *conn); 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); 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); 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 */ /* replication status functions */

View File

@@ -51,3 +51,8 @@ CREATE FUNCTION set_voting_status_initiated()
RETURNS VOID RETURNS VOID
AS '$libdir/repmgr', 'set_voting_status_initiated' AS '$libdir/repmgr', 'set_voting_status_initiated'
LANGUAGE C STRICT; LANGUAGE C STRICT;
CREATE FUNCTION other_node_is_candidate(INT)
RETURNS BOOL
AS '$libdir/repmgr', 'other_node_is_candidate'
LANGUAGE C STRICT;

View File

@@ -30,6 +30,8 @@
#include "voting.h" #include "voting.h"
#define UNKNOWN_NODE_ID -1
#define MAXFNAMELEN 64 #define MAXFNAMELEN 64
#define TRANCHE_NAME "repmgrd" #define TRANCHE_NAME "repmgrd"
@@ -46,6 +48,7 @@ typedef struct repmgrdSharedState
LWLockId lock; /* protects search/modification */ LWLockId lock; /* protects search/modification */
NodeState node_state; NodeState node_state;
NodeVotingStatus voting_status; NodeVotingStatus voting_status;
int candidate_node_id;
} repmgrdSharedState; } repmgrdSharedState;
static repmgrdSharedState *shared_state = NULL; static repmgrdSharedState *shared_state = NULL;
@@ -67,6 +70,8 @@ PG_FUNCTION_INFO_V1(get_voting_status);
Datum set_voting_status_initiated(PG_FUNCTION_ARGS); Datum set_voting_status_initiated(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(set_voting_status_initiated); PG_FUNCTION_INFO_V1(set_voting_status_initiated);
Datum other_node_is_candidate(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(other_node_is_candidate);
/* /*
* Module load callback * Module load callback
*/ */
@@ -130,7 +135,7 @@ repmgr_shmem_startup(void)
if (!found) if (!found)
{ {
/* First time through ... */ /* Initialise shared memory struct */
#if (PG_VERSION_NUM >= 90600) #if (PG_VERSION_NUM >= 90600)
shared_state->lock = &(GetNamedLWLockTranche(TRANCHE_NAME))->lock; shared_state->lock = &(GetNamedLWLockTranche(TRANCHE_NAME))->lock;
#else #else
@@ -138,6 +143,7 @@ repmgr_shmem_startup(void)
#endif #endif
shared_state->voting_status = VS_NO_VOTE; shared_state->voting_status = VS_NO_VOTE;
shared_state->candidate_node_id = UNKNOWN_NODE_ID;
} }
LWLockRelease(AddinShmemInitLock); LWLockRelease(AddinShmemInitLock);
@@ -225,3 +231,25 @@ set_voting_status_initiated(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); 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);
}

View File

@@ -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 static NodeVotingStatus
do_election(void) do_election(void)
{ {
@@ -598,6 +599,8 @@ do_election(void)
long unsigned rand_wait = (long) ((rand() % 50) + 10) * 10000; long unsigned rand_wait = (long) ((rand() % 50) + 10) * 10000;
bool other_node_is_candidate = false;
log_debug("do_election(): sleeping %li", rand_wait); log_debug("do_election(): sleeping %li", rand_wait);
pg_usleep(rand_wait); pg_usleep(rand_wait);
@@ -646,10 +649,21 @@ do_election(void)
continue; 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; cell->node_info->is_visible = true;
visible_nodes ++; visible_nodes ++;
} }
if (other_node_is_candidate == true)
{
return VS_NO_VOTE;
}
// XXX check if > 50% visible // XXX check if > 50% visible
/* check again if we've been asked to vote */ /* check again if we've been asked to vote */