MXS-2546 Separate slave connection settings to its own class
The settings are different from the other fields in that they should not change on their own. Most manipulation functions only require the settings. Also takes into use a class for host and port data.
This commit is contained in:
parent
0257e6e690
commit
2a1925744b
@ -189,7 +189,8 @@ void MariaDBMonitor::build_replication_graph()
|
||||
bool is_external = false;
|
||||
if (use_hostnames)
|
||||
{
|
||||
found_master = get_server(slave_conn.master_host, slave_conn.master_port);
|
||||
found_master = get_server(slave_conn.settings.master_endpoint.host(),
|
||||
slave_conn.settings.master_endpoint.port());
|
||||
if (!found_master)
|
||||
{
|
||||
// Must be an external server.
|
||||
|
@ -366,10 +366,8 @@ bool MariaDBMonitor::manual_reset_replication(SERVER* master_server, json_t** er
|
||||
|
||||
if (!slaves.empty())
|
||||
{
|
||||
SlaveStatus new_conn;
|
||||
SERVER* new_master_srv = new_master->m_server_base->server;
|
||||
new_conn.master_host = new_master_srv->address;
|
||||
new_conn.master_port = new_master_srv->port;
|
||||
SlaveStatus::Settings new_conn("", new_master_srv);
|
||||
GeneralOpData general(error_out, mxb::Duration(0.0)); // Expect this to complete quickly.
|
||||
size_t slave_conns_started = 0;
|
||||
for (auto slave : slaves)
|
||||
@ -507,7 +505,7 @@ int MariaDBMonitor::redirect_slaves_ex(GeneralOpData& general, OperationType typ
|
||||
{
|
||||
// No conflict, redirect as normal.
|
||||
auto old_conn = redirectable->slave_connection_status(from);
|
||||
if (redirectable->redirect_existing_slave_conn(general, *old_conn, to))
|
||||
if (redirectable->redirect_existing_slave_conn(general, old_conn->settings, to))
|
||||
{
|
||||
successes++;
|
||||
redirected->push_back(redirectable);
|
||||
@ -576,9 +574,7 @@ uint32_t MariaDBMonitor::do_rejoin(const ServerArray& joinable_servers, json_t**
|
||||
MXS_NOTICE("Directing standalone server '%s' to replicate from '%s'.", name, master_name);
|
||||
// A slave connection description is required. As this is the only connection, no name
|
||||
// is required.
|
||||
SlaveStatus new_conn;
|
||||
new_conn.master_host = master_server->address;
|
||||
new_conn.master_port = master_server->port;
|
||||
SlaveStatus::Settings new_conn("", master_server);
|
||||
op_success = joinable->create_start_slave(general, new_conn);
|
||||
}
|
||||
else
|
||||
@ -595,7 +591,8 @@ uint32_t MariaDBMonitor::do_rejoin(const ServerArray& joinable_servers, json_t**
|
||||
name, master_name, master_name);
|
||||
// Multisource replication does not get to this point.
|
||||
mxb_assert(joinable->m_slave_status.size() == 1);
|
||||
op_success = joinable->redirect_existing_slave_conn(general, joinable->m_slave_status[0],
|
||||
op_success = joinable->redirect_existing_slave_conn(general,
|
||||
joinable->m_slave_status[0].settings,
|
||||
m_master);
|
||||
}
|
||||
|
||||
@ -713,6 +710,7 @@ bool MariaDBMonitor::server_is_rejoin_suspect(MariaDBServer* rejoin_cand, json_t
|
||||
else if (rejoin_cand->m_slave_status.size() == 1)
|
||||
{
|
||||
SlaveStatus* slave_status = &rejoin_cand->m_slave_status[0];
|
||||
|
||||
// which is connected to master but it's the wrong one
|
||||
if (slave_status->slave_io_running == SlaveStatus::SLAVE_IO_YES
|
||||
&& slave_status->master_server_id != m_master->m_server_id)
|
||||
@ -721,11 +719,13 @@ bool MariaDBMonitor::server_is_rejoin_suspect(MariaDBServer* rejoin_cand, json_t
|
||||
}
|
||||
// or is disconnected but master host or port is wrong.
|
||||
else if (slave_status->slave_io_running == SlaveStatus::SLAVE_IO_CONNECTING
|
||||
&& slave_status->slave_sql_running
|
||||
&& (slave_status->master_host != m_master->m_server_base->server->address
|
||||
|| slave_status->master_port != m_master->m_server_base->server->port))
|
||||
&& slave_status->slave_sql_running)
|
||||
{
|
||||
is_suspect = true;
|
||||
EndPoint cluster_master_endpoint(m_master->m_server_base->server);
|
||||
if (slave_status->settings.master_endpoint != cluster_master_endpoint)
|
||||
{
|
||||
is_suspect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -948,7 +948,7 @@ void MariaDBMonitor::wait_cluster_stabilization(GeneralOpData& op, const ServerA
|
||||
{
|
||||
// IO error on slave
|
||||
MXS_WARNING("%s cannot start replication because of IO thread error: '%s'.",
|
||||
slave_conn->to_short_string().c_str(), slave_conn->last_error.c_str());
|
||||
slave_conn->settings.to_string().c_str(), slave_conn->last_error.c_str());
|
||||
repl_fails.push_back(*iter);
|
||||
iter = unconfirmed.erase(iter);
|
||||
}
|
||||
@ -956,7 +956,7 @@ void MariaDBMonitor::wait_cluster_stabilization(GeneralOpData& op, const ServerA
|
||||
{
|
||||
// SQL error on slave
|
||||
MXS_WARNING("%s cannot start replication because of SQL thread error: '%s'.",
|
||||
slave_conn->to_short_string().c_str(), slave_conn->last_error.c_str());
|
||||
slave_conn->settings.to_string().c_str(), slave_conn->last_error.c_str());
|
||||
repl_fails.push_back(*iter);
|
||||
iter = unconfirmed.erase(iter);
|
||||
}
|
||||
@ -1024,7 +1024,7 @@ void MariaDBMonitor::wait_cluster_stabilization(GeneralOpData& op, const ServerA
|
||||
if (slave_conn && !slave_conn->last_error.empty())
|
||||
{
|
||||
MXB_WARNING("%s did not connect because of error: '%s'",
|
||||
slave_conn->to_short_string().c_str(), slave_conn->last_error.c_str());
|
||||
slave_conn->settings.to_string().c_str(), slave_conn->last_error.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1503,7 +1503,7 @@ void MariaDBMonitor::check_cluster_operations_support()
|
||||
{
|
||||
supported = false;
|
||||
auto reason = string_printf("%s is not using gtid-replication.",
|
||||
slave_conn.to_short_string().c_str());
|
||||
slave_conn.settings.to_string().c_str());
|
||||
printer.cat(all_reasons, reason);
|
||||
}
|
||||
}
|
||||
|
@ -310,10 +310,10 @@ bool MariaDBServer::do_show_slave_status(string* errmsg_out)
|
||||
bool parse_error = false;
|
||||
while (result->next_row())
|
||||
{
|
||||
SlaveStatus new_row;
|
||||
new_row.owning_server = name();
|
||||
new_row.master_host = result->get_string(i_master_host);
|
||||
new_row.master_port = result->get_int(i_master_port);
|
||||
SlaveStatus new_row(name());
|
||||
new_row.settings.master_endpoint = EndPoint(result->get_string(i_master_host),
|
||||
result->get_int(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);
|
||||
new_row.last_error = !last_io_error.empty() ? last_io_error : last_sql_error;
|
||||
@ -337,7 +337,7 @@ bool MariaDBServer::do_show_slave_status(string* errmsg_out)
|
||||
|
||||
if (all_slaves_status)
|
||||
{
|
||||
new_row.name = result->get_string(i_connection_name);
|
||||
new_row.settings.name = result->get_string(i_connection_name);
|
||||
new_row.received_heartbeats = result->get_int(i_slave_rec_hbs);
|
||||
|
||||
string using_gtid = result->get_string(i_using_gtid);
|
||||
@ -1003,7 +1003,7 @@ bool MariaDBServer::sstatus_array_topology_equal(const SlaveStatusArray& new_sla
|
||||
// but the situations it would make a difference are so rare they can be ignored.
|
||||
if (new_row.slave_io_running != old_row.slave_io_running
|
||||
|| new_row.slave_sql_running != old_row.slave_sql_running
|
||||
|| new_row.master_host != old_row.master_host || new_row.master_port != old_row.master_port
|
||||
|| new_row.settings.master_endpoint != old_row.settings.master_endpoint
|
||||
|| new_row.master_server_id != old_row.master_server_id)
|
||||
{
|
||||
rval = false;
|
||||
@ -1026,7 +1026,8 @@ const SlaveStatus* MariaDBServer::sstatus_find_previous_row(const SlaveStatus& s
|
||||
{
|
||||
// Helper function. Checks if the connection in the new row is to the same server than in the old row.
|
||||
auto compare_rows = [](const SlaveStatus& lhs, const SlaveStatus& rhs) -> bool {
|
||||
return rhs.master_host == lhs.master_host && rhs.master_port == lhs.master_port;
|
||||
return lhs.settings.name == rhs.settings.name
|
||||
&& lhs.settings.master_endpoint == rhs.settings.master_endpoint;
|
||||
};
|
||||
|
||||
// Usually the same slave connection can be found from the same index than in the previous slave
|
||||
@ -1182,13 +1183,11 @@ const SlaveStatus* MariaDBServer::slave_connection_status(const MariaDBServer* t
|
||||
if (m_settings.assume_unique_hostnames)
|
||||
{
|
||||
// Can simply compare host:port.
|
||||
SERVER* target_srv = target->m_server_base->server;
|
||||
string target_host = target_srv->address;
|
||||
int target_port = target_srv->port;
|
||||
EndPoint target_endpoint(target->m_server_base->server);
|
||||
for (const SlaveStatus& ss : m_slave_status)
|
||||
{
|
||||
if (ss.master_host == target_host && ss.master_port == target_port
|
||||
&& ss.slave_sql_running && ss.slave_io_running != SlaveStatus::SLAVE_IO_NO)
|
||||
if (ss.settings.master_endpoint == target_endpoint && ss.slave_sql_running
|
||||
&& ss.slave_io_running != SlaveStatus::SLAVE_IO_NO)
|
||||
{
|
||||
rval = &ss;
|
||||
break;
|
||||
@ -1217,11 +1216,10 @@ const SlaveStatus* MariaDBServer::slave_connection_status(const MariaDBServer* t
|
||||
|
||||
const SlaveStatus* MariaDBServer::slave_connection_status_host_port(const MariaDBServer* target) const
|
||||
{
|
||||
string target_host = target->m_server_base->server->address;
|
||||
int target_port = target->m_server_base->server->port;
|
||||
EndPoint target_endpoint(target->m_server_base->server);
|
||||
for (const SlaveStatus& ss : m_slave_status)
|
||||
{
|
||||
if (ss.master_host == target_host && ss.master_port == target_port)
|
||||
if (ss.settings.master_endpoint == target_endpoint)
|
||||
{
|
||||
return &ss;
|
||||
}
|
||||
@ -1438,18 +1436,19 @@ bool MariaDBServer::reset_all_slave_conns(json_t** error_out)
|
||||
{
|
||||
string error_msg;
|
||||
bool error = false;
|
||||
for (auto& sstatus : m_slave_status)
|
||||
for (const auto& slave_conn : m_slave_status)
|
||||
{
|
||||
auto stop = string_printf("STOP SLAVE '%s';", sstatus.name.c_str());
|
||||
auto reset = string_printf("RESET SLAVE '%s' ALL;", sstatus.name.c_str());
|
||||
auto conn_name = slave_conn.settings.name;
|
||||
auto stop = string_printf("STOP SLAVE '%s';", conn_name.c_str());
|
||||
auto reset = string_printf("RESET SLAVE '%s' ALL;", conn_name.c_str());
|
||||
if (!execute_cmd(stop, &error_msg) || !execute_cmd(reset, &error_msg))
|
||||
{
|
||||
error = true;
|
||||
string log_message = sstatus.name.empty() ?
|
||||
string log_message = conn_name.empty() ?
|
||||
string_printf("Error when reseting the default slave connection of '%s': %s",
|
||||
name(), error_msg.c_str()) :
|
||||
string_printf("Error when reseting the slave connection '%s' of '%s': %s",
|
||||
sstatus.name.c_str(), name(), error_msg.c_str());
|
||||
conn_name.c_str(), name(), error_msg.c_str());
|
||||
PRINT_MXS_JSON_ERROR(error_out, "%s", log_message.c_str());
|
||||
break;
|
||||
}
|
||||
@ -1789,7 +1788,8 @@ bool MariaDBServer::remove_slave_conns(GeneralOpData& op, const SlaveStatusArray
|
||||
bool stop_slave_error = false;
|
||||
for (size_t i = 0; !stop_slave_error && i < conns_to_remove.size(); i++)
|
||||
{
|
||||
if (!stop_slave_conn(conns_to_remove[i].name, StopMode::RESET_ALL, time_remaining, error_out))
|
||||
if (!stop_slave_conn(conns_to_remove[i].settings.name, StopMode::RESET_ALL, time_remaining,
|
||||
error_out))
|
||||
{
|
||||
stop_slave_error = true;
|
||||
}
|
||||
@ -1814,12 +1814,12 @@ bool MariaDBServer::remove_slave_conns(GeneralOpData& op, const SlaveStatusArray
|
||||
std::set<string> connection_names;
|
||||
for (auto& slave_conn : m_slave_status)
|
||||
{
|
||||
connection_names.insert(slave_conn.name);
|
||||
connection_names.insert(slave_conn.settings.name);
|
||||
}
|
||||
int found = 0;
|
||||
for (auto& removed_conn : conns_to_remove_copy)
|
||||
{
|
||||
if (connection_names.count(removed_conn.name) > 0)
|
||||
if (connection_names.count(removed_conn.settings.name) > 0)
|
||||
{
|
||||
found++;
|
||||
}
|
||||
@ -1889,8 +1889,7 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
auto conn_can_be_merged = [this](const SlaveStatus& slave_conn, string* ignore_reason_out) -> bool {
|
||||
bool accepted = true;
|
||||
auto master_id = slave_conn.master_server_id;
|
||||
string my_host = m_server_base->server->address;
|
||||
int my_port = m_server_base->server->port;
|
||||
EndPoint my_host_port(m_server_base->server);
|
||||
// The connection is only merged if it satisfies the copy-conditions. Merging has also
|
||||
// additional requirements.
|
||||
string ignore_reason;
|
||||
@ -1904,7 +1903,7 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
accepted = false;
|
||||
ignore_reason = string_printf("it points to '%s' (according to server id:s).", name());
|
||||
}
|
||||
else if (slave_conn.master_host == my_host && slave_conn.master_port == my_port)
|
||||
else if (slave_conn.settings.master_endpoint == my_host_port)
|
||||
{
|
||||
accepted = false;
|
||||
ignore_reason = string_printf("it points to '%s' (according to master host:port).", name());
|
||||
@ -1921,14 +1920,14 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
") matches an existing slave connection on '%s'.";
|
||||
ignore_reason = string_printf(format, master_id, name());
|
||||
}
|
||||
else if (my_slave_conn.master_host == slave_conn.master_host
|
||||
&& my_slave_conn.master_port == slave_conn.master_port)
|
||||
else if (my_slave_conn.settings.master_endpoint == slave_conn.settings.master_endpoint)
|
||||
{
|
||||
accepted = false;
|
||||
ignore_reason = string_printf("its Master_Host (%s) and Master_Port (%i) match "
|
||||
"an existing slave connection on %s.",
|
||||
slave_conn.master_host.c_str(), slave_conn.master_port,
|
||||
name());
|
||||
const auto& endpoint = slave_conn.settings.master_endpoint;
|
||||
ignore_reason = string_printf(
|
||||
"its Master_Host (%s) and Master_Port (%i) match an existing "
|
||||
"slave connection on %s.",
|
||||
endpoint.host().c_str(), endpoint.port(), name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1944,29 +1943,29 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
std::set<string> connection_names;
|
||||
for (const auto& conn : m_slave_status)
|
||||
{
|
||||
connection_names.insert(conn.name);
|
||||
connection_names.insert(conn.settings.name);
|
||||
}
|
||||
|
||||
// Helper function which checks that a connection name is unique and modifies it if not.
|
||||
auto check_modify_conn_name = [this, &connection_names](SlaveStatus* slave_conn) -> bool {
|
||||
auto check_modify_conn_name = [this, &connection_names](SlaveStatus::Settings* conn_settings) -> bool {
|
||||
bool name_is_unique = false;
|
||||
if (connection_names.count(slave_conn->name) > 0)
|
||||
string conn_name = conn_settings->name;
|
||||
if (connection_names.count(conn_name) > 0)
|
||||
{
|
||||
// If the name is used, generate a name using the host:port of the master,
|
||||
// it should be unique.
|
||||
string second_try = string_printf("To [%s]:%i",
|
||||
slave_conn->master_host.c_str(), slave_conn->master_port);
|
||||
string second_try = "To " + conn_settings->master_endpoint.to_string();
|
||||
if (connection_names.count(second_try) > 0)
|
||||
{
|
||||
// Even this one exists, something is really wrong. Give up.
|
||||
MXS_ERROR("Could not generate a unique connection name for '%s': both '%s' and '%s' are "
|
||||
"already taken.", name(), slave_conn->name.c_str(), second_try.c_str());
|
||||
"already taken.", name(), conn_name.c_str(), second_try.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_WARNING("A slave connection with name '%s' already exists on '%s', using generated "
|
||||
"name '%s' instead.", slave_conn->name.c_str(), name(), second_try.c_str());
|
||||
slave_conn->name = second_try;
|
||||
"name '%s' instead.", conn_name.c_str(), name(), second_try.c_str());
|
||||
conn_settings->name = second_try;
|
||||
name_is_unique = true;
|
||||
}
|
||||
}
|
||||
@ -1985,11 +1984,12 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
string ignore_reason;
|
||||
if (conn_can_be_merged(slave_conn, &ignore_reason))
|
||||
{
|
||||
if (check_modify_conn_name(&slave_conn))
|
||||
auto& conn_settings = slave_conn.settings;
|
||||
if (check_modify_conn_name(&conn_settings))
|
||||
{
|
||||
if (create_start_slave(op, slave_conn))
|
||||
if (create_start_slave(op, conn_settings))
|
||||
{
|
||||
connection_names.insert(slave_conn.name);
|
||||
connection_names.insert(conn_settings.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2005,7 +2005,7 @@ bool MariaDBServer::merge_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
{
|
||||
mxb_assert(!ignore_reason.empty());
|
||||
MXS_WARNING("%s was ignored when promoting '%s' because %s",
|
||||
slave_conn.to_short_string().c_str(), name(), ignore_reason.c_str());
|
||||
slave_conn.settings.to_string().c_str(), name(), ignore_reason.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2023,27 +2023,27 @@ bool MariaDBServer::copy_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
string reason_not_copied;
|
||||
if (slave_conn.should_be_copied(&reason_not_copied))
|
||||
{
|
||||
// Any slave connection that was going to this server itself are instead directed
|
||||
// Any slave connection that was going to this server itself is instead directed
|
||||
// to the replacement server.
|
||||
bool ok_to_copy = true;
|
||||
if (slave_conn.master_server_id == m_server_id)
|
||||
{
|
||||
if (replacement)
|
||||
{
|
||||
slave_conn.master_host = replacement->m_server_base->server->address;
|
||||
slave_conn.master_port = replacement->m_server_base->server->port;
|
||||
slave_conn.settings.master_endpoint = EndPoint(replacement->m_server_base->server);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is only possible if replication is configured wrong and we are
|
||||
// undoing a switchover demotion.
|
||||
MXB_WARNING("Server id:s of '%s' and [%s]:%i are identical, not copying the connection "
|
||||
ok_to_copy = false;
|
||||
MXB_WARNING("Server id:s of '%s' and %s are identical, not copying the connection "
|
||||
"to '%s'.",
|
||||
name(), slave_conn.master_host.c_str(), slave_conn.master_port, name());
|
||||
name(), slave_conn.settings.master_endpoint.to_string().c_str(), name());
|
||||
}
|
||||
}
|
||||
|
||||
if (ok_to_copy && !create_start_slave(op, slave_conn))
|
||||
if (ok_to_copy && !create_start_slave(op, slave_conn.settings))
|
||||
{
|
||||
start_slave_error = true;
|
||||
}
|
||||
@ -2051,44 +2051,44 @@ bool MariaDBServer::copy_slave_conns(GeneralOpData& op, const SlaveStatusArray&
|
||||
else
|
||||
{
|
||||
MXS_WARNING("%s was not copied to '%s' because %s",
|
||||
slave_conn.to_short_string().c_str(), name(), reason_not_copied.c_str());
|
||||
slave_conn.settings.to_string().c_str(), name(), reason_not_copied.c_str());
|
||||
}
|
||||
}
|
||||
return !start_slave_error;
|
||||
}
|
||||
|
||||
bool MariaDBServer::create_start_slave(GeneralOpData& op, const SlaveStatus& slave_conn)
|
||||
bool MariaDBServer::create_start_slave(GeneralOpData& op, const SlaveStatus::Settings& conn_settings)
|
||||
{
|
||||
maxbase::Duration& time_remaining = op.time_remaining;
|
||||
StopWatch timer;
|
||||
string error_msg;
|
||||
bool success = false;
|
||||
SlaveStatus new_conn = slave_conn;
|
||||
new_conn.owning_server = name();
|
||||
string change_master = generate_change_master_cmd(op, new_conn);
|
||||
|
||||
SlaveStatus::Settings new_settings(conn_settings.name, conn_settings.master_endpoint, name());
|
||||
string change_master = generate_change_master_cmd(new_settings);
|
||||
bool conn_created = execute_cmd_time_limit(change_master, time_remaining, &error_msg);
|
||||
time_remaining -= timer.restart();
|
||||
if (conn_created)
|
||||
{
|
||||
string start_slave = string_printf("START SLAVE '%s';", new_conn.name.c_str());
|
||||
string start_slave = string_printf("START SLAVE '%s';", new_settings.name.c_str());
|
||||
bool slave_started = execute_cmd_time_limit(start_slave, time_remaining, &error_msg);
|
||||
time_remaining -= timer.restart();
|
||||
if (slave_started)
|
||||
{
|
||||
success = true;
|
||||
MXS_NOTICE("%s created and started.", new_conn.to_short_string().c_str());
|
||||
MXS_NOTICE("%s created and started.", new_settings.to_string().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("%s could not be started: %s",
|
||||
new_conn.to_short_string().c_str(), error_msg.c_str());
|
||||
new_settings.to_string().c_str(), error_msg.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This may currently print out passwords.
|
||||
MXS_ERROR("%s could not be created: %s",
|
||||
new_conn.to_short_string().c_str(), error_msg.c_str());
|
||||
new_settings.to_string().c_str(), error_msg.c_str());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@ -2096,16 +2096,16 @@ bool MariaDBServer::create_start_slave(GeneralOpData& op, const SlaveStatus& sla
|
||||
/**
|
||||
* Generate a CHANGE MASTER TO-query.
|
||||
*
|
||||
* @param op Operation descriptor, required for username and password
|
||||
* @param slave_conn Existing slave connection to emulate
|
||||
* @param conn_settings Existing slave connection settings to emulate
|
||||
* @return Generated query
|
||||
*/
|
||||
string MariaDBServer::generate_change_master_cmd(GeneralOpData& op, const SlaveStatus& slave_conn)
|
||||
string MariaDBServer::generate_change_master_cmd(const SlaveStatus::Settings& conn_settings)
|
||||
{
|
||||
string change_cmd;
|
||||
change_cmd += string_printf("CHANGE MASTER '%s' TO MASTER_HOST = '%s', MASTER_PORT = %i, ",
|
||||
slave_conn.name.c_str(),
|
||||
slave_conn.master_host.c_str(), slave_conn.master_port);
|
||||
conn_settings.name.c_str(),
|
||||
conn_settings.master_endpoint.host().c_str(),
|
||||
conn_settings.master_endpoint.port());
|
||||
change_cmd += "MASTER_USE_GTID = current_pos, ";
|
||||
if (m_settings.replication_ssl)
|
||||
{
|
||||
@ -2122,8 +2122,9 @@ string MariaDBServer::generate_change_master_cmd(GeneralOpData& op, const SlaveS
|
||||
return change_cmd;
|
||||
}
|
||||
|
||||
bool MariaDBServer::redirect_existing_slave_conn(GeneralOpData& op, const SlaveStatus& old_conn,
|
||||
const MariaDBServer* new_master)
|
||||
bool
|
||||
MariaDBServer::redirect_existing_slave_conn(GeneralOpData& op, const SlaveStatus::Settings& conn_settings,
|
||||
const MariaDBServer* new_master)
|
||||
{
|
||||
auto error_out = op.error_out;
|
||||
maxbase::Duration& time_remaining = op.time_remaining;
|
||||
@ -2131,21 +2132,21 @@ bool MariaDBServer::redirect_existing_slave_conn(GeneralOpData& op, const SlaveS
|
||||
bool success = false;
|
||||
|
||||
// First, just stop the slave connection.
|
||||
bool stopped = stop_slave_conn(old_conn.name, StopMode::STOP_ONLY, time_remaining, error_out);
|
||||
string conn_name = conn_settings.name;
|
||||
bool stopped = stop_slave_conn(conn_name, StopMode::STOP_ONLY, time_remaining, error_out);
|
||||
time_remaining -= timer.restart();
|
||||
if (stopped)
|
||||
{
|
||||
SlaveStatus modified_conn = old_conn;
|
||||
SERVER* target_server = new_master->m_server_base->server;
|
||||
modified_conn.master_host = target_server->address;
|
||||
modified_conn.master_port = target_server->port;
|
||||
string change_master = generate_change_master_cmd(op, modified_conn);
|
||||
SlaveStatus::Settings modified_settings = conn_settings;
|
||||
modified_settings.master_endpoint = EndPoint(new_master->m_server_base->server);
|
||||
string change_master = generate_change_master_cmd(modified_settings);
|
||||
|
||||
string error_msg;
|
||||
bool changed = execute_cmd_time_limit(change_master, time_remaining, &error_msg);
|
||||
time_remaining -= timer.restart();
|
||||
if (changed)
|
||||
{
|
||||
string start = string_printf("START SLAVE '%s';", old_conn.name.c_str());
|
||||
string start = string_printf("START SLAVE '%s';", conn_name.c_str());
|
||||
bool started = execute_cmd_time_limit(start, time_remaining, &error_msg);
|
||||
time_remaining -= timer.restart();
|
||||
if (started)
|
||||
@ -2156,16 +2157,16 @@ bool MariaDBServer::redirect_existing_slave_conn(GeneralOpData& op, const SlaveS
|
||||
{
|
||||
PRINT_MXS_JSON_ERROR(error_out,
|
||||
"%s could not be started: %s",
|
||||
modified_conn.to_short_string().c_str(), error_msg.c_str());
|
||||
modified_settings.to_string().c_str(), error_msg.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This may currently print out passwords.
|
||||
PRINT_MXS_JSON_ERROR(error_out,
|
||||
"%s could not be redirected to [%s]:%i: %s",
|
||||
old_conn.to_short_string().c_str(),
|
||||
modified_conn.master_host.c_str(), modified_conn.master_port,
|
||||
"%s could not be redirected to %s: %s",
|
||||
conn_settings.to_string().c_str(),
|
||||
modified_settings.master_endpoint.to_string().c_str(),
|
||||
error_msg.c_str());
|
||||
}
|
||||
} // 'stop_slave_conn' prints its own errors
|
||||
|
@ -395,11 +395,11 @@ public:
|
||||
* Redirect the slave connection going to old master to replicate from new master.
|
||||
*
|
||||
* @param op Operation descriptor
|
||||
* @param old_conn The connection which is redirected
|
||||
* @param conn_settings The connection which is redirected
|
||||
* @param new_master The new master for the redirected connection
|
||||
* @return True on success
|
||||
*/
|
||||
bool redirect_existing_slave_conn(GeneralOpData& op, const SlaveStatus& old_conn,
|
||||
bool redirect_existing_slave_conn(GeneralOpData& op, const SlaveStatus::Settings& conn_settings,
|
||||
const MariaDBServer* new_master);
|
||||
|
||||
/**
|
||||
@ -422,10 +422,10 @@ public:
|
||||
* Create a new slave connection on the server and start it.
|
||||
*
|
||||
* @param op Operation descriptor
|
||||
* @param slave_conn Existing connection to emulate
|
||||
* @param conn_settings Existing connection to emulate
|
||||
* @return True on success
|
||||
*/
|
||||
bool create_start_slave(GeneralOpData& op, const SlaveStatus& slave_conn);
|
||||
bool create_start_slave(GeneralOpData& op, const SlaveStatus::Settings& conn_settings);
|
||||
|
||||
/**
|
||||
* Kill the connections of any super-users except for the monitor itself.
|
||||
@ -587,7 +587,7 @@ private:
|
||||
|
||||
bool set_read_only(ReadOnlySetting value, maxbase::Duration time_limit, json_t** error_out);
|
||||
bool merge_slave_conns(GeneralOpData& op, const SlaveStatusArray& conns_to_merge);
|
||||
std::string generate_change_master_cmd(GeneralOpData& op, const SlaveStatus& slave_conn);
|
||||
std::string generate_change_master_cmd(const SlaveStatus::Settings& conn_settings);
|
||||
|
||||
bool update_enabled_events();
|
||||
|
||||
|
@ -30,19 +30,23 @@ const char CONNECTING[] = "Connecting";
|
||||
const char NO[] = "No";
|
||||
}
|
||||
|
||||
SlaveStatus::SlaveStatus(const std::string& owner)
|
||||
: settings(owner)
|
||||
{
|
||||
}
|
||||
|
||||
string SlaveStatus::to_string() const
|
||||
{
|
||||
// Print all of this on the same line to make things compact. Are the widths reasonable? The format is
|
||||
// not quite array-like since usually there is just one row. May be changed later.
|
||||
// Form the components of the line.
|
||||
string host_port = string_printf("[%s]:%d", master_host.c_str(), master_port);
|
||||
string running_states = string_printf("%s/%s",
|
||||
slave_io_to_string(slave_io_running).c_str(),
|
||||
slave_sql_running ? "Yes" : "No");
|
||||
|
||||
string rval = string_printf(
|
||||
" Host: %22s, IO/SQL running: %7s, Master ID: %4" PRId64 ", Gtid_IO_Pos: %s, R.Lag: %d",
|
||||
host_port.c_str(),
|
||||
settings.master_endpoint.to_string().c_str(),
|
||||
running_states.c_str(),
|
||||
master_server_id,
|
||||
gtid_io_pos.to_string().c_str(),
|
||||
@ -50,26 +54,26 @@ string SlaveStatus::to_string() const
|
||||
return rval;
|
||||
}
|
||||
|
||||
string SlaveStatus::to_short_string() const
|
||||
std::string SlaveStatus::Settings::to_string() const
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
return string_printf("Slave connection from %s to [%s]:%i",
|
||||
owning_server.c_str(), master_host.c_str(), master_port);
|
||||
return string_printf("Slave connection from %s to %s",
|
||||
m_owner.c_str(), master_endpoint.to_string().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
return string_printf("Slave connection '%s' from %s to [%s]:%i",
|
||||
name.c_str(), owning_server.c_str(), master_host.c_str(), master_port);
|
||||
return string_printf("Slave connection '%s' from %s to %s",
|
||||
name.c_str(), m_owner.c_str(), master_endpoint.to_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
json_t* SlaveStatus::to_json() const
|
||||
{
|
||||
json_t* result = json_object();
|
||||
json_object_set_new(result, "connection_name", json_string(name.c_str()));
|
||||
json_object_set_new(result, "master_host", json_string(master_host.c_str()));
|
||||
json_object_set_new(result, "master_port", json_integer(master_port));
|
||||
json_object_set_new(result, "connection_name", json_string(settings.name.c_str()));
|
||||
json_object_set_new(result, "master_host", json_string(settings.master_endpoint.host().c_str()));
|
||||
json_object_set_new(result, "master_port", json_integer(settings.master_endpoint.port()));
|
||||
json_object_set_new(result,
|
||||
"slave_io_running",
|
||||
json_string(slave_io_to_string(slave_io_running).c_str()));
|
||||
@ -82,6 +86,7 @@ json_t* SlaveStatus::to_json() const
|
||||
json_object_set_new(result, "gtid_io_pos", json_string(gtid_io_pos.to_string().c_str()));
|
||||
return result;
|
||||
}
|
||||
|
||||
SlaveStatus::slave_io_running_t SlaveStatus::slave_io_from_string(const std::string& str)
|
||||
{
|
||||
slave_io_running_t rval = SLAVE_IO_NO;
|
||||
@ -155,6 +160,23 @@ bool SlaveStatus::should_be_copied(string* ignore_reason_out) const
|
||||
return accepted;
|
||||
}
|
||||
|
||||
SlaveStatus::Settings::Settings(const std::string& name, const EndPoint& target, const std::string& owner)
|
||||
: name(name)
|
||||
, master_endpoint(target)
|
||||
, m_owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
SlaveStatus::Settings::Settings(const std::string& name, const SERVER* target)
|
||||
: Settings(name, EndPoint(target), "")
|
||||
{
|
||||
}
|
||||
|
||||
SlaveStatus::Settings::Settings(const std::string& owner)
|
||||
: m_owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
ServerOperation::ServerOperation(MariaDBServer* target, bool was_is_master,
|
||||
const SlaveStatusArray& conns_to_copy,
|
||||
const EventNameSet& events_to_enable)
|
||||
@ -416,3 +438,28 @@ GtidList::DomainList GtidList::domains() const
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
EndPoint::EndPoint(const std::string& host, int port)
|
||||
: m_host(host, port)
|
||||
{
|
||||
}
|
||||
|
||||
EndPoint::EndPoint(const SERVER* server)
|
||||
: EndPoint(server->address, server->port)
|
||||
{
|
||||
}
|
||||
|
||||
EndPoint::EndPoint()
|
||||
: EndPoint("", PORT_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
bool EndPoint::operator==(const EndPoint& rhs) const
|
||||
{
|
||||
return m_host.address() == rhs.m_host.address() && m_host.port() == rhs.m_host.port();
|
||||
}
|
||||
|
||||
std::string EndPoint::to_string() const
|
||||
{
|
||||
return "[" + m_host.address() + "]:" + std::to_string(m_host.port());
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <maxbase/host.hh>
|
||||
#include <maxbase/stopwatch.hh>
|
||||
#include <maxscale/server.hh>
|
||||
|
||||
@ -168,10 +169,43 @@ private:
|
||||
std::vector<Gtid> m_triplets;
|
||||
};
|
||||
|
||||
// Helper class for host-port combinations
|
||||
class EndPoint
|
||||
{
|
||||
public:
|
||||
EndPoint(const std::string& host, int port);
|
||||
explicit EndPoint(const SERVER* server);
|
||||
EndPoint();
|
||||
|
||||
std::string host() const
|
||||
{
|
||||
return m_host.address();
|
||||
}
|
||||
|
||||
int port() const
|
||||
{
|
||||
return m_host.port();
|
||||
}
|
||||
|
||||
bool operator==(const EndPoint& rhs) const;
|
||||
bool operator!=(const EndPoint& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
private:
|
||||
mxb::Host m_host; /* Address and port */
|
||||
};
|
||||
|
||||
|
||||
// Contains data returned by one row of SHOW ALL SLAVES STATUS
|
||||
class SlaveStatus
|
||||
{
|
||||
public:
|
||||
explicit SlaveStatus(const std::string& owner);
|
||||
|
||||
enum slave_io_running_t
|
||||
{
|
||||
SLAVE_IO_YES,
|
||||
@ -179,16 +213,38 @@ public:
|
||||
SLAVE_IO_NO,
|
||||
};
|
||||
|
||||
std::string owning_server; /* Server name of the owner */
|
||||
bool seen_connected = false; /* Has this slave connection been seen connected,
|
||||
* meaning that the master server id is correct? */
|
||||
std::string name; /* Slave connection name. Must be unique for
|
||||
* the server.*/
|
||||
// Helper class for containing slave connection settings. These are modifiable by
|
||||
// a CHANGE MASTER TO-command and should not change on their own. The owning server
|
||||
// is included to simplify log message creation.
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings(const std::string& name, const EndPoint& target, const std::string& owner);
|
||||
Settings(const std::string& name, const SERVER* target);
|
||||
explicit Settings(const std::string& owner);
|
||||
|
||||
/**
|
||||
* Create a short description in the form of "Slave connection from <owner> to <[host]:port>."
|
||||
*
|
||||
* @return Description
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
std::string name; /* Slave connection name. Must be unique for the server. */
|
||||
EndPoint master_endpoint; /* Master server address & port */
|
||||
|
||||
private:
|
||||
std::string m_owner; /* Name of the owning server. Used for logging. */
|
||||
};
|
||||
|
||||
Settings settings; /* User-defined settings for the slave connection. */
|
||||
|
||||
bool seen_connected = false; /* Has this slave connection been seen connected,
|
||||
* meaning that the master server id is correct? */
|
||||
|
||||
int64_t master_server_id = SERVER_ID_UNKNOWN; /* The master's server_id value. Valid ids are
|
||||
* 32bit unsigned. -1 is unread/error. */
|
||||
std::string master_host; /* Master server host name. */
|
||||
int master_port = PORT_UNKNOWN; /* Master server port. */
|
||||
slave_io_running_t slave_io_running = SLAVE_IO_NO; /* Slave I/O thread running state: * "Yes",
|
||||
slave_io_running_t slave_io_running = SLAVE_IO_NO; /* Slave I/O thread running state: "Yes",
|
||||
* "Connecting" or "No" */
|
||||
bool slave_sql_running = false; /* Slave SQL thread running state, true if "Yes" */
|
||||
GtidList gtid_io_pos; /* Gtid I/O position of the slave thread. */
|
||||
@ -204,13 +260,6 @@ public:
|
||||
std::string to_string() const;
|
||||
json_t* to_json() const;
|
||||
|
||||
/**
|
||||
* Create a short description in the form of "Slave connection from <slave> to <master>"
|
||||
*
|
||||
* @return Description
|
||||
*/
|
||||
std::string to_short_string() const;
|
||||
|
||||
static slave_io_running_t slave_io_from_string(const std::string& str);
|
||||
static std::string slave_io_to_string(slave_io_running_t slave_io);
|
||||
bool should_be_copied(std::string* ignore_reason_out) const;
|
||||
|
@ -213,13 +213,13 @@ void MariaDBMonitor::Test::add_replication(EdgeArray edges)
|
||||
break;
|
||||
}
|
||||
|
||||
SlaveStatus ss;
|
||||
MariaDBServer* slave = get_server(slave_id);
|
||||
SlaveStatus ss(slave->name());
|
||||
ss.slave_io_running = SlaveStatus::SLAVE_IO_YES;
|
||||
ss.slave_sql_running = true;
|
||||
if (m_use_hostnames)
|
||||
{
|
||||
ss.master_host = create_hostname(master_id);
|
||||
ss.master_port = master_id;
|
||||
ss.settings.master_endpoint = EndPoint(create_hostname(master_id), master_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -227,7 +227,6 @@ void MariaDBMonitor::Test::add_replication(EdgeArray edges)
|
||||
ss.seen_connected = true;
|
||||
}
|
||||
|
||||
MariaDBServer* slave = get_server(slave_id);
|
||||
slave->m_slave_status.push_back(ss);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user