MXS-1703 Move more functions to MariaDBServer

Also, the QueryResult integer reading method now only reads non-negative integers
since the server rarely returns negative values. This frees negative values for
indicating parsing error(s).

Gtid-class was moved back to utility.hh/.cc because the QueryResult-class requires it.
This commit is contained in:
Esa Korhonen
2018-03-27 12:41:06 +03:00
parent 27fd0e78b5
commit 923de851f9
7 changed files with 285 additions and 260 deletions

View File

@ -17,7 +17,6 @@
#include "utilities.hh"
static int add_slave_to_master(long *slaves_list, int list_size, long node_id);
static void read_server_variables(MariaDBServer* serv_info);
static bool report_version_err = true;
@ -655,11 +654,11 @@ void MariaDBMonitor::monitor_database(MariaDBServer* serv_info)
serv_info->version = MYSQL_SERVER_VERSION_51;
}
/* Query a few settings. */
read_server_variables(serv_info);
serv_info->read_server_variables();
/* If gtid domain exists and server is 10.0, update gtid:s */
if (m_master_gtid_domain >= 0 && serv_info->version == MYSQL_SERVER_VERSION_100)
{
update_gtids(serv_info);
serv_info->update_gtids(m_master_gtid_domain);
}
/* Check for MariaDB 10.x.x and get status for multi-master replication */
if (serv_info->version == MYSQL_SERVER_VERSION_100 || serv_info->version == MYSQL_SERVER_VERSION_55)
@ -682,45 +681,6 @@ void MariaDBMonitor::monitor_database(MariaDBServer* serv_info)
}
}
/**
* Read server_id, read_only and (if 10.X) gtid_domain_id. TODO: Move to MariaDBServer
*
* @param serv_info Where to save results
*/
static void read_server_variables(MariaDBServer* serv_info)
{
MXS_MONITORED_SERVER* database = serv_info->server_base;
string query = "SELECT @@global.server_id, @@read_only;";
int columns = 2;
if (serv_info->version == MYSQL_SERVER_VERSION_100)
{
query.erase(query.end() - 1);
query += ", @@global.gtid_domain_id;";
columns = 3;
}
int ind_id = 0;
int ind_ro = 1;
int ind_domain = 2;
StringVector row;
if (query_one_row(database, query.c_str(), columns, &row))
{
int64_t server_id = scan_server_id(row[ind_id].c_str());
database->server->node_id = server_id;
serv_info->server_id = server_id;
ss_dassert(row[ind_ro] == "0" || row[ind_ro] == "1");
serv_info->read_only = (row[ind_ro] == "1");
if (columns == 3)
{
uint32_t domain = 0;
ss_debug(int rv = ) sscanf(row[ind_domain].c_str(), "%" PRIu32, &domain);
ss_dassert(rv == 1);
serv_info->gtid_domain_id = domain;
}
}
}
/**
* Monitor a database with given server info.
*
@ -747,34 +707,6 @@ void MariaDBMonitor::monitor_mysql_db(MariaDBServer* serv_info)
}
}
/**
* Query gtid_current_pos and gtid_binlog_pos and save the values to the server info object.
* Only the cluster master domain is parsed.
*
* @param info Server info structure for saving result TODO: move to MariaDBServer
* @return True if successful
*/
bool MariaDBMonitor::update_gtids(MariaDBServer* info)
{
MXS_MONITORED_SERVER* database = info->server_base;
StringVector row;
const char query[] = "SELECT @@gtid_current_pos, @@gtid_binlog_pos;";
const int ind_current_pos = 0;
const int ind_binlog_pos = 1;
int64_t domain = m_master_gtid_domain;
ss_dassert(domain >= 0);
bool rval = false;
if (query_one_row(database, query, 2, &row))
{
info->gtid_current_pos = (row[ind_current_pos] != "") ?
Gtid(row[ind_current_pos].c_str(), domain) : Gtid();
info->gtid_binlog_pos = (row[ind_binlog_pos] != "") ?
Gtid(row[ind_binlog_pos].c_str(), domain) : Gtid();
rval = true;
}
return rval;
}
/**
* Update replication settings and gtid:s of the slave server.
*
@ -785,31 +717,11 @@ MariaDBServer* MariaDBMonitor::update_slave_info(MXS_MONITORED_SERVER* server)
{
MariaDBServer* info = get_server_info(server);
if (info->slave_status.slave_sql_running &&
update_replication_settings(server, info) &&
update_gtids(info) &&
info->update_replication_settings() &&
info->update_gtids(m_master_gtid_domain) &&
info->do_show_slave_status(m_master_gtid_domain))
{
return info;
}
return NULL;
}
/**
* Query a few miscellaneous replication settings.
*
* @param database The slave server to query
* @param info Where to save results
* @return True on success
*/
bool MariaDBMonitor::update_replication_settings(MXS_MONITORED_SERVER *database, MariaDBServer* info)
{
StringVector row;
bool ok = query_one_row(database, "SELECT @@gtid_strict_mode, @@log_bin, @@log_slave_updates;", 3, &row);
if (ok)
{
info->rpl_settings.gtid_strict_mode = (row[0] == "1");
info->rpl_settings.log_bin = (row[1] == "1");
info->rpl_settings.log_slave_updates = (row[2] == "1");
}
return ok;
}

