From 0a1addfdc0e55e128b831199ccfe1710167d692a Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Wed, 12 Jul 2017 09:03:15 +0900 Subject: [PATCH] When registering a BDR node, sync repmgr.nodes from another node If a BDR node is added via bdr_group_join(), repmgr.nodes will start off empty, so we'll need to sync it ourselves before adding it to the repmgr replication set. --- dbutils.c | 27 ++++++++++++++++++++++- dbutils.h | 1 + repmgr-action-bdr.c | 52 +++++++++++++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/dbutils.c b/dbutils.c index c4486820..26c84010 100644 --- a/dbutils.c +++ b/dbutils.c @@ -1436,6 +1436,30 @@ void _populate_node_records(PGresult *res, NodeInfoList *node_list) } +void +get_all_node_records(PGconn *conn, NodeInfoList *node_list) +{ + PQExpBufferData query; + PGresult *res; + + initPQExpBuffer(&query); + + appendPQExpBuffer(&query, + " SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active" + " FROM repmgr.nodes " + "ORDER BY node_id "); + + log_verbose(LOG_DEBUG, "get_all_node_records():\n%s", query.data); + + res = PQexec(conn, query.data); + + termPQExpBuffer(&query); + + _populate_node_records(res, node_list); + + return; +} + void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *node_list) { @@ -2996,7 +3020,8 @@ get_bdr_init_node_record(PGconn *conn, t_bdr_node_info *node_info) if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { - // + PQclear(res); + return RECORD_NOT_FOUND; } else { diff --git a/dbutils.h b/dbutils.h index 757d6722..f8dcdd54 100644 --- a/dbutils.h +++ b/dbutils.h @@ -240,6 +240,7 @@ t_node_info *get_node_record_pointer(PGconn *conn, int node_id); bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info); bool get_primary_node_record(PGconn *conn, t_node_info *node_info); +void get_all_node_records(PGconn *conn, NodeInfoList *node_list); void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes); void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list); void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list); diff --git a/repmgr-action-bdr.c b/repmgr-action-bdr.c index c5836d52..4afb2ab6 100644 --- a/repmgr-action-bdr.c +++ b/repmgr-action-bdr.c @@ -87,26 +87,52 @@ do_bdr_register(void) commit_transaction(conn); } - // any other BDR nodes - if so connect to one where "node_init_from_dsn" is null, - // and copy repmgr.nodes - // (we'll assume all other nodes are up-to-date) - // don't copy other tables... + /* + * before adding the extension tables to the replication set, + * if any other BDR nodes exist, populate repmgr.nodes with a copy + * of existing entries + * + * currently we won't copy the contents of any other tables + * + */ { - PGconn *init_node; - RecordStatus bdr_record_status; - t_bdr_node_info bdr_init_node_info = T_BDR_NODE_INFO_INITIALIZER; + NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER; + get_all_node_records(conn, &local_node_records); - bdr_record_status = get_bdr_init_node_record(conn, &bdr_init_node_info); - - if (bdr_record_status == RECORD_FOUND) + if (local_node_records.node_count == 0) { + /* XXX get all BDR node records */ + RecordStatus bdr_record_status; + t_bdr_node_info bdr_init_node_info = T_BDR_NODE_INFO_INITIALIZER; + + bdr_record_status = get_bdr_init_node_record(conn, &bdr_init_node_info); + + if (bdr_record_status != RECORD_FOUND) + { + /* XXX don't assume the original node will still be part of the cluster */ + log_error(_("unable to retrieve record for originating node")); + PQfinish(conn); + exit(ERR_BAD_CONFIG); + } + if (strncmp(node_info.node_name, bdr_init_node_info.node_name, MAXLEN) != 0) { - init_node = establish_db_connection_quiet(bdr_init_node_info.node_init_from_dsn); - + /* */ + PGconn *init_node_conn; + NodeInfoList existing_nodes = T_NODE_INFO_LIST_INITIALIZER; + NodeInfoListCell *cell; + + init_node_conn = establish_db_connection_quiet(bdr_init_node_info.node_local_dsn); + + /* XXX check repmgr schema exists */ + get_all_node_records(init_node_conn, &existing_nodes); + + for (cell = existing_nodes.head; cell; cell = cell->next) + { + create_node_record(conn, "bdr register", cell->node_info); + } } } - } /* Add the repmgr extension tables to a replication set */