From fcb7e7a29b617d60f02db6c1f14b7c02b92c5b1f Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 4 Jan 2018 17:12:52 +0900 Subject: [PATCH] "repmgr bdr register": create missing connection replication set if needed Previously the assumption was that the "repmgr" replication set would be set up when the nodes are created, however no checks were implemented and this was not well-documented. Addresses GitHub #347. --- dbutils.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ dbutils.h | 2 ++ repmgr-action-bdr.c | 6 +++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/dbutils.c b/dbutils.c index 821d56e6..b631e031 100644 --- a/dbutils.c +++ b/dbutils.c @@ -4596,3 +4596,71 @@ unset_bdr_failover_handler(PGconn *conn) PQclear(res); return; } + + +bool +bdr_node_has_repmgr_set(PGconn *conn, const char *node_name) +{ + PQExpBufferData query; + PGresult *res = NULL; + bool has_repmgr_set = false; + + initPQExpBuffer(&query); + + appendPQExpBuffer(&query, + " SELECT COUNT(*) " + " FROM UNNEST(bdr.connection_get_replication_sets('%s') AS repset " + " WHERE repset = 'repmgr'", + node_name); + + res = PQexec(conn, query.data); + termPQExpBuffer(&query); + + if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0) + { + has_repmgr_set = false; + } + else + { + has_repmgr_set = atoi(PQgetvalue(res, 0, 0)) == 1 ? true : false; + } + + PQclear(res); + + return has_repmgr_set; +} + + +bool +bdr_node_set_repmgr_set(PGconn *conn, const char *node_name) +{ + PQExpBufferData query; + PGresult *res = NULL; + bool success = true; + + initPQExpBuffer(&query); + + appendPQExpBuffer(&query, + " SELECT bdr.connection_set_replication_sets( " + " ARRAY( " + " SELECT repset::TEXT " + " FROM UNNEST(bdr.connection_get_replication_sets('node1')) AS repset " + " UNION " + " SELECT 'repmgr'::TEXT " + " ), " + " '%s' " + " ) ", + node_name); + + res = PQexec(conn, query.data); + termPQExpBuffer(&query); + + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + success = false; + } + + PQclear(res); + + return success; +} diff --git a/dbutils.h b/dbutils.h index 4cf232c0..214cb0a8 100644 --- a/dbutils.h +++ b/dbutils.h @@ -504,5 +504,7 @@ 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); +bool bdr_node_has_repmgr_set(PGconn *conn, const char *node_name); +bool bdr_node_set_repmgr_set(PGconn *conn, const char *node_name); #endif /* _REPMGR_DBUTILS_H_ */ diff --git a/repmgr-action-bdr.c b/repmgr-action-bdr.c index 7677bd05..3c03d345 100644 --- a/repmgr-action-bdr.c +++ b/repmgr-action-bdr.c @@ -124,7 +124,7 @@ do_bdr_register(void) termPQExpBuffer(&bdr_local_node_name); } - /* check whether repmgr extension exists, and that any other nodes are BDR */ + /* check whether repmgr extension exists, and there are no non-BDR nodes registered */ extension_status = get_repmgr_extension_status(conn); if (extension_status == REPMGR_UNKNOWN) @@ -174,6 +174,10 @@ do_bdr_register(void) pfree(dbname); + if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false) + { + bdr_node_set_repmgr_set(conn, config_file_options.node_name); + } /* * before adding the extension tables to the replication set, if any other