From 804991404ea2fc1462089982de77a7c56af8a710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sat, 11 Aug 2018 14:18:48 +0300 Subject: [PATCH] Rewrite stale_slaves The behavior of mariadbmon was changed so that it better understands slaves attempting to replicate. Rewrote the test to accommodate the change in behavior and take the opportunity to use newer code. --- maxscale-system-test/CMakeLists.txt | 2 +- .../cnf/maxscale.cnf.template.stale_slaves | 59 ++++++++ maxscale-system-test/mariadb_func.h | 6 + maxscale-system-test/stale_slaves.cpp | 135 +++++++----------- 4 files changed, 121 insertions(+), 81 deletions(-) create mode 100644 maxscale-system-test/cnf/maxscale.cnf.template.stale_slaves diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index bbae57b10..743649930 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -872,7 +872,7 @@ add_test_derived(ssl sql_queries ssl LABELS maxscale readwritesplit REPL_BACKEND #add_test_script(ssl_load_galera load_balancing_galera ssl_load_galera LABELS maxscale readwritesplit GALERA_BACKEND) # Testing slaves who have lost their master and how MaxScale works with them -add_test_executable(stale_slaves.cpp stale_slaves replication LABELS mysqlmon REPL_BACKEND) +add_test_executable(stale_slaves.cpp stale_slaves stale_slaves LABELS mysqlmon REPL_BACKEND) # Run sysbech test and block one slave during test execution add_test_executable(sysbench_kill_slave.cpp sysbench_kill_slave replication LABELS UNSTABLE HEAVY REPL_BACKEND) diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.stale_slaves b/maxscale-system-test/cnf/maxscale.cnf.template.stale_slaves new file mode 100644 index 000000000..9849e60cb --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.stale_slaves @@ -0,0 +1,59 @@ +[maxscale] +threads=###threads### + +[MySQL Monitor] +type=monitor +module=mysqlmon +servers=server1,server2,server3,server4 +user=maxskysql +password=skysql +monitor_interval=1000 +failcount=1 + +[Read Connection Router Slave] +type=service +router=readconnroute +router_options=slave +servers=server1,server2,server3,server4 +user=maxskysql +password=skysql + +[Read Connection Listener Slave] +type=listener +service=Read Connection Router Slave +protocol=MySQLClient +port=4009 + +[CLI] +type=service +router=cli + +[CLI Listener] +type=listener +service=CLI +protocol=maxscaled +socket=default + +[server1] +type=server +address=###node_server_IP_1### +port=###node_server_port_1### +protocol=MySQLBackend + +[server2] +type=server +address=###node_server_IP_2### +port=###node_server_port_2### +protocol=MySQLBackend + +[server3] +type=server +address=###node_server_IP_3### +port=###node_server_port_3### +protocol=MySQLBackend + +[server4] +type=server +address=###node_server_IP_4### +port=###node_server_port_4### +protocol=MySQLBackend diff --git a/maxscale-system-test/mariadb_func.h b/maxscale-system-test/mariadb_func.h index b220844e8..795e8f950 100644 --- a/maxscale-system-test/mariadb_func.h +++ b/maxscale-system-test/mariadb_func.h @@ -295,6 +295,12 @@ public: return get_row(m_conn, q); } + std::string field(std::string q) + { + Row r = get_row(m_conn, q); + return r.empty() ? std::string() : r[0]; + } + const char* error() const { return mysql_error(m_conn); diff --git a/maxscale-system-test/stale_slaves.cpp b/maxscale-system-test/stale_slaves.cpp index 114a467e4..e8af7e454 100644 --- a/maxscale-system-test/stale_slaves.cpp +++ b/maxscale-system-test/stale_slaves.cpp @@ -2,105 +2,80 @@ * @file stale_slaves.cpp Testing slaves who have lost their master and how MaxScale works with them * * When the master server is blocked and slaves lose their master, they should - * still be available for read queries. When a slave with no master fails, it should not - * be assigned slave status again. Once the master comes back, all slaves should get slave - * status if replication is running. + * still be available for read queries. Once the master comes back, all slaves + * should get slave status if replication is running. */ - -#include #include "testconnections.h" +#include +#include +#include + +using namespace std; + int main(int argc, char **argv) { - TestConnections *test = new TestConnections(argc, argv); + TestConnections test(argc, argv); + vector ids; - char server_id[test->repl->N][1024]; - - test->repl->connect(); - /** Get server_id for each node */ - for (int i = 0; i < test->repl->N; i++) + test.repl->connect(); + for (int i = 0; i < test.repl->N; i++) { - sprintf(server_id[i], "%d", test->repl->get_server_id(i)); + ids.push_back(test.repl->get_server_id_str(i)); } - test->tprintf("Block the master and try a read query\n"); - test->repl->block_node(0); - sleep(15); - test->maxscales->connect_readconn_slave(0); - char first_slave[1024]; - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", first_slave); - - int found = -1; - - for (int i = 0; i < test->repl->N; i++) + auto get_id = [&]() { - if (strcmp(server_id[i], first_slave) == 0) + Connection c = test.maxscales->readconn_slave(); + test.assert(c.connect(), "Connection should be OK: %s", c.error()); + string res = c.field("SELECT @@server_id"); + test.assert(!res.empty(), "Field should not be empty: %s", c.error()); + return res; + }; + + auto in_use = [&](string id) + { + for (int i = 0; i < 2 * test.repl->N; i++) { - found = i; - break; + if (get_id() == id) + { + return true; + } } - } - test->add_result(found < 0, "No server with ID '%s' found.", first_slave); + return false; + }; - test->tprintf("Blocking node %d\n", found + 1); - test->repl->block_node(found); - sleep(15); + test.tprintf("Blocking the master and doing a read query"); + test.repl->block_node(0); + test.maxscales->wait_for_monitor(); - test->tprintf("Blocked the slave that replied to us, expecting a different slave\n"); - test->maxscales->connect_readconn_slave(0); - char second_slave[1024]; - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", second_slave); - test->add_result(strcmp(first_slave, second_slave) == 0, - "Server IDs match when they shouldn't: %s - %s", - first_slave, second_slave); + string first = get_id(); + auto it = find(begin(ids), end(ids), first); + test.assert(it != end(ids), "ID should be found"); + int node = distance(begin(ids), it); - test->tprintf("Unblocking the slave that replied\n"); - test->repl->unblock_node(found); - sleep(15); + test.tprintf("Blocking the slave that replied to us"); + test.repl->block_node(node); + test.maxscales->wait_for_monitor(); + test.assert(!in_use(first), "The first slave should not be in use"); - test->tprintf("Unblocked the slave, still expecting a different slave\n"); - test->maxscales->connect_readconn_slave(0); - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", second_slave); - test->add_result(strcmp(first_slave, second_slave) == 0, - "Server IDs match when they shouldn't: %s - %s", - first_slave, second_slave); + test.tprintf("Unblocking all nodes"); + test.repl->unblock_all_nodes(); + test.maxscales->wait_for_monitor(); + test.assert(in_use(first), "The first slave should be in use"); - test->tprintf("Unblocking all nodes\n"); - test->repl->unblock_all_nodes(); - sleep(15); + test.tprintf("Stopping replication on first slave"); + execute_query(test.repl->nodes[node], "STOP SLAVE"); + test.maxscales->wait_for_monitor(); + test.assert(!in_use(first), "The first slave should not be in use"); - test->tprintf("Unblocked all nodes, expecting the server ID of the first slave server\n"); - test->maxscales->connect_readconn_slave(0); - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", second_slave); - test->add_result(strcmp(first_slave, second_slave) != 0, - "Server IDs don't match when they should: %s - %s", - first_slave, second_slave); + test.tprintf("Starting replication on first slave"); + execute_query(test.repl->nodes[node], "START SLAVE"); + test.maxscales->wait_for_monitor(); + test.assert(in_use(first), "The first slave should be in use"); + test.repl->disconnect(); - test->tprintf("Stopping replication on node %d\n", found + 1); - execute_query(test->repl->nodes[found], "stop slave"); - sleep(15); - - test->tprintf("Stopped replication, expecting a different slave\n"); - test->maxscales->connect_readconn_slave(0); - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", second_slave); - test->add_result(strcmp(first_slave, second_slave) == 0, - "Server IDs match when they shouldn't: %s - %s", - first_slave, second_slave); - - test->tprintf("Starting replication on node %d\n", found + 1); - execute_query(test->repl->nodes[found], "start slave"); - sleep(15); - - test->tprintf("Started replication, expecting the server ID of the first slave server\n"); - test->maxscales->connect_readconn_slave(0); - find_field(test->maxscales->conn_slave[0], "SELECT @@server_id", "@@server_id", second_slave); - test->add_result(strcmp(first_slave, second_slave) != 0, - "Server IDs don't match when they should: %s - %s", - first_slave, second_slave); - - int rval = test->global_result; - delete test; - return rval; + return test.global_result; }