From 3fac975de6cb1f33c8ac0d55a90750ac6e7adc02 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Fri, 24 Jun 2016 09:25:41 +0900 Subject: [PATCH] Prevent multiple nodes being registered with the same name. Fixes GitHub #192. --- dbutils.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- dbutils.h | 1 + repmgr.c | 25 ++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/dbutils.c b/dbutils.c index 7138fc81..29a2f6be 100644 --- a/dbutils.c +++ b/dbutils.c @@ -31,6 +31,7 @@ char repmgr_schema[MAXLEN] = ""; char repmgr_schema_quoted[MAXLEN] = ""; +static int _get_node_record(PGconn *conn, char *cluster, char *sqlquery, t_node_info *node_info); PGconn * _establish_db_connection(const char *conninfo, const bool exit_on_error, const bool log_notice) @@ -1681,8 +1682,7 @@ int get_node_record(PGconn *conn, char *cluster, int node_id, t_node_info *node_info) { char sqlquery[QUERY_STR_LEN]; - PGresult *res; - int ntuples; + int result; sqlquery_snprintf( sqlquery, @@ -1696,6 +1696,49 @@ get_node_record(PGconn *conn, char *cluster, int node_id, t_node_info *node_info log_verbose(LOG_DEBUG, "get_node_record():\n%s\n", sqlquery); + result = _get_node_record(conn, cluster, sqlquery, node_info); + + if (result == 0) + { + log_verbose(LOG_DEBUG, "get_node_record(): no record found for node %i\n", node_id); + } + + return result; +} + +int +get_node_record_by_name(PGconn *conn, char *cluster, const char *node_name, t_node_info *node_info) +{ + char sqlquery[QUERY_STR_LEN]; + int result; + + sqlquery_snprintf( + sqlquery, + "SELECT id, type, upstream_node_id, name, conninfo, slot_name, priority, active" + " FROM %s.repl_nodes " + " WHERE cluster = '%s' " + " AND node_name = %s", + get_repmgr_schema_quoted(conn), + cluster, + node_name); + + result = _get_node_record(conn, cluster, sqlquery, node_info); + + if (result == 0) + { + log_verbose(LOG_DEBUG, "get_node_record(): no record found for node %s\n", node_name); + } + + return result; +} + + +static int +_get_node_record(PGconn *conn, char *cluster, char *sqlquery, t_node_info *node_info) +{ + int ntuples; + PGresult *res; + res = PQexec(conn, sqlquery); if (PQresultStatus(res) != PGRES_TUPLES_OK) { @@ -1706,7 +1749,6 @@ get_node_record(PGconn *conn, char *cluster, int node_id, t_node_info *node_info if (ntuples == 0) { - log_verbose(LOG_DEBUG, "get_node_record(): no record found for node %i\n", node_id); return 0; } @@ -1727,6 +1769,9 @@ get_node_record(PGconn *conn, char *cluster, int node_id, t_node_info *node_info } + + + int get_node_replication_state(PGconn *conn, char *node_name, char *output) { diff --git a/dbutils.h b/dbutils.h index 8d980d8e..85a2b167 100644 --- a/dbutils.h +++ b/dbutils.h @@ -125,6 +125,7 @@ bool witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *c bool create_node_record(PGconn *conn, char *action, int node, char *type, int upstream_node, char *cluster_name, char *node_name, char *conninfo, int priority, char *slot_name, bool active); bool delete_node_record(PGconn *conn, int node, char *action); int get_node_record(PGconn *conn, char *cluster, int node_id, t_node_info *node_info); +int get_node_record_by_name(PGconn *conn, char *cluster, const char *node_name, t_node_info *node_info); bool update_node_record_status(PGconn *conn, char *cluster_name, int this_node_id, char *type, int upstream_node_id, bool active); bool update_node_record_set_upstream(PGconn *conn, char *cluster_name, int this_node_id, int new_upstream_node_id); bool create_event_record(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details); diff --git a/repmgr.c b/repmgr.c index c1ba3187..d99e7d3c 100644 --- a/repmgr.c +++ b/repmgr.c @@ -1127,8 +1127,9 @@ do_standby_register(void) PGconn *master_conn; int ret; - bool record_created; + t_node_info node_record; + int node_result; log_info(_("connecting to standby database\n")); conn = establish_db_connection(options.conninfo, true); @@ -1185,6 +1186,28 @@ do_standby_register(void) } } + /* + * Check that an active node with the same node_name doesn't exist already + */ + + node_result = get_node_record_by_name(master_conn, + options.cluster_name, + options.node_name, + &node_record); + + if (node_result) + { + if (node_record.active == true) + { + log_err(_("Node %i exists already with node_name \"%s\""), + node_record.node_id, + options.node_name); + PQfinish(master_conn); + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + } + record_created = create_node_record(master_conn, "standby register", options.node,