mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Remove BDR 2.x support
The BDR 2.x support was conceptual only and was never used in production. As BDR 2.x will be EOL'd shortly, there is no risk it will be needed.
This commit is contained in:
829
dbutils.c
829
dbutils.c
@@ -33,13 +33,6 @@
|
||||
#define NODE_RECORD_PARAM_COUNT 11
|
||||
|
||||
|
||||
/*
|
||||
* This is set by is_bdr_db(), which is called by every BDR-related
|
||||
* action anyway; this is required to be able to generate appropriate
|
||||
* queries for versions 2 and 3.
|
||||
*/
|
||||
int bdr_version_num = UNKNOWN_BDR_VERSION_NUM;
|
||||
|
||||
static void log_db_error(PGconn *conn, const char *query_text, const char *fmt,...)
|
||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
||||
|
||||
@@ -66,10 +59,6 @@ static ReplSlotStatus _verify_replication_slot(PGconn *conn, char *slot_name, PQ
|
||||
|
||||
static bool _create_event(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info, bool send_notification);
|
||||
|
||||
static bool _is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet);
|
||||
static void _populate_bdr_node_record(PGresult *res, t_bdr_node_info *node_info, int row);
|
||||
static void _populate_bdr_node_records(PGresult *res, BdrNodeInfoList *node_list);
|
||||
|
||||
/*
|
||||
* This provides a standardized way of logging database errors. Note
|
||||
* that the provided PGconn can be a normal or a replication connection;
|
||||
@@ -119,36 +108,6 @@ parse_lsn(const char *str)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wrap query with appropriate DDL function, if required.
|
||||
*/
|
||||
void
|
||||
wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt,...)
|
||||
{
|
||||
va_list arglist;
|
||||
char buf[MAXLEN];
|
||||
|
||||
if (replication_type == REPLICATION_TYPE_BDR)
|
||||
{
|
||||
if (bdr_version_num < 3)
|
||||
appendPQExpBufferStr(query_buf, "SELECT bdr.bdr_replicate_ddl_command($repmgr$");
|
||||
else
|
||||
appendPQExpBufferStr(query_buf, "SELECT bdr.replicate_ddl_command($repmgr$");
|
||||
}
|
||||
|
||||
va_start(arglist, fmt);
|
||||
vsnprintf(buf, MAXLEN, fmt, arglist);
|
||||
va_end(arglist);
|
||||
|
||||
appendPQExpBufferStr(query_buf, buf);
|
||||
|
||||
if (replication_type == REPLICATION_TYPE_BDR)
|
||||
{
|
||||
appendPQExpBufferStr(query_buf, "$repmgr$)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ==================== */
|
||||
/* Connection functions */
|
||||
/* ==================== */
|
||||
@@ -2517,10 +2476,6 @@ parse_node_type(const char *type)
|
||||
{
|
||||
return WITNESS;
|
||||
}
|
||||
else if (strcmp(type, "bdr") == 0)
|
||||
{
|
||||
return BDR;
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
@@ -2537,8 +2492,6 @@ get_node_type_string(t_server_type type)
|
||||
return "standby";
|
||||
case WITNESS:
|
||||
return "witness";
|
||||
case BDR:
|
||||
return "bdr";
|
||||
/* this should never happen */
|
||||
case UNKNOWN:
|
||||
default:
|
||||
@@ -5777,788 +5730,6 @@ is_wal_replay_paused(PGconn *conn, bool check_pending_wal)
|
||||
}
|
||||
|
||||
|
||||
/* ============= */
|
||||
/* BDR functions */
|
||||
/* ============= */
|
||||
|
||||
|
||||
static bool
|
||||
_is_bdr_db(PGconn *conn, PQExpBufferData *output, bool quiet)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool is_bdr_db = false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT (pg_catalog.regexp_matches(extversion, '^\\d+'))[1] AS major_version "
|
||||
" FROM pg_catalog.pg_extension "
|
||||
" WHERE extname = 'bdr' ");
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
is_bdr_db = false;
|
||||
bdr_version_num = UNKNOWN_BDR_VERSION_NUM;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_bdr_db = true;
|
||||
bdr_version_num = atoi(PQgetvalue(res, 0, 0));
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
log_verbose(LOG_DEBUG, "BDR ext version number is %i", bdr_version_num);
|
||||
|
||||
if (is_bdr_db == false)
|
||||
{
|
||||
const char *warning = _("BDR extension is not available for this database");
|
||||
|
||||
if (output != NULL)
|
||||
appendPQExpBufferStr(output, warning);
|
||||
else if (quiet == false)
|
||||
log_warning("%s", warning);
|
||||
|
||||
return is_bdr_db;
|
||||
}
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
"SELECT bdr.bdr_is_active_in_db()");
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
is_bdr_db = atobool(PQgetvalue(res, 0, 0));
|
||||
|
||||
if (is_bdr_db == false)
|
||||
{
|
||||
const char *warning = _("BDR extension available for this database, but the database is not configured for BDR");
|
||||
|
||||
if (output != NULL)
|
||||
appendPQExpBufferStr(output, warning);
|
||||
else if (quiet == false)
|
||||
log_warning("%s", warning);
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
|
||||
return is_bdr_db;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
is_bdr_db(PGconn *conn, PQExpBufferData *output)
|
||||
{
|
||||
return _is_bdr_db(conn, output, false);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
is_bdr_db_quiet(PGconn *conn)
|
||||
{
|
||||
return _is_bdr_db(conn, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
get_bdr_version_num(void)
|
||||
{
|
||||
return bdr_version_num;
|
||||
}
|
||||
|
||||
bool
|
||||
is_active_bdr_node(PGconn *conn, const char *node_name)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool is_active_bdr_node = false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT COALESCE(s.active, TRUE) AS active"
|
||||
" FROM bdr.bdr_nodes n "
|
||||
" LEFT JOIN pg_catalog.pg_replication_slots s "
|
||||
" ON s.slot_name=bdr.bdr_format_slot_name(n.node_sysid, n.node_timeline, n.node_dboid, (SELECT oid FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database())) "
|
||||
" WHERE n.node_name='%s' ",
|
||||
node_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT COALESCE(s.active, FALSE) AS active"
|
||||
" FROM bdr.node bn "
|
||||
" INNER JOIN pglogical.node pn "
|
||||
" ON (pn.node_id = bn.pglogical_node_id) "
|
||||
" LEFT JOIN pg_catalog.pg_replication_slots s "
|
||||
" ON s.slot_name=bn.local_slot_name "
|
||||
" WHERE pn.node_name='%s' ",
|
||||
node_name);
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "is_active_bdr_node():\n %s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
/* we don't care if the query fails */
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
is_active_bdr_node = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_active_bdr_node = atobool(PQgetvalue(res, 0, 0));
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return is_active_bdr_node;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
is_bdr_repmgr(PGconn *conn)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
int non_bdr_nodes = 0;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
"SELECT pg_catalog.count(*)"
|
||||
" FROM repmgr.nodes n"
|
||||
" WHERE n.type != 'bdr' ");
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
|
||||
non_bdr_nodes = atoi(PQgetvalue(res, 0, 0));
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return (non_bdr_nodes == 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get name of default BDR replication set.
|
||||
*
|
||||
* Caller must free provided value.
|
||||
*/
|
||||
char *
|
||||
get_default_bdr_replication_set(PGconn *conn)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
char *default_replication_set = NULL;
|
||||
int namelen;
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
/* For BDR2, we use a custom replication set */
|
||||
namelen = strlen(BDR2_REPLICATION_SET_NAME);
|
||||
default_replication_set = pg_malloc0(namelen + 1);
|
||||
snprintf(default_replication_set,
|
||||
namelen + 1,
|
||||
"%s", BDR2_REPLICATION_SET_NAME);
|
||||
|
||||
return default_replication_set;
|
||||
}
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT rs.set_name "
|
||||
" FROM pglogical.replication_set rs "
|
||||
" INNER JOIN bdr.node_group ng "
|
||||
" ON ng.node_group_default_repset = rs.set_id ");
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
log_warning(_("unable to retrieve default BDR replication set name"));
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
log_detail("%s", PQerrorMessage(conn));
|
||||
|
||||
PQclear(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namelen = strlen(PQgetvalue(res, 0, 0));
|
||||
default_replication_set = pg_malloc0(namelen + 1);
|
||||
|
||||
snprintf(default_replication_set,
|
||||
namelen,
|
||||
"%s", PQgetvalue(res, 0, 0));
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return default_replication_set;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool in_replication_set = false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
"SELECT pg_catalog.count(*) "
|
||||
" FROM pg_catalog.unnest(bdr.table_get_replication_sets('repmgr.%s')) AS repset "
|
||||
" WHERE repset='%s' ",
|
||||
tablename,
|
||||
set);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT pg_catalog.count(*) "
|
||||
" FROM pglogical.replication_set s "
|
||||
" INNER JOIN pglogical.replication_set_table st "
|
||||
" ON s.set_id = st.set_id "
|
||||
" WHERE s.set_name = '%s' "
|
||||
" AND st.set_reloid = 'repmgr.%s'::REGCLASS ",
|
||||
set,
|
||||
tablename);
|
||||
|
||||
}
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
in_replication_set = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_replication_set = atoi(PQgetvalue(res, 0, 0)) == 1 ? true : false;
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return in_replication_set;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool success = true;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
"SELECT bdr.table_set_replication_sets('repmgr.%s', '{%s}')",
|
||||
tablename,
|
||||
set);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT bdr.replication_set_add_table( "
|
||||
" relation := 'repmgr.%s', "
|
||||
" set_name := '%s' "
|
||||
" ) ",
|
||||
tablename,
|
||||
set);
|
||||
}
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_error(_("unable to add table \"repmgr.%s\" to replication set \"%s\""),
|
||||
tablename,
|
||||
set);
|
||||
log_detail("%s", PQerrorMessage(conn));
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
bdr_node_name_matches(PGconn *conn, const char *node_name, PQExpBufferData *bdr_local_node_name)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool node_exists = false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBufferStr(&query,
|
||||
"SELECT bdr.bdr_get_local_node_name() AS node_name");
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBufferStr(&query,
|
||||
"SELECT node_name FROM bdr.local_node_info()");
|
||||
}
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
node_exists = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
node_exists = true;
|
||||
appendPQExpBuffer(bdr_local_node_name,
|
||||
"%s", PQgetvalue(res, 0, 0));
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return node_exists;
|
||||
}
|
||||
|
||||
|
||||
ReplSlotStatus
|
||||
get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
ReplSlotStatus status = SLOT_UNKNOWN;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT s.active "
|
||||
" FROM pg_catalog.pg_replication_slots s "
|
||||
" WHERE slot_name = "
|
||||
" (SELECT bdr.bdr_format_slot_name(node_sysid, node_timeline, node_dboid, datoid) "
|
||||
" FROM bdr.bdr_nodes "
|
||||
" WHERE node_name = '%s') ",
|
||||
node_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT COALESCE(s.active, FALSE) AS active"
|
||||
" FROM bdr.node bn "
|
||||
" INNER JOIN pglogical.node pn "
|
||||
" ON (pn.node_id = bn.pglogical_node_id) "
|
||||
" INNER JOIN pg_catalog.pg_replication_slots s "
|
||||
" ON s.slot_name=bn.local_slot_name "
|
||||
" WHERE pn.node_name='%s' ",
|
||||
node_name);
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "get_bdr_node_replication_slot_status():\n %s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0)
|
||||
{
|
||||
status = SLOT_UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = (atobool(PQgetvalue(res, 0, 0)) == true)
|
||||
? SLOT_ACTIVE
|
||||
: SLOT_INACTIVE;
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
get_bdr_other_node_name(PGconn *conn, int node_id, char *node_name)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT n.node_name "
|
||||
" FROM repmgr.nodes n "
|
||||
" WHERE n.node_id != %i",
|
||||
node_id);
|
||||
|
||||
log_verbose(LOG_DEBUG, "get_bdr_other_node_name():\n %s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
||||
{
|
||||
snprintf(node_name,
|
||||
NAMEDATALEN,
|
||||
"%s", PQgetvalue(res, 0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning(_("get_bdr_other_node_name(): unable to execute query\n %s"),
|
||||
PQerrorMessage(conn));
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For BDR 2.x only
|
||||
*/
|
||||
void
|
||||
add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT c.relname "
|
||||
" FROM pg_class c "
|
||||
"INNER JOIN pg_namespace n "
|
||||
" ON c.relnamespace = n.oid "
|
||||
" WHERE n.nspname = 'repmgr' "
|
||||
" AND c.relkind = 'r' ");
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
/* XXX log error */
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
add_table_to_bdr_replication_set(conn,
|
||||
PQgetvalue(res, i, 0),
|
||||
"repmgr");
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT " BDR2_NODES_COLUMNS
|
||||
" FROM bdr.bdr_nodes "
|
||||
"ORDER BY node_seq_id ");
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT " BDR3_NODES_COLUMNS
|
||||
" FROM bdr.node_summary ns "
|
||||
" ORDER BY node_name");
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "get_all_bdr_node_records():\n%s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
_populate_bdr_node_records(res, node_list);
|
||||
|
||||
PQclear(res);
|
||||
return;
|
||||
}
|
||||
|
||||
RecordStatus
|
||||
get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
if (bdr_version_num < 3)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT " BDR2_NODES_COLUMNS
|
||||
" FROM bdr.bdr_nodes "
|
||||
" WHERE node_name = '%s'",
|
||||
node_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT " BDR3_NODES_COLUMNS
|
||||
" FROM bdr.node_summary ns "
|
||||
" WHERE ns.node_name = '%s'",
|
||||
node_name);
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "get_bdr_node_record_by_name():\n%s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_error(_("unable to retrieve BDR node record for \"%s\":\n %s"),
|
||||
node_name,
|
||||
PQerrorMessage(conn));
|
||||
|
||||
PQclear(res);
|
||||
return RECORD_ERROR;
|
||||
}
|
||||
|
||||
if (PQntuples(res) == 0)
|
||||
{
|
||||
PQclear(res);
|
||||
return RECORD_NOT_FOUND;
|
||||
}
|
||||
|
||||
_populate_bdr_node_record(res, node_info, 0);
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return RECORD_FOUND;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
_populate_bdr_node_records(PGresult *res, BdrNodeInfoList *node_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_node_info_list((NodeInfoList *) node_list);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
BdrNodeInfoListCell *cell;
|
||||
|
||||
cell = (BdrNodeInfoListCell *) pg_malloc0(sizeof(BdrNodeInfoListCell));
|
||||
|
||||
cell->node_info = pg_malloc0(sizeof(t_bdr_node_info));
|
||||
|
||||
_populate_bdr_node_record(res, cell->node_info, i);
|
||||
|
||||
if (node_list->tail)
|
||||
node_list->tail->next = cell;
|
||||
else
|
||||
node_list->head = cell;
|
||||
|
||||
node_list->tail = cell;
|
||||
node_list->node_count++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_populate_bdr_node_record(PGresult *res, t_bdr_node_info *node_info, int row)
|
||||
{
|
||||
snprintf(node_info->node_sysid, sizeof(node_info->node_sysid), "%s", PQgetvalue(res, row, 0));
|
||||
node_info->node_timeline = atoi(PQgetvalue(res, row, 1));
|
||||
node_info->node_dboid = atoi(PQgetvalue(res, row, 2));
|
||||
snprintf(node_info->node_name, sizeof(node_info->node_name), "%s", PQgetvalue(res, row, 3));
|
||||
snprintf(node_info->node_local_dsn, sizeof(node_info->node_local_dsn), "%s", PQgetvalue(res, row, 4));
|
||||
snprintf(node_info->peer_state_name, sizeof(node_info->peer_state_name), "%s", PQgetvalue(res, row, 5));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
am_bdr_failover_handler(PGconn *conn, int node_id)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
bool am_handler = false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBuffer(&query,
|
||||
"SELECT repmgr.am_bdr_failover_handler(%i)",
|
||||
node_id);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_error(_("unable to execute function repmgr.am_bdr_failover_handler():\n %s"),
|
||||
PQerrorMessage(conn));
|
||||
PQclear(res);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
am_handler = atobool(PQgetvalue(res, 0, 0));
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return am_handler;
|
||||
}
|
||||
|
||||
void
|
||||
unset_bdr_failover_handler(PGconn *conn)
|
||||
{
|
||||
PGresult *res = NULL;
|
||||
|
||||
res = PQexec(conn, "SELECT repmgr.unset_bdr_failover_handler()");
|
||||
|
||||
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;
|
||||
|
||||
if (bdr_version_num >= 3)
|
||||
return true;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT pg_catalog.count(*) "
|
||||
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s') AS repset "
|
||||
" WHERE repset = '%s'",
|
||||
node_name,
|
||||
BDR2_REPLICATION_SET_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;
|
||||
|
||||
if (bdr_version_num >= 3)
|
||||
return true;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
/*
|
||||
* Here we extract a list of existing replication sets, add 'repmgr', and
|
||||
* set the replication sets to the new list.
|
||||
*/
|
||||
appendPQExpBuffer(&query,
|
||||
" SELECT bdr.connection_set_replication_sets( "
|
||||
" ARRAY( "
|
||||
" SELECT repset::TEXT "
|
||||
" FROM pg_catalog.unnest(bdr.connection_get_replication_sets('%s')) AS repset "
|
||||
" UNION "
|
||||
" SELECT '%s'::TEXT "
|
||||
" ), "
|
||||
" '%s' "
|
||||
" ) ",
|
||||
node_name,
|
||||
BDR2_REPLICATION_SET_NAME,
|
||||
node_name);
|
||||
|
||||
log_debug("bdr_node_set_repmgr_set():\n%s", query.data);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
termPQExpBuffer(&query);
|
||||
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_debug("result status: %s", PQresStatus(PQresultStatus(res)));
|
||||
log_error(_("unable to create replication set \"repmgr\""));
|
||||
log_detail("%s", PQerrorMessage(conn));
|
||||
success = false;
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* miscellaneous debugging functions */
|
||||
|
||||
const char *
|
||||
|
||||
Reference in New Issue
Block a user