diff --git a/maxctrl/lib/common.js b/maxctrl/lib/common.js index ce7459075..b3555c8f1 100644 --- a/maxctrl/lib/common.js +++ b/maxctrl/lib/common.js @@ -50,9 +50,14 @@ module.exports = function() { // No password given, ask it from the command line if (argv.p == '') { - argv.p = readlineSync.question('Enter password: ', { - hideEchoBack: true - }) + if (process.stdin.isTTY) { + argv.p = readlineSync.question('Enter password: ', { + hideEchoBack: true + }) + } else { + var line = fs.readFileSync(0) + argv.p = line.toString().trim() + } } // Split the hostnames, separated by commas diff --git a/maxscale-system-test/mariadb_nodes.cpp b/maxscale-system-test/mariadb_nodes.cpp index 0dbd6b9ee..6ae51dec7 100644 --- a/maxscale-system-test/mariadb_nodes.cpp +++ b/maxscale-system-test/mariadb_nodes.cpp @@ -1145,16 +1145,13 @@ int Mariadb_nodes::truncate_mariadb_logs() int local_result = 0; for (int node = 0; node < N; node++) { - char sys[PATH_MAX + 1500]; if (strcmp(IP[node], "127.0.0.1") != 0) { - snprintf(sys, - sizeof(sys), - "ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s 'sudo truncate /var/lib/mysql/*.err --size 0;sudo rm -f /etc/my.cnf.d/binlog_enc*\' &", - sshkey[node], - access_user[node], - IP[node]); - local_result += system(sys); + local_result += ssh_node_f(node, true, + "truncate -s 0 /var/lib/mysql/*.err;" + "truncate -s 0 /var/log/syslog;" + "truncate -s 0 /var/log/messages;" + "rm -f /etc/my.cnf.d/binlog_enc*;"); } } return local_result; diff --git a/maxscale-system-test/maxscales.cpp b/maxscale-system-test/maxscales.cpp index 6ba1b30b9..e7aadbf58 100644 --- a/maxscale-system-test/maxscales.cpp +++ b/maxscale-system-test/maxscales.cpp @@ -247,7 +247,11 @@ int Maxscales::restart_maxscale(int m) if (use_valgrind) { res = stop_maxscale(m); - res += start_maxscale(m); + res = ssh_node_f(m, false, + "sudo --user=maxscale valgrind --leak-check=full --show-leak-kinds=all " + "--log-file=/%s/valgrind%02d.log --trace-children=yes " + "--track-origins=yes /usr/bin/maxscale", maxscale_log_dir[m], valgring_log_num); + valgring_log_num++; } else { diff --git a/maxscale-system-test/testconnections.cpp b/maxscale-system-test/testconnections.cpp index a0b25ea54..bdb44e0c0 100644 --- a/maxscale-system-test/testconnections.cpp +++ b/maxscale-system-test/testconnections.cpp @@ -791,12 +791,16 @@ void TestConnections::init_maxscale(int m) true, "cp maxscale.cnf %s;" "iptables -F INPUT;" - "rm -rf %s/*.log /tmp/core* /dev/shm/* /var/lib/maxscale/maxscale.cnf.d/ /var/lib/maxscale/*;" - "%s" - "maxctrl api get maxscale/debug/monitor_wait", + "rm -rf %s/*.log /tmp/core* /dev/shm/* /var/lib/maxscale/maxscale.cnf.d/ /var/lib/maxscale/*;", maxscales->maxscale_cnf[m], - maxscales->maxscale_log_dir[m], - maxscale::start ? "service maxscale restart;" : ""); + maxscales->maxscale_log_dir[m]); + if (maxscale::start) + { + maxscales->restart_maxscale(m); + maxscales->ssh_node_f(m, + true, + "maxctrl api get maxscale/debug/monitor_wait"); + } } void TestConnections::copy_one_mariadb_log(int i, std::string filename) diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index ae69bc5b0..a46f97eb8 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -83,7 +83,7 @@ endif() # Using initial-exec instead of the default global-dynamic tls-model # reduces the cost of using thread-local variables in dynamic libraries. -target_compile_options(maxscale-common PUBLIC "-ftls-model=initial-exec") +target_compile_options(maxscale-common PRIVATE "-ftls-model=initial-exec") add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd jansson maxbase) set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0") diff --git a/server/core/backend.cc b/server/core/backend.cc index 2868a67d6..f45bb077c 100644 --- a/server/core/backend.cc +++ b/server/core/backend.cc @@ -47,7 +47,7 @@ Backend::~Backend() void Backend::close(close_type type) { - mxb_assert(m_dcb->n_close == 0); + mxb_assert(m_dcb && m_dcb->n_close == 0); if (!m_closed) { @@ -180,7 +180,7 @@ void Backend::set_state(backend_state state) bool Backend::connect(MXS_SESSION* session, SessionCommandList* sescmd) { - mxb_assert(!in_use()); + mxb_assert(!in_use() && m_dcb == nullptr); bool rval = false; if ((m_dcb = dcb_connect(m_backend->server, session, m_backend->server->protocol().c_str()))) diff --git a/server/core/config.cc b/server/core/config.cc index 312daed48..97b68c870 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -313,7 +313,7 @@ const MXS_MODULE_PARAM config_service_params[] = {CN_LOG_AUTH_WARNINGS, MXS_MODULE_PARAM_BOOL, "true"}, {CN_RETRY_ON_FAILURE, MXS_MODULE_PARAM_BOOL, "true"}, {CN_SESSION_TRACK_TRX_STATE, MXS_MODULE_PARAM_BOOL, "false"}, - {CN_RETAIN_LAST_STATEMENTS, MXS_MODULE_PARAM_COUNT, "0"}, + {CN_RETAIN_LAST_STATEMENTS, MXS_MODULE_PARAM_COUNT, "-1"}, {CN_CLUSTER, MXS_MODULE_PARAM_STRING}, {NULL} }; @@ -4869,36 +4869,6 @@ bool config_parse_disk_space_threshold(SERVER::DiskSpaceLimits* pDisk_space_thre return success; } -void dump_if_changed(const MXS_MODULE_PARAM* params, - int file, - const std::string& key, - const std::string& value) -{ - for (int i = 0; params[i].name; i++) - { - if (params[i].name == key) - { - /** - * This detects only exact matches, not ones that are logically equivalent - * but lexicographically different e.g. 1 and true. This might not - * be a bad thing: it'll distinct user defined values from defaults. - */ - - if (!params[i].default_value || value != params[i].default_value) - { - if (dprintf(file, "%s=%s\n", key.c_str(), value.c_str()) == -1) - { - MXS_ERROR("Failed to serialize service value: %d, %s", - errno, - mxs_strerror(errno)); - } - } - - break; - } - } -} - void dump_param_list(int file, const MXS_CONFIG_PARAMETER* list, const std::unordered_set& ignored, @@ -4911,8 +4881,10 @@ void dump_param_list(int file, const string& value = p.second; if (ignored.count(name) == 0 && !value.empty()) { - dump_if_changed(common_params, file, name, value); - dump_if_changed(module_params, file, name, value); + if (dprintf(file, "%s=%s\n", name.c_str(), value.c_str()) == -1) + { + MXS_ERROR("Failed to serialize service value: %d, %s", errno, mxs_strerror(errno)); + } } } } diff --git a/server/core/dcb.cc b/server/core/dcb.cc index e89a9cb43..98a8f47cb 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -1942,7 +1942,7 @@ static void dcb_hangup_foreach_worker(MXB_WORKER* worker, struct SERVER* server) for (DCB* dcb = this_unit.all_dcbs[id]; dcb; dcb = dcb->thread.next) { - if (dcb->state == DCB_STATE_POLLING && dcb->server && dcb->server == server) + if (dcb->state == DCB_STATE_POLLING && dcb->server && dcb->server == server && dcb->n_close == 0) { if (!dcb->dcb_errhandle_called) { diff --git a/server/core/filter.cc b/server/core/filter.cc index 73f52d876..4b60ca0a9 100644 --- a/server/core/filter.cc +++ b/server/core/filter.cc @@ -517,12 +517,13 @@ static bool create_filter_config(const SFilterDef& filter, const char* filename) dprintf(file, "[%s]\n", filter->name.c_str()); dprintf(file, "%s=%s\n", CN_TYPE, CN_FILTER); + dprintf(file, "%s=%s\n", CN_MODULE, filter->module.c_str()); const MXS_MODULE* mod = get_module(filter->module.c_str(), NULL); mxb_assert(mod); MXS_MODULE_PARAM no_common_params = {}; - dump_param_list(file, filter->parameters, {CN_TYPE}, &no_common_params, mod->parameters); + dump_param_list(file, filter->parameters, {CN_TYPE, CN_MODULE}, &no_common_params, mod->parameters); close(file); return true; diff --git a/server/core/service.cc b/server/core/service.cc index 2685856c6..1e0f0de5a 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -224,15 +224,7 @@ Service::Service(const std::string& name, log_auth_warnings = params->get_bool(CN_LOG_AUTH_WARNINGS); strip_db_esc = params->get_bool(CN_STRIP_DB_ESC); session_track_trx_state = params->get_bool(CN_SESSION_TRACK_TRX_STATE); - - if (params->contains(CN_RETAIN_LAST_STATEMENTS)) - { - retain_last_statements = params->get_integer(CN_RETAIN_LAST_STATEMENTS); - } - else - { - retain_last_statements = -1; // Indicates that it has not been set. - } + retain_last_statements = params->get_integer(CN_RETAIN_LAST_STATEMENTS); /** * At service start last update is set to config->users_refresh_time seconds earlier. diff --git a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc index 79e81f3b5..26a5f1508 100644 --- a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc +++ b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc @@ -1335,6 +1335,7 @@ static int gw_error_backend_event(DCB* dcb) */ static int gw_backend_hangup(DCB* dcb) { + mxb_assert(dcb->n_close == 0); MXS_SESSION* session = dcb->session; if (!dcb->persistentstart) diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index 23937e64e..6557f7a74 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -1111,8 +1111,6 @@ static int gw_read_normal_data(DCB* dcb, GWBUF* read_buffer, int nbytes_read) // is thread and not session specific. qc_set_sql_mode(static_cast(session->client_protocol_data)); } - - session_retain_statement(session, read_buffer); } /** Update the current protocol command being executed */ else if (!process_client_commands(dcb, nbytes_read, &read_buffer)) @@ -1632,6 +1630,7 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF { // TODO: Do this only when RCAP_TYPE_CONTIGUOUS_INPUT is requested packetbuf = gwbuf_make_contiguous(packetbuf); + session_retain_statement(session, packetbuf); MySQLProtocol* proto = (MySQLProtocol*)session->client_dcb->protocol; diff --git a/server/modules/routing/readwritesplit/rwsplitsession.cc b/server/modules/routing/readwritesplit/rwsplitsession.cc index d290c2860..818d6d742 100644 --- a/server/modules/routing/readwritesplit/rwsplitsession.cc +++ b/server/modules/routing/readwritesplit/rwsplitsession.cc @@ -226,7 +226,7 @@ bool RWSplitSession::route_stored_query() * to wait for a response before attempting another reroute */ while (m_query_queue) { - MXS_INFO("Routing stored queries"); + MXS_INFO(">>> Routing stored queries"); GWBUF* query_queue = modutil_get_next_MySQL_packet(&m_query_queue); query_queue = gwbuf_make_contiguous(query_queue); mxb_assert(query_queue); @@ -244,6 +244,9 @@ bool RWSplitSession::route_stored_query() GWBUF* temp_storage = m_query_queue; m_query_queue = NULL; + // The query needs to be explicitly parsed as it was processed multiple times + qc_parse(query_queue, QC_COLLECT_ALL); + // TODO: Move the handling of queued queries to the client protocol // TODO: module where the command tracking is done automatically. uint8_t cmd = mxs_mysql_get_command(query_queue); @@ -255,6 +258,8 @@ bool RWSplitSession::route_stored_query() MXS_ERROR("Failed to route queued query."); } + MXS_INFO("<<< Stored queries routed"); + if (m_query_queue == NULL) { /** Query successfully routed and no responses are expected */