View File

@ -156,7 +156,7 @@ bool MariaDBMonitor::manual_rejoin(SERVER* rejoin_server, json_t** output)
if (server_is_rejoin_suspect(mon_server, master_info, output))
{
if (update_gtids(master_info))
if (master_info->update_gtids(m_master_gtid_domain))
{
if (can_replicate_from(mon_server, server_info, master_info))
{
@ -433,7 +433,7 @@ bool MariaDBMonitor::get_joinable_servers(ServerVector* output)
bool comm_ok = true;
if (!suspects.empty())
{
if (update_gtids(master_info))
if (master_info->update_gtids(m_master_gtid_domain))
{
for (size_t i = 0; i < suspects.size(); i++)
{
@ -814,7 +814,7 @@ bool MariaDBMonitor::failover_wait_relay_log(MXS_MONITORED_SERVER* new_master, i
Gtid old_gtid_io_pos = master_info->slave_status.gtid_io_pos;
// Update gtid:s first to make sure Gtid_IO_Pos is the more recent value.
// It doesn't matter here, but is a general rule.
query_ok = update_gtids(master_info) &&
query_ok = master_info->update_gtids(m_master_gtid_domain) &&
master_info->do_show_slave_status(m_master_gtid_domain);
io_pos_stable = (old_gtid_io_pos == master_info->slave_status.gtid_io_pos);
}
@ -903,7 +903,7 @@ bool MariaDBMonitor::switchover_demote_master(MXS_MONITORED_SERVER* current_mast
if (!query_error)
{
query = "";
if (update_gtids(info))
if (info->update_gtids(m_master_gtid_domain))
{
success = true;
}
@ -1071,7 +1071,7 @@ bool MariaDBMonitor::wait_cluster_stabilization(MXS_MONITORED_SERVER* new_master
MariaDBServer* new_master_info = get_server_info(new_master);
if (mxs_mysql_query(new_master->con, "FLUSH TABLES;") == 0 &&
update_gtids(new_master_info))
new_master_info->update_gtids(m_master_gtid_domain))
{
int query_fails = 0;
int repl_fails = 0;
@ -1094,7 +1094,8 @@ bool MariaDBMonitor::wait_cluster_stabilization(MXS_MONITORED_SERVER* new_master
{
MXS_MONITORED_SERVER* slave = wait_list[i];
MariaDBServer* slave_info = get_server_info(slave);
if (update_gtids(slave_info) && slave_info->do_show_slave_status(m_master_gtid_domain))
if (slave_info->update_gtids(m_master_gtid_domain) &&
slave_info->do_show_slave_status(m_master_gtid_domain))
{
if (!slave_info->slave_status.last_error.empty())
{
@ -1157,7 +1158,7 @@ bool MariaDBMonitor::switchover_check_preferred_master(MXS_MONITORED_SERVER* pre
ss_dassert(preferred);
bool rval = true;
MariaDBServer* preferred_info = update_slave_info(preferred);
if (preferred_info == NULL || !check_replication_settings(preferred, preferred_info))
if (preferred_info == NULL || !preferred_info->check_replication_settings())
{
PRINT_MXS_JSON_ERROR(err_out, "The requested server '%s' is not a valid promotion candidate.",
preferred->server->unique_name);
@ -1234,14 +1235,14 @@ MXS_MONITORED_SERVER* MariaDBMonitor::select_new_master(ServerVector* slaves_out
{
slaves_out->push_back(cand);
// Check that server is not in the exclusion list while still being a valid choice.
if (server_is_excluded(cand) && check_replication_settings(cand, cand_info, WARNINGS_OFF))
if (server_is_excluded(cand) && cand_info->check_replication_settings(WARNINGS_OFF))
{
valid_but_excluded.push_back(cand);
const char CANNOT_SELECT[] = "Promotion candidate '%s' is excluded from new "
"master selection.";
MXS_INFO(CANNOT_SELECT, cand->server->unique_name);
}
else if (check_replication_settings(cand, cand_info))
else if (cand_info->check_replication_settings())
{
// If no new master yet, accept any valid candidate. Otherwise check.
if (current_best == NULL || is_candidate_better(current_best_info, cand_info))
@ -1482,49 +1483,6 @@ bool MariaDBMonitor::failover_check(json_t** error_out)
return !error && slaves > 0;
}
/**
* Check if server has binary log enabled. Print warnings if gtid_strict_mode or log_slave_updates is off.
*
* @param server Server to check
* @param server_info Server info
* @param print_on Print warnings or not
* @return True if log_bin is on
*/
bool check_replication_settings(const MXS_MONITORED_SERVER* server, MariaDBServer* server_info,
print_repl_warnings_t print_warnings)
{
bool rval = true;
const char* servername = server->server->unique_name;
if (server_info->rpl_settings.log_bin == false)
{
if (print_warnings == WARNINGS_ON)
{
const char NO_BINLOG[] =
"Slave '%s' has binary log disabled and is not a valid promotion candidate.";
MXS_WARNING(NO_BINLOG, servername);
}
rval = false;
}
else if (print_warnings == WARNINGS_ON)
{
if (server_info->rpl_settings.gtid_strict_mode == false)
{
const char NO_STRICT[] =
"Slave '%s' has gtid_strict_mode disabled. Enabling this setting is recommended. "
"For more information, see https://mariadb.com/kb/en/library/gtid/#gtid_strict_mode";
MXS_WARNING(NO_STRICT, servername);
}
if (server_info->rpl_settings.log_slave_updates == false)
{
const char NO_SLAVE_UPDATES[] =
"Slave '%s' has log_slave_updates disabled. It is a valid candidate but replication "
"will break for lagging slaves if '%s' is promoted.";
MXS_WARNING(NO_SLAVE_UPDATES, servername, servername);
}
}
return rval;
}
/**
* Checks if slave can replicate from master. Only considers gtid:s and only detects obvious errors. The
* non-detected errors will mostly be detected once the slave tries to start replicating.
@ -1538,7 +1496,7 @@ bool MariaDBMonitor::can_replicate_from(MXS_MONITORED_SERVER* slave,
MariaDBServer* slave_info, MariaDBServer* master_info)
{
bool rval = false;
if (update_gtids(slave_info))
if (slave_info->update_gtids(m_master_gtid_domain))
{
Gtid slave_gtid = slave_info->gtid_current_pos;
Gtid master_gtid = master_info->gtid_binlog_pos;

View File

@ -37,12 +37,6 @@ typedef std::tr1::unordered_map<MXS_MONITORED_SERVER*, MariaDBServer*> ServerInf
// Server container, owns the server objects.
typedef std::vector<MariaDBServer> ServerContainer; // TODO: Rename/get rid of ServerVector typedef!
enum print_repl_warnings_t
{
WARNINGS_ON,
WARNINGS_OFF
};
enum slave_down_setting_t
{
ACCEPT_DOWN,
@ -51,8 +45,6 @@ enum slave_down_setting_t
// TODO: Most of following should be class methods
void print_redirect_errors(MXS_MONITORED_SERVER* first_server, const ServerVector& servers, json_t** err_out);
bool check_replication_settings(const MXS_MONITORED_SERVER* server, MariaDBServer* server_info,
print_repl_warnings_t print_warnings = WARNINGS_ON);
MXS_MONITORED_SERVER* getServerByNodeId(MXS_MONITORED_SERVER *, long);
MXS_MONITORED_SERVER* getSlaveOfNodeId(MXS_MONITORED_SERVER *, long, slave_down_setting_t);
@ -217,7 +209,6 @@ private:
bool server_is_excluded(const MXS_MONITORED_SERVER* server);
bool is_candidate_better(const MariaDBServer* current_best_info, const MariaDBServer* candidate_info);
MariaDBServer* update_slave_info(MXS_MONITORED_SERVER* server);
bool update_replication_settings(MXS_MONITORED_SERVER *database, MariaDBServer* info);
void init_server_info();
bool slave_receiving_events();
void monitor_database(MariaDBServer* param_db);
@ -247,7 +238,6 @@ private:
json_t** output);
bool cluster_can_be_joined();
bool failover_check(json_t** error_out);
bool update_gtids(MariaDBServer* info);
void disable_setting(const char* setting);
bool switchover_check_new(const MXS_MONITORED_SERVER* monitored_server, json_t** error);
bool switchover_check_current(const MXS_MONITORED_SERVER* suggested_curr_master,

View File

@ -18,68 +18,6 @@
#include <maxscale/mysql_utils.h>
#include "utilities.hh"
Gtid::Gtid()
: domain(0)
, server_id(SERVER_ID_UNKNOWN)
, sequence(0)
{}
Gtid::Gtid(const char* str, int64_t search_domain)
: domain(0)
, server_id(SERVER_ID_UNKNOWN)
, sequence(0)
{
// Autoselect only allowed with one triplet
ss_dassert(search_domain >= 0 || strchr(str, ',') == NULL);
parse_triplet(str);
if (search_domain >= 0 && domain != search_domain)
{
// Search for the correct triplet.
bool found = false;
for (const char* next_triplet = strchr(str, ',');
next_triplet != NULL && !found;
next_triplet = strchr(next_triplet, ','))
{
parse_triplet(++next_triplet);
if (domain == search_domain)
{
found = true;
}
}
ss_dassert(found);
}
}
bool Gtid::operator == (const Gtid& rhs) const
{
return domain == rhs.domain &&
server_id != SERVER_ID_UNKNOWN && server_id == rhs.server_id &&
sequence == rhs.sequence;
}
string Gtid::to_string() const
{
std::stringstream ss;
if (server_id != SERVER_ID_UNKNOWN)
{
ss << domain << "-" << server_id << "-" << sequence;
}
return ss.str();
}
void Gtid::parse_triplet(const char* str)
{
ss_debug(int rv = ) sscanf(str, "%" PRIu32 "-%" PRId64 "-%" PRIu64, &domain, &server_id, &sequence);
ss_dassert(rv == 3);
}
string Gtid::generate_master_gtid_wait_cmd(double timeout) const
{
std::stringstream query_ss;
query_ss << "SELECT MASTER_GTID_WAIT(\"" << to_string() << "\", " << timeout << ");";
return query_ss.str();
}
SlaveStatusInfo::SlaveStatusInfo()
: master_server_id(SERVER_ID_UNKNOWN)
, master_port(0)
@ -214,7 +152,7 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
{
/** Only check binlog name for the first running slave */
string master_log_file = result->get_string(i_master_log_file);
uint64_t read_master_log_pos = result->get_int(i_read_master_log_pos);
uint64_t read_master_log_pos = result->get_uint(i_read_master_log_pos);
if (slave_status.master_log_file != master_log_file ||
slave_status.read_master_log_pos != read_master_log_pos)
{
@ -233,7 +171,7 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
* root master server.
* Please note, there could be no slaves at all if Slave_SQL_Running == 'No'
*/
int64_t last_io_errno = result->get_int(i_last_io_errno);
int64_t last_io_errno = result->get_uint(i_last_io_errno);
int io_errno = last_io_errno;
const int connection_errno = 2003;
@ -247,18 +185,18 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
if (server_version == MYSQL_SERVER_VERSION_100)
{
slave_status.master_host = result->get_string(i_master_host);
slave_status.master_port = result->get_int(i_master_port);
slave_status.master_port = result->get_uint(i_master_port);
string last_io_error = result->get_string(i_last_io_error);
string last_sql_error = result->get_string(i_last_sql_error);
slave_status.last_error = !last_io_error.empty() ? last_io_error : last_sql_error;
int heartbeats = result->get_int(i_slave_rec_hbs);
int heartbeats = result->get_uint(i_slave_rec_hbs);
if (slave_heartbeats < heartbeats)
{
latest_event = time(NULL);
slave_heartbeats = heartbeats;
heartbeat_period = result->get_int(i_slave_hb_period);
heartbeat_period = result->get_uint(i_slave_hb_period);
}
string using_gtid = result->get_string(i_using_gtid);
if (gtid_domain >= 0 && (using_gtid == "Current_Pos" || using_gtid == "Slave_Pos"))
@ -291,3 +229,103 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
n_slaves_running = nrunning;
return rval;
}
bool MariaDBServer::update_gtids(int64_t gtid_domain)
{
ss_dassert(gtid_domain >= 0);
static const string query = "SELECT @@gtid_current_pos, @@gtid_binlog_pos;";
const int ind_current_pos = 0;
const int ind_binlog_pos = 1;
bool rval = false;
auto result = execute_query(query);
if (result.get() != NULL && result->next_row())
{
gtid_current_pos = result->get_gtid(ind_current_pos, gtid_domain);
gtid_binlog_pos = result->get_gtid(ind_binlog_pos, gtid_domain);
rval = true;
}
return rval;
}
bool MariaDBServer::update_replication_settings()
{
static const string query = "SELECT @@gtid_strict_mode, @@log_bin, @@log_slave_updates;";
bool rval = false;
auto result = execute_query(query);
if (result.get() != NULL && result->next_row())
{
rpl_settings.gtid_strict_mode = result->get_bool(0);
rpl_settings.log_bin = result->get_bool(1);
rpl_settings.log_slave_updates = result->get_bool(2);
rval = true;
}
return rval;
}
void MariaDBServer::read_server_variables()
{
MXS_MONITORED_SERVER* database = server_base;
string query = "SELECT @@global.server_id, @@read_only;";
int columns = 2;
if (version == MYSQL_SERVER_VERSION_100)
{
query.erase(query.end() - 1);
query += ", @@global.gtid_domain_id;";
columns = 3;
}
int ind_id = 0;
int ind_ro = 1;
int ind_domain = 2;
auto result = execute_query(query);
if (result.get() != NULL && result->next_row())
{
int64_t server_id_parsed = result->get_uint(ind_id);
if (server_id_parsed < 0)
{
server_id_parsed = SERVER_ID_UNKNOWN;
}
database->server->node_id = server_id_parsed;
server_id = server_id_parsed;
read_only = result->get_bool(ind_ro);
if (columns == 3)
{
gtid_domain_id = result->get_uint(ind_domain);
}
}
}
bool MariaDBServer::check_replication_settings(print_repl_warnings_t print_warnings)
{
bool rval = true;
const char* servername = server_base->server->unique_name;
if (rpl_settings.log_bin == false)
{
if (print_warnings == WARNINGS_ON)
{
const char NO_BINLOG[] =
"Slave '%s' has binary log disabled and is not a valid promotion candidate.";
MXS_WARNING(NO_BINLOG, servername);
}
rval = false;
}
else if (print_warnings == WARNINGS_ON)
{
if (rpl_settings.gtid_strict_mode == false)
{
const char NO_STRICT[] =
"Slave '%s' has gtid_strict_mode disabled. Enabling this setting is recommended. "
"For more information, see https://mariadb.com/kb/en/library/gtid/#gtid_strict_mode";
MXS_WARNING(NO_STRICT, servername);
}
if (rpl_settings.log_slave_updates == false)
{
const char NO_SLAVE_UPDATES[] =
"Slave '%s' has log_slave_updates disabled. It is a valid candidate but replication "
"will break for lagging slaves if '%s' is promoted.";
MXS_WARNING(NO_SLAVE_UPDATES, servername, servername);
}
}
return rval;
}

View File

@ -27,38 +27,10 @@ enum mysql_server_version
MYSQL_SERVER_VERSION_51
};
class Gtid
enum print_repl_warnings_t
{
public:
uint32_t domain;
int64_t server_id; // Is actually 32bit unsigned. 0 is only used by server versions <= 10.1
uint64_t sequence;
Gtid();
/**
* Parse a Gtid-triplet from a string. In case of a multi-triplet value, only the triplet with
* the given domain is returned.
*
* @param str Gtid string
* @param search_domain The Gtid domain whose triplet should be returned. Negative domain stands for
* autoselect, which is only allowed when the string contains one triplet.
*/
Gtid(const char* str, int64_t search_domain = -1);
bool operator == (const Gtid& rhs) const;
std::string to_string() const;
/**
* Generate a MASTER_GTID_WAIT()-query to this gtid.
*
* @param timeout Maximum wait time in seconds
* @return The query
*/
std::string generate_master_gtid_wait_cmd(double timeout) const;
private:
void parse_triplet(const char* str);
WARNINGS_ON,
WARNINGS_OFF
};
// Contains data returned by one row of SHOW ALL SLAVES STATUS
@ -155,4 +127,33 @@ public:
* @return True on success
*/
bool do_show_slave_status(int64_t gtid_domain);
/**
* Query gtid_current_pos and gtid_binlog_pos and save the values to the server.
* Only the given domain is parsed.
*
* @param gtid_domain Which gtid domain should be parsed
* @return True if successful
*/
bool update_gtids(int64_t gtid_domain);
/**
* Query a few miscellaneous replication settings.
*
* @return True on success
*/
bool update_replication_settings();
/**
* Query and save server_id, read_only and (if 10.X) gtid_domain_id.
*/
void read_server_variables();
/**
* Check if server has binary log enabled. Print warnings if gtid_strict_mode or log_slave_updates is off.
*
* @param print_on Print warnings or not
* @return True if log_bin is on
*/
bool check_replication_settings(print_repl_warnings_t print_warnings = WARNINGS_ON);
};

View File

@ -177,12 +177,21 @@ string QueryResult::get_string(int64_t column_ind) const
return data ? data : "";
}
int64_t QueryResult::get_int(int64_t column_ind) const
int64_t QueryResult::get_uint(int64_t column_ind) const
{
ss_dassert(column_ind < m_columns);
char* data = m_rowdata[column_ind];
errno = 0; // strtoll sets this
return data ? strtoll(data, NULL, 10) : 0;
int64_t rval = -1;
if (data)
{
errno = 0; // strtoll sets this
auto parsed = strtoll(data, NULL, 10);
if (parsed >= 0 && errno == 0)
{
rval = parsed;
}
}
return rval;
}
bool QueryResult::get_bool(int64_t column_ind) const
@ -191,3 +200,77 @@ bool QueryResult::get_bool(int64_t column_ind) const
char* data = m_rowdata[column_ind];
return data ? (strcmp(data,"Y") == 0 || strcmp(data, "1") == 0) : false;
}
Gtid QueryResult::get_gtid(int64_t column_ind, int64_t gtid_domain) const
{
ss_dassert(column_ind < m_columns);
char* data = m_rowdata[column_ind];
Gtid rval;
if (data && *data)
{
rval = Gtid(data, gtid_domain);
}
return rval;
}
Gtid::Gtid()
: domain(0)
, server_id(SERVER_ID_UNKNOWN)
, sequence(0)
{}
Gtid::Gtid(const char* str, int64_t search_domain)
: domain(0)
, server_id(SERVER_ID_UNKNOWN)
, sequence(0)
{
// Autoselect only allowed with one triplet
ss_dassert(search_domain >= 0 || strchr(str, ',') == NULL);
parse_triplet(str);
if (search_domain >= 0 && domain != search_domain)
{
// Search for the correct triplet.
bool found = false;
for (const char* next_triplet = strchr(str, ',');
next_triplet != NULL && !found;
next_triplet = strchr(next_triplet, ','))
{
parse_triplet(++next_triplet);
if (domain == search_domain)
{
found = true;
}
}
ss_dassert(found);
}
}
bool Gtid::operator == (const Gtid& rhs) const
{
return domain == rhs.domain &&
server_id != SERVER_ID_UNKNOWN && server_id == rhs.server_id &&
sequence == rhs.sequence;
}
string Gtid::to_string() const
{
std::stringstream ss;
if (server_id != SERVER_ID_UNKNOWN)
{
ss << domain << "-" << server_id << "-" << sequence;
}
return ss.str();
}
void Gtid::parse_triplet(const char* str)
{
ss_debug(int rv = ) sscanf(str, "%" PRIu32 "-%" PRId64 "-%" PRIu64, &domain, &server_id, &sequence);
ss_dassert(rv == 3);
}
string Gtid::generate_master_gtid_wait_cmd(double timeout) const
{
std::stringstream query_ss;
query_ss << "SELECT MASTER_GTID_WAIT(\"" << to_string() << "\", " << timeout << ");";
return query_ss.str();
}

View File

@ -72,6 +72,40 @@ string get_connection_errors(const ServerVector& servers);
*/
string monitored_servers_to_string(const ServerVector& array);
class Gtid
{
public:
uint32_t domain;
int64_t server_id; // Is actually 32bit unsigned. 0 is only used by server versions <= 10.1
uint64_t sequence;
Gtid();
/**
* Parse a Gtid-triplet from a string. In case of a multi-triplet value, only the triplet with
* the given domain is returned.
*
* @param str Gtid string
* @param search_domain The Gtid domain whose triplet should be returned. Negative domain stands for
* autoselect, which is only allowed when the string contains one triplet.
*/
Gtid(const char* str, int64_t search_domain = -1);
bool operator == (const Gtid& rhs) const;
std::string to_string() const;
/**
* Generate a MASTER_GTID_WAIT()-query to this gtid.
*
* @param timeout Maximum wait time in seconds
* @return The query
*/
std::string generate_master_gtid_wait_cmd(double timeout) const;
private:
void parse_triplet(const char* str);
};
/**
* Helper class for simplifying working with resultsets. Used in MariaDBServer.
*/
@ -124,13 +158,12 @@ public:
string get_string(int64_t column_ind) const;
/**
* Read an integer value from the current row and given column. No error checking is done on the parsing.
* The parsing is performed by @c strtoll(), so the caller may check errno for errors.
* Read a non-negative integer value from the current row and given column.
*
* @param column_ind Column index
* @return Value as integer
* @return Value as integer. 0 or greater indicates success, -1 is returned on error.
*/
int64_t get_int(int64_t column_ind) const;
int64_t get_uint(int64_t column_ind) const;
/**
* Read a boolean value from the current row and given column.
@ -140,6 +173,16 @@ public:
*/
bool get_bool(int64_t column_ind) const;
/**
* Read a gtid values from the current row and given column. If the field is empty, will return an invalid
* gtid.
*
* @param column_ind Column index
* @param gtid_domain Which gtid domain to parse
* @return Value as a gtid.
*/
Gtid get_gtid(int64_t column_ind, int64_t gtid_domain) const;
private:
MYSQL_RES* m_resultset; // Underlying result set, freed at dtor.
std::tr1::unordered_map<string, int64_t> m_col_indexes; // Map of column name -> index