From 472d703d2e8fad878698db25db3ac3b3a2484168 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Tue, 28 Nov 2017 10:51:32 +0900 Subject: [PATCH] repmgr: initialise "voting_term" in "repmgr primary register" This previously happened in the extension SQL code, which could potentially cause replay problems if installing on a BDR cluster. As this table is only required for streaming replication failover, move the initialisation to "repmgr primary register". Addresses GitHub #344 . --- dbutils.c | 36 ++++++++++++++++++++++++++++++++---- dbutils.h | 1 + repmgr--4.0.sql | 3 --- repmgr-action-primary.c | 7 ++++++- repmgr.h | 1 + 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/dbutils.c b/dbutils.c index 2b28a7cf..b576449d 100644 --- a/dbutils.c +++ b/dbutils.c @@ -3735,7 +3735,7 @@ int get_current_term(PGconn *conn) { PGresult *res = NULL; - int term = -1; + int term = VOTING_TERM_NOT_SET; res = PQexec(conn, "SELECT term FROM repmgr.voting_term"); @@ -3747,13 +3747,43 @@ get_current_term(PGconn *conn) return -1; } - term = atoi(PQgetvalue(res, 0, 0)); + if (PQntuples(res) > 0) + { + term = atoi(PQgetvalue(res, 0, 0)); + } PQclear(res); return term; } +void +initialize_voting_term(PGconn *conn) +{ + PGresult *res = NULL; + + int current_term = get_current_term(conn); + + if (current_term == VOTING_TERM_NOT_SET) + { + res = PQexec(conn, "INSERT INTO repmgr.voting_term (term) VALUES (1)"); + } + else + { + res = PQexec(conn, "UPDATE repmgr.voting_term SET term = 1"); + } + + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + log_error(_("unable to initialize repmgr.voting_term:\n %s"), + PQerrorMessage(conn)); + } + + PQclear(res); + return; +} + + void increment_current_term(PGconn *conn) { @@ -3765,8 +3795,6 @@ increment_current_term(PGconn *conn) { log_error(_("unable to increment repmgr.voting_term:\n %s"), PQerrorMessage(conn)); - PQclear(res); - return; } PQclear(res); diff --git a/dbutils.h b/dbutils.h index af7accec..2997957d 100644 --- a/dbutils.h +++ b/dbutils.h @@ -473,6 +473,7 @@ bool delete_monitoring_records(PGconn *primary_conn, int keep_history); /* node voting functions */ +void initialize_voting_term(PGconn *conn); int get_current_term(PGconn *conn); void increment_current_term(PGconn *conn); bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term); diff --git a/repmgr--4.0.sql b/repmgr--4.0.sql index 0e28a5de..f012853f 100644 --- a/repmgr--4.0.sql +++ b/repmgr--4.0.sql @@ -91,9 +91,6 @@ CREATE RULE voting_term_delete AS ON DELETE TO repmgr.voting_term DO INSTEAD NOTHING; -/* XXX do this in "repmgr primary register" */ -INSERT INTO repmgr.voting_term (term) VALUES (1); - /* ================= */ /* repmgrd functions */ diff --git a/repmgr-action-primary.c b/repmgr-action-primary.c index 31b84c06..91b22436 100644 --- a/repmgr-action-primary.c +++ b/repmgr-action-primary.c @@ -74,7 +74,11 @@ do_primary_register(void) log_verbose(LOG_INFO, _("server is not in recovery")); - /* create the repmgr extension if it doesn't already exist */ + /* + * create the repmgr extension if it doesn't already exist; + * note that create_repmgr_extension() will take into account + * the --dry-run option + */ if (!create_repmgr_extension(conn)) { PQfinish(conn); @@ -92,6 +96,7 @@ do_primary_register(void) return; } + initialize_voting_term(conn); /* Ensure there isn't another registered node which is primary */ primary_conn = get_primary_connection(conn, ¤t_primary_id, NULL); diff --git a/repmgr.h b/repmgr.h index 0a2b00c8..4b9987df 100644 --- a/repmgr.h +++ b/repmgr.h @@ -56,6 +56,7 @@ #define NO_UPSTREAM_NODE -1 #define UNKNOWN_NODE_ID -1 +#define VOTING_TERM_NOT_SET -1 /* * various default values - ensure repmgr.conf.sample is update