diff --git a/BUILD/install_build_deps.sh b/BUILD/install_build_deps.sh index b913d0cd5..7f8709051 100755 --- a/BUILD/install_build_deps.sh +++ b/BUILD/install_build_deps.sh @@ -9,7 +9,7 @@ command -v apt-get if [ $? == 0 ] then # DEB-based distro - + install_libdir=/usr/lib sudo apt-get update sudo apt-get install -y --force-yes dpkg-dev git wget \ @@ -35,6 +35,7 @@ then fi else ## RPM-based distro + install_libdir=/usr/lib64 command -v yum if [ $? != 0 ] @@ -142,7 +143,7 @@ fi mkdir -p jansson/build pushd jansson/build -cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS=-fPIC -DJANSSON_INSTALL_LIB_DIR=/usr/lib64 +cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS=-fPIC -DJANSSON_INSTALL_LIB_DIR=$install_libdir make sudo make install popd diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index 34a68e631..84f55e6bc 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -21,6 +21,7 @@ * MaxScale now supports IPv6 For more details, please refer to: +* [MariaDB MaxScale 2.1.5 Release Notes](Release-Notes/MaxScale-2.1.5-Release-Notes.md) * [MariaDB MaxScale 2.1.4 Release Notes](Release-Notes/MaxScale-2.1.4-Release-Notes.md) * [MariaDB MaxScale 2.1.3 Release Notes](Release-Notes/MaxScale-2.1.3-Release-Notes.md) * [MariaDB MaxScale 2.1.2 Release Notes](Release-Notes/MaxScale-2.1.2-Release-Notes.md) diff --git a/Documentation/Monitors/Galera-Monitor.md b/Documentation/Monitors/Galera-Monitor.md index 4014d610d..0104d3d48 100644 --- a/Documentation/Monitors/Galera-Monitor.md +++ b/Documentation/Monitors/Galera-Monitor.md @@ -65,8 +65,9 @@ use_priority=true ### `root_node_as_master` This option controls whether the write master Galera node requires a -_wsrep_local_index_ value of 0. This option is enabled by default and was -introduced in MaxScale 2.1.0. +_wsrep_local_index_ value of 0. This option was introduced in MaxScale 2.1.0 and +it is disabled by default in versions 2.1.5 and newer. In versions 2.1.4 and +older, the option was enabled by default. A Galera cluster will always have a node which has a _wsrep_local_index_ value of 0. Based on this information, multiple MaxScale instances can always pick the diff --git a/Documentation/Release-Notes/MaxScale-2.1.5-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.1.5-Release-Notes.md index 9025c9581..5c58eca86 100644 --- a/Documentation/Release-Notes/MaxScale-2.1.5-Release-Notes.md +++ b/Documentation/Release-Notes/MaxScale-2.1.5-Release-Notes.md @@ -1,4 +1,4 @@ -# MariaDB MaxScale 2.1.5 Release Notes +# MariaDB MaxScale 2.1.5 Release Notes -- 2017-07-31 Release 2.1.5 is a GA release. @@ -18,12 +18,32 @@ report at [Jira](https://jira.mariadb.org). ## Changed Features +### SSL CA Certificates + +Before MaxScale 2.1.5, MaxScale would only use the first certificate file found +in the CA certificate file. In MaxScale 2.1.5, the first certificate is loaded +and the rest of the certificates on the file are stored in the chain store. + +This change should not cause any changes in MaxScale's behavior. + +### `root_node_as_master` + +The galeramon parameter `root_node_as_master` is now disabled by default. The +option should be enabled when it is of great importance to know that all +MaxScale instances treat a shared Galera cluster in the same way. + ### Schemarouter Starting with MaxScale 2.1.5, the _schemarouter_ will prioritize the current database over an explicit database if tables in the the current database are used in a query. +### Dbfwfilter + +The function type rule will now accept backtick quoted values. This allows +keywords such as `insert` and `function` to be used as values for a function +rule. + ## New Features ### Schemarouter @@ -40,10 +60,25 @@ will still go to the central database. ## Bug fixes -[Here is a list of bugs fixed since the release of MaxScale 2.1.4.] +[Here is a list of bugs fixed in MaxScale 2.1.5.] (https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.1.5) +* [MXS-1335](https://jira.mariadb.org/browse/MXS-1335) root_node_as_master should not be enabled by default +* [MXS-1330](https://jira.mariadb.org/browse/MXS-1330) insertstream attempts to parse all buffers +* [MXS-1329](https://jira.mariadb.org/browse/MXS-1329) Using filters with SSL and keep alive can cause errors +* [MXS-1328](https://jira.mariadb.org/browse/MXS-1328) Strange behavior with routes between master / slaves +* [MXS-1326](https://jira.mariadb.org/browse/MXS-1326) Upgrade error on Ubuntu Xenial +* [MXS-1324](https://jira.mariadb.org/browse/MXS-1324) MaxScale 2.1.4 compiled without the avrorouter? +* [MXS-1323](https://jira.mariadb.org/browse/MXS-1323) Maxscale2.1.3 coredump +* [MXS-1319](https://jira.mariadb.org/browse/MXS-1319) Maxscale selecting extra whitespace while loading users +* [MXS-1318](https://jira.mariadb.org/browse/MXS-1318) Use SSL_CTX_use_certificate_chain_file in Maxscale to use CA signed certificates +* [MXS-1316](https://jira.mariadb.org/browse/MXS-1316) error using Kafka with binlog router +* [MXS-1313](https://jira.mariadb.org/browse/MXS-1313) Character set is not updated if servers are down +* [MXS-1312](https://jira.mariadb.org/browse/MXS-1312) Rule with only on_queries do not work +* [MXS-1311](https://jira.mariadb.org/browse/MXS-1311) Function type rule that blocks function results in syntax error * [MXS-1310](https://jira.mariadb.org/browse/MXS-1310) schemarouter ignores local copy of duplicate schemas on JOIN +* [MXS-1309](https://jira.mariadb.org/browse/MXS-1309) ALTER TABLE detection is broken +* [MXS-1285](https://jira.mariadb.org/browse/MXS-1285) cannot stat `/usr/share/maxscale/upstart/maxscale.conf': No such file or directory ## Known Issues and Limitations diff --git a/Documentation/Upgrading/Upgrading-To-MaxScale-1.3.md b/Documentation/Upgrading/Upgrading-To-MaxScale-1.3.md index 4c814b4a5..78ca57ccf 100644 --- a/Documentation/Upgrading/Upgrading-To-MaxScale-1.3.md +++ b/Documentation/Upgrading/Upgrading-To-MaxScale-1.3.md @@ -3,7 +3,7 @@ This document describes upgrading MaxScale from version 1.2.1 to 1.3. The major changes can be found in the [changelog](../Changelog.md) and more -detailed information in the [release notes](../Release-Notes/MaxScale-1.3.0-Release-Notes.md). +detailed information in the MaxScale 1.3.0 release notes. ## Installation diff --git a/Documentation/Upgrading/Upgrading-To-MaxScale-1.4.md b/Documentation/Upgrading/Upgrading-To-MaxScale-1.4.md index 23f15ccaa..ba18eb8e4 100644 --- a/Documentation/Upgrading/Upgrading-To-MaxScale-1.4.md +++ b/Documentation/Upgrading/Upgrading-To-MaxScale-1.4.md @@ -3,10 +3,10 @@ This document describes upgrading MaxScale from version 1.3 to 1.4. For more detailed information about MaxScale 1.4, please refer to: -* [MaxScale 1.4.3 release notes](../Release-Notes/MaxScale-1.4.3-Release-Notes.md) -* [MaxScale 1.4.2 release notes](../Release-Notes/MaxScale-1.4.2-Release-Notes.md) -* [MaxScale 1.4.1 release notes](../Release-Notes/MaxScale-1.4.1-Release-Notes.md) -* [MaxScale 1.4.0 release notes](../Release-Notes/MaxScale-1.4.0-Release-Notes.md) +* MaxScale 1.4.3 release notes +* MaxScale 1.4.2 release notes +* MaxScale 1.4.1 release notes +* MaxScale 1.4.0 release notes ## Installation diff --git a/Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md b/Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md index aee13f8dc..a07949329 100644 --- a/Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md +++ b/Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md @@ -7,6 +7,7 @@ For more information about MariaDB MaxScale 2.1, please refer to the [ChangeLog](../Changelog.md). For a complete list of changes in MaxScale 2.1, refer to the +[MaxScale 2.1.5 Release Notes](../Release-Notes/MaxScale-2.1.5-Release-Notes.md). [MaxScale 2.1.4 Release Notes](../Release-Notes/MaxScale-2.1.4-Release-Notes.md). [MaxScale 2.1.3 Release Notes](../Release-Notes/MaxScale-2.1.3-Release-Notes.md). [MaxScale 2.1.2 Release Notes](../Release-Notes/MaxScale-2.1.2-Release-Notes.md). diff --git a/VERSION21.cmake b/VERSION21.cmake index ba1a23389..56646f85c 100644 --- a/VERSION21.cmake +++ b/VERSION21.cmake @@ -5,7 +5,7 @@ set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version") set(MAXSCALE_VERSION_MINOR "1" CACHE STRING "Minor version") -set(MAXSCALE_VERSION_PATCH "4" CACHE STRING "Patch version") +set(MAXSCALE_VERSION_PATCH "5" CACHE STRING "Patch version") # This should only be incremented if a package is rebuilt set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number") diff --git a/etc/postinst.in b/etc/postinst.in index a46ec3bd9..592fcf0ce 100755 --- a/etc/postinst.in +++ b/etc/postinst.in @@ -53,7 +53,7 @@ then systemctl daemon-reload fi else - if [ -d "/etc/init/" ] + if [ -d "/etc/init/" ] && [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf" ] then cp @CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf /etc/init/ fi diff --git a/etc/postrm.in b/etc/postrm.in index 7474dda40..4a10dcaf3 100755 --- a/etc/postrm.in +++ b/etc/postrm.in @@ -3,7 +3,7 @@ # The first argument is the number of packages left after # this one has been removed. If it is 0 then the package is being # removed from the system. -if [ "$1" -eq 0 ] +if [ "$1" = "0" ] || [ "$1" = "remove" ] then if [ -f /etc/init.d/maxscale ] then diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index d54c372f6..796228737 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -302,6 +302,10 @@ add_test_executable(mxs1110_16mb.cpp mxs1110_16mb longblob_filters LABELS readwr # Schemarouter implicit database detection add_test_executable(mxs1310_implicit_db.cpp mxs1310_implicit_db mxs1310_implicit_db LABELS schemarouter REPL_BACKEND) +# Retry reads with persistent connections +add_test_executable(mxs1323_retry_read.cpp mxs1323_retry_read mxs1323 LABELS readwritesplit LIGHT REPL_BACKEND) +add_test_executable(mxs1323_stress.cpp mxs1323_stress mxs1323 LABELS readwritesplit REPL_BACKEND) + # INSERT extremelly big number of rows add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit HEAVY GALERA_BACKEND) @@ -309,7 +313,7 @@ add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit H add_test_script(mariadb_tests_hartmut mariadb_tests_hartmut.sh replication LABELS readwritesplit REPL_BACKEND) # A set of MariaDB server tests executed against Maxscale RWSplit (Galera backend) -add_test_script(mariadb_tests_hartmut_galera mariadb_tests_hartmut.sh galera LABELS readwritesplit GALERA_BACKEND) +add_test_script(mariadb_tests_hartmut_galera mariadb_tests_hartmut.sh galera_hartmut LABELS readwritesplit GALERA_BACKEND) # Creates a number of connections > max_connections setting add_test_executable(max_connections.cpp max_connections replication LABELS MySQLAuth MySQLProtocol UNSTABLE HEAVY REPL_BACKEND) @@ -545,7 +549,7 @@ add_test_executable(rwsplit_multi_stmt.cpp rwsplit_multi_stmt rwsplit_multi_stmt add_test_executable(rwsplit_read_only_trx.cpp rwsplit_read_only_trx rwsplit_read_only_trx LABELS readwritesplit REPL_BACKEND) # Test replication-manager with MaxScale -add_test_executable(replication_manager.cpp replication_manager replication_manager LABELS maxscale REPL_BACKEND) +#add_test_executable(replication_manager.cpp replication_manager replication_manager LABELS maxscale REPL_BACKEND) #add_test_executable_notest(replication_manager_2nodes.cpp replication_manager_2nodes replication_manager_2nodes LABELS maxscale REPL_BACKEND) #add_test_executable_notest(replication_manager_3nodes.cpp replication_manager_3nodes replication_manager_3nodes LABELS maxscale REPL_BACKEND) diff --git a/maxscale-system-test/avro_alter.cpp b/maxscale-system-test/avro_alter.cpp index 3fdf0146b..2ee641875 100644 --- a/maxscale-system-test/avro_alter.cpp +++ b/maxscale-system-test/avro_alter.cpp @@ -65,6 +65,7 @@ int main(int argc, char *argv[]) free(rows); } + test.stop_timeout(); execute_query(test.repl->nodes[0], "DROP TABLE test.t1;RESET MASTER"); test.repl->fix_replication(); diff --git a/maxscale-system-test/bug662.cpp b/maxscale-system-test/bug662.cpp index a400665c4..efc399875 100644 --- a/maxscale-system-test/bug662.cpp +++ b/maxscale-system-test/bug662.cpp @@ -1,39 +1,18 @@ /** * @file bug662.cpp regression case for bug 662 ("MaxScale hangs in startup if backend server is not responsive"), covers also bug680 ("RWSplit can't load DB user if backend is not available at MaxScale start") * - * - block all Mariadb servers Firewall - * - restart MaxScale - * - check it took no more then 20 seconds - * - unblock Mariadb servers - * - sleep one minute - * - check if Maxscale is alive + * - Block all Mariadb servers + * - Restart MaxScale + * - Unblock Mariadb servers + * - Sleep and check if Maxscale is alive */ -/* -Vilho Raatikka 2014-12-29 08:38:28 UTC -During startup, load_mysql_users tries to read the contents of the mysql.user table. If the chosen backend is not responsive, connection hangs for a long time. -Comment 1 Vilho Raatikka 2014-12-29 11:41:32 UTC -The issue causes long stalls for the executing thread whenever getUsers function is called and one or more backends are not responsive. -Comment 2 Vilho Raatikka 2014-12-29 11:50:10 UTC -dbusers.c: Added function for setting read, write and connection timeout values. Set default timeouts for getUsers. Defaults are listed in service.c - gateway.c:shutdown_server is called whenever MaxScale is to be shut down. Added call for service_shutdown to shutdown_server. - service.c:service_alloc: replaced malloc with calloc and removed unnecessary zero/NULL initialization statements as a consequence. - serviceStart: Exit serviceStartPort loop if shutdown flag is set for the service. - serviceStartAll: Exit serviceStart loop if shutdown flag is set for the service. - service.c: Added service_shutdown which sets shutdown flag for each service found in allServices list. - service.h: Added prototype for service_shutdown -*/ - - - -#include #include "testconnections.h" #include "maxadmin_operations.h" int main(int argc, char *argv[]) { TestConnections * Test = new TestConnections(argc, argv); - Test->set_timeout(20); int i; Test->tprintf("Connecting to Maxscale %s\n", Test->maxscale_IP); @@ -44,6 +23,7 @@ int main(int argc, char *argv[]) for (i = 0; i < Test->repl->N; i++) { + Test->set_timeout(30); Test->tprintf("Setup firewall to block mysql on node %d\n", i); Test->repl->block_node(i); fflush(stdout); @@ -53,12 +33,12 @@ int main(int argc, char *argv[]) Test->tprintf("Restarting MaxScale"); Test->restart_maxscale(); - Test->set_timeout(20); Test->tprintf("Checking if MaxScale is alive by connecting to MaxAdmin\n"); Test->add_result(Test->execute_maxadmin_command((char* ) "show servers"), "Maxadmin execution failed.\n"); for (i = 0; i < Test->repl->N; i++) { + Test->set_timeout(30); Test->tprintf("Setup firewall back to allow mysql on node %d\n", i); Test->repl->unblock_node(i); fflush(stdout); @@ -68,13 +48,11 @@ int main(int argc, char *argv[]) Test->tprintf("Sleeping 30 seconds\n"); sleep(30); - Test->set_timeout(20); - + Test->set_timeout(30); Test->tprintf("Checking Maxscale is alive\n"); Test->check_maxscale_alive(); int rval = Test->global_result; delete Test; return rval; - //} } diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.galera_hartmut b/maxscale-system-test/cnf/maxscale.cnf.template.galera_hartmut new file mode 100644 index 000000000..fbfbb4d6c --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.galera_hartmut @@ -0,0 +1,89 @@ +[maxscale] +threads=###threads### +log_info=1 + +[Galera Monitor] +type=monitor +module=galeramon +servers=server1,server2,server3,server4 +user=maxskysql +passwd=skysql +monitor_interval=1000 +root_node_as_master=false + +[RW Split Router] +type=service +router=readwritesplit +servers=server1,server2,server3,server4 +user=maxskysql +passwd=skysql +router_options=slave_selection_criteria=LEAST_GLOBAL_CONNECTIONS +max_slave_connections=1 + +[Read Connection Router Slave] +type=service +router=readconnroute +router_options=slave +servers=server1,server2,server3,server4 +user=maxskysql +passwd=skysql + +[Read Connection Router Master] +type=service +router=readconnroute +router_options=master +servers=server1,server2,server3,server4 +user=maxskysql +passwd=skysql + +[RW Split Listener] +type=listener +service=RW Split Router +protocol=MySQLClient +port=4006 + +[Read Connection Listener Slave] +type=listener +service=Read Connection Router Slave +protocol=MySQLClient +port=4009 + +[Read Connection Listener Master] +type=listener +service=Read Connection Router Master +protocol=MySQLClient +port=4008 + +[CLI] +type=service +router=cli + +[CLI Listener] +type=listener +service=CLI +protocol=maxscaled +socket=default + +[server1] +type=server +address=###galera_server_IP_1### +port=###galera_server_port_1### +protocol=MySQLBackend + +[server2] +type=server +address=###galera_server_IP_2### +port=###galera_server_port_2### +protocol=MySQLBackend + +[server3] +type=server +address=###galera_server_IP_3### +port=###galera_server_port_3### +protocol=MySQLBackend + +[server4] +type=server +address=###galera_server_IP_4### +port=###galera_server_port_4### +protocol=MySQLBackend diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.mxs1323 b/maxscale-system-test/cnf/maxscale.cnf.template.mxs1323 new file mode 100644 index 000000000..f5fff9976 --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.mxs1323 @@ -0,0 +1,51 @@ +[maxscale] +threads=###threads### +log_info=1 + +[MySQL Monitor] +type=monitor +module=mysqlmon +###repl51### +servers= server1,server2 +user=maxskysql +passwd= skysql +monitor_interval=500 + +[RW Split Router] +type=service +router= readwritesplit +servers=server1,server2 +user=maxskysql +passwd=skysql + +[RW Split Listener] +type=listener +service=RW Split Router +protocol=MySQLClient +port=4006 + +[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 +persistpoolmax=10 +persistmaxtime=300 + +[server2] +type=server +address=###node_server_IP_2### +port=###node_server_port_2### +protocol=MySQLBackend +persistpoolmax=10 +persistmaxtime=300 diff --git a/maxscale-system-test/mariadb_nodes.cpp b/maxscale-system-test/mariadb_nodes.cpp index 85860f4db..cd21436af 100644 --- a/maxscale-system-test/mariadb_nodes.cpp +++ b/maxscale-system-test/mariadb_nodes.cpp @@ -14,6 +14,7 @@ #include "sql_const.h" #include #include +#include #include Mariadb_nodes::Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose): @@ -918,6 +919,13 @@ int Mariadb_nodes::get_server_id(int index) return id; } +std::string Mariadb_nodes::get_server_id_str(int index) +{ + std::stringstream ss; + ss << get_server_id(index); + return ss.str(); +} + void Mariadb_nodes::generate_ssh_cmd(char *cmd, int node, const char *ssh, bool sudo) { if (strcmp(IP[node], "127.0.0.1") == 0) diff --git a/maxscale-system-test/mariadb_nodes.h b/maxscale-system-test/mariadb_nodes.h index bc01f34dc..f7052c0c2 100644 --- a/maxscale-system-test/mariadb_nodes.h +++ b/maxscale-system-test/mariadb_nodes.h @@ -16,6 +16,7 @@ #include "mariadb_func.h" #include +#include /** * @brief A class to handle backend nodes @@ -329,6 +330,7 @@ public: * @return Node id of the server or -1 on error */ int get_server_id(int index); + std::string get_server_id_str(int index); /** * @brief Generate command line to execute command on the node via ssh diff --git a/maxscale-system-test/mariadb_tests_hartmut.sh b/maxscale-system-test/mariadb_tests_hartmut.sh index ef8b6e64d..a456d6917 100755 --- a/maxscale-system-test/mariadb_tests_hartmut.sh +++ b/maxscale-system-test/mariadb_tests_hartmut.sh @@ -4,7 +4,7 @@ # # TODO: Don't test correctness of routing with mysqltest # -./non_native_setup $1 + master_id=`echo "SELECT @@server_id" | mysql -u$node_user -p$node_password -h $node_000_network $ssl_options -P $node_000_port | tail -n1` echo "--disable_query_log" > Hartmut_tests/maxscale-mysqltest/testconf.inc echo "SET @TMASTER_ID=$master_id;" >> Hartmut_tests/maxscale-mysqltest/testconf.inc diff --git a/maxscale-system-test/mxs1071_maxrows.cpp b/maxscale-system-test/mxs1071_maxrows.cpp index c52a295b1..3f6253c5d 100644 --- a/maxscale-system-test/mxs1071_maxrows.cpp +++ b/maxscale-system-test/mxs1071_maxrows.cpp @@ -207,7 +207,7 @@ int compare_expected(TestConnections * Test, const char * sql, my_ulonglong exp_ my_ulonglong *rows = new my_ulonglong[30]; my_ulonglong i; - Test->set_timeout(10); + Test->set_timeout(30); execute_query_num_of_rows(Test->conn_rwsplit, sql, rows, &i); Test->tprintf("Result sets number is %llu\n", i); @@ -245,7 +245,7 @@ int compare_stmt_expected(TestConnections * Test, MYSQL_STMT * stmt, my_ulonglon my_ulonglong *rows = new my_ulonglong[30]; my_ulonglong i; - Test->set_timeout(10); + Test->set_timeout(30); execute_stmt_num_of_rows(stmt, rows, &i); Test->tprintf("Result sets number is %llu\n", i); @@ -290,7 +290,7 @@ int main(int argc, char *argv[]) MYSQL_STMT * stmt; TestConnections * Test = new TestConnections(argc, argv); - Test->set_timeout(10); + Test->set_timeout(30); Test->connect_rwsplit(); create_t1(Test->conn_rwsplit); diff --git a/maxscale-system-test/mxs1323_retry_read.cpp b/maxscale-system-test/mxs1323_retry_read.cpp new file mode 100644 index 000000000..7d17f337f --- /dev/null +++ b/maxscale-system-test/mxs1323_retry_read.cpp @@ -0,0 +1,50 @@ +/** + * Test for MXS-1323. + * - Check that retried reads work with persistent connections + */ + +#include "testconnections.h" + +void* async_block(void* data) +{ + TestConnections *test = (TestConnections*)data; + sleep(5); + test->tprintf("Blocking slave"); + test->repl->block_node(1); + return NULL; +} + +std::string do_query(TestConnections& test) +{ + MYSQL* conn = test.open_rwsplit_connection(); + + const char* query = "SELECT SLEEP(10), @@server_id"; + char output[512] = ""; + + find_field(conn, query, "@@server_id", output); + mysql_close(conn); + + return std::string(output); +} + +int main(int argc, char *argv[]) +{ + TestConnections test(argc, argv); + + char server_id[2][1024]; + test.repl->connect(); + std::string master = test.repl->get_server_id_str(0); + std::string slave = test.repl->get_server_id_str(1); + test.repl->close_connections(); + + test.set_timeout(60); + test.add_result(do_query(test) != slave, "The slave should respond to the first query"); + + pthread_t thr; + pthread_create(&thr, NULL, async_block, &test); + test.add_result(do_query(test) != master, "The master should respond to the second query"); + pthread_join(thr, NULL); + test.repl->unblock_node(1); + + return test.global_result; +} diff --git a/maxscale-system-test/mxs1323_stress.cpp b/maxscale-system-test/mxs1323_stress.cpp new file mode 100644 index 000000000..efae35e66 --- /dev/null +++ b/maxscale-system-test/mxs1323_stress.cpp @@ -0,0 +1,81 @@ +/** + * Test for MXS-1323. + * - Check that retried reads work with persistent connections + */ + +#include "testconnections.h" +#include + +static bool running = true; + +void* async_query(void* data) +{ + TestConnections *test = (TestConnections*)data; + + while (running && test->global_result == 0) + { + MYSQL* conn = test->open_rwsplit_connection(); + + for (int i = 0; i < 50 && running && test->global_result == 0; i++) + { + const char* query = "SET @a = (SELECT SLEEP(1))"; + test->try_query(conn, query); + } + + mysql_close(conn); + } + + return NULL; +} + +#define NUM_THR 5 + +int main(int argc, char *argv[]) +{ + TestConnections test(argc, argv); + pthread_t query_thr[NUM_THR]; + std::stringstream ss; + + ss << "CREATE OR REPLACE TABLE test.t1 (id INT)"; + test.connect_maxscale(); + test.try_query(test.conn_rwsplit, ss.str().c_str()); + + ss.str(""); + ss << "INSERT INTO test.t1 VALUES (0)"; + for (int i = 1; i <= 10000; i++) + { + ss << ",(" << i << ")"; + } + test.try_query(test.conn_rwsplit, ss.str().c_str()); + + test.close_maxscale_connections(); + + if (test.global_result) + { + return test.global_result; + } + + for (int i = 0; i < NUM_THR; i++) + { + pthread_create(&query_thr[i], NULL, async_query, &test); + } + + for (int i = 0; i < 3 && test.global_result == 0; i++) + { + test.tprintf("Round %d", i + 1); + test.repl->block_node(1); + sleep(5); + test.repl->unblock_node(1); + sleep(5); + } + + running = false; + + for (int i = 0; i < NUM_THR; i++) + { + test.set_timeout(10); + pthread_join(query_thr[i], NULL); + } + + return test.global_result; +} diff --git a/query_classifier/qc_sqlite/builtin_functions.c b/query_classifier/qc_sqlite/builtin_functions.c index ec4dae9da..44bace220 100644 --- a/query_classifier/qc_sqlite/builtin_functions.c +++ b/query_classifier/qc_sqlite/builtin_functions.c @@ -369,6 +369,16 @@ static const char* BUILTIN_FUNCTIONS[] = "to_base64", "weight_string", + /* + * Regex functions + * https://mariadb.com/kb/en/mariadb/regular-expressions-functions/ + */ + "regexp", + "regexp_instr", + "regexp_replace", + "regexp_substr", + "rlike", + /* * http://dev.mysql.com/doc/refman/5.7/en/row-subqueries.html */ diff --git a/query_classifier/test/maxscale.test b/query_classifier/test/maxscale.test index 95a3c130e..52a10478c 100644 --- a/query_classifier/test/maxscale.test +++ b/query_classifier/test/maxscale.test @@ -77,3 +77,5 @@ ROLLBACK TO SAVEPOINT id; ROLLBACK WORK TO id; ROLLBACK TO id; RELEASE SAVEPOINT id; + +SELECT her FROM (SELECT @@server_id as her) as t WHERE her REGEXP '.*'; diff --git a/server/modules/filter/insertstream/insertstream.c b/server/modules/filter/insertstream/insertstream.c index e61b2236d..bec4b4327 100644 --- a/server/modules/filter/insertstream/insertstream.c +++ b/server/modules/filter/insertstream/insertstream.c @@ -606,7 +606,8 @@ static bool extract_insert_target(GWBUF *buffer, char* target, int len) { bool rval = false; - if (qc_get_operation(buffer) == QUERY_OP_INSERT && + if (MYSQL_GET_COMMAND(GWBUF_DATA(buffer)) == MYSQL_COM_QUERY && + qc_get_operation(buffer) == QUERY_OP_INSERT && only_implicit_values(buffer)) { int n_tables = 0; diff --git a/server/modules/monitor/galeramon/galeramon.c b/server/modules/monitor/galeramon/galeramon.c index 6cbda4144..916a7f580 100644 --- a/server/modules/monitor/galeramon/galeramon.c +++ b/server/modules/monitor/galeramon/galeramon.c @@ -85,7 +85,7 @@ MXS_MODULE* MXS_CREATE_MODULE() {"disable_master_failback", MXS_MODULE_PARAM_BOOL, "false"}, {"available_when_donor", MXS_MODULE_PARAM_BOOL, "false"}, {"disable_master_role_setting", MXS_MODULE_PARAM_BOOL, "false"}, - {"root_node_as_master", MXS_MODULE_PARAM_BOOL, "true"}, + {"root_node_as_master", MXS_MODULE_PARAM_BOOL, "false"}, {"use_priority", MXS_MODULE_PARAM_BOOL, "false"}, { "script", diff --git a/server/modules/protocol/examples/cdc_schema.go b/server/modules/protocol/examples/cdc_schema.go index 44910d500..b946a1bbc 100644 --- a/server/modules/protocol/examples/cdc_schema.go +++ b/server/modules/protocol/examples/cdc_schema.go @@ -15,11 +15,11 @@ import ( "database/sql" "encoding/json" "flag" + "fmt" "log" "os" "regexp" "strconv" - "fmt" ) import _ "github.com/go-sql-driver/mysql" @@ -45,8 +45,10 @@ The "user" and "password" flags are required. // Avro field type Field struct { - Name string `json:"name"` - Type string `json:"type"` + Name string `json:"name"` + Type string `json:"type"` + RealType string `json:"real_type"` + Length int `json:"length"` } // Avro schema @@ -68,13 +70,20 @@ func LogObject(obj interface{}) { } var field_re *regexp.Regexp +var length_re *regexp.Regexp // Convert the SQL type to the appropriate Avro type func (f *Field) ToAvroType() { + orig := f.Type f.Type = field_re.ReplaceAllString(f.Type, "") + f.Length = -1 + f.RealType = f.Type switch f.Type { case "date", "datetime", "time", "timestamp", "year", "tinytext", "text", - "mediumtext", "longtext", "char", "varchar", "enum", "set": + "mediumtext", "longtext", "char", "varchar": + f.Type = "string" + f.Length, _ = strconv.Atoi(length_re.ReplaceAllString(orig, "$1")) + case "enum", "set": f.Type = "string" case "tinyblob", "blob", "mediumblob", "longblob", "binary", "varbinary": f.Type = "bytes" @@ -127,11 +136,18 @@ func StoreSchema(db *sql.DB, schema, table string) { func main() { var err error field_re, err = regexp.Compile("[(].*") + if err != nil { log.Fatal("Error: ", err) } - flag.Usage = PrintUsage; + length_re, err = regexp.Compile(".*[(](.*)[)].*") + + if err != nil { + log.Fatal("Error: ", err) + } + + flag.Usage = PrintUsage flag.Parse() if len(*user) == 0 || len(*passwd) == 0 { diff --git a/server/modules/routing/readwritesplit/readwritesplit.cc b/server/modules/routing/readwritesplit/readwritesplit.cc index 9163dc092..a1390a8fa 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.cc +++ b/server/modules/routing/readwritesplit/readwritesplit.cc @@ -401,8 +401,7 @@ static bool handle_error_new_connection(RWSplit *inst, * to the client. */ GWBUF *stored = NULL; - const SERVER *target; - + const SERVER *target = NULL; if (!session_take_stmt(backend_dcb->session, &stored, &target) || target != backend->backend()->server || !reroute_stored_statement(*rses, backend, stored))