diff --git a/Documentation/Reference/MaxCtrl.md b/Documentation/Reference/MaxCtrl.md index d5effed0d..4b602e466 100644 --- a/Documentation/Reference/MaxCtrl.md +++ b/Documentation/Reference/MaxCtrl.md @@ -32,6 +32,7 @@ For more information about the MaxScale REST API, refer to the * [rotate](#rotate) * [call](#call) * [cluster](#cluster) +* [api](#api) ## Options @@ -39,7 +40,9 @@ All command accept the following global options. ``` -u, --user Username to use [string] [default: "admin"] - -p, --password Password for the user [string] [default: "mariadb"] + -p, --password Password for the user. To input the password manually, give -p + as the last argument or use --password='' + [string] [default: "mariadb"] -h, --hosts List of MaxScale hosts. The hosts must be in HOST:PORT format and each value must be separated by a comma. [string] [default: "localhost:8989"] @@ -664,3 +667,21 @@ due to a network failure or some other ephemeral error. Any other errors require manual synchronization of the MaxScale configuration files and a restart of the failed Maxscale. +## api + +``` +Usage: api + +Commands: + get [path] Get raw JSON + +``` + +### api get + +`Usage: get [path]` + +Perform a raw REST API call. The path definition uses JavaScript syntax to +extract values. For example, the following command extracts all server states as +an array of JSON values: maxctrl api get servers data[].attributes.state + diff --git a/Documentation/Release-Notes/MaxScale-2.2.5-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.2.5-Release-Notes.md new file mode 100644 index 000000000..b13f160d6 --- /dev/null +++ b/Documentation/Release-Notes/MaxScale-2.2.5-Release-Notes.md @@ -0,0 +1,63 @@ +# MariaDB MaxScale 2.2.5 Release Notes + +Release 2.2.5 is a GA release. + +This document describes the changes in release 2.2.5, when compared to +release 2.2.4. + +For any problems you encounter, please consider submitting a bug +report at [Jira](https://jira.mariadb.org). + +## Changed Features + +## Dropped Features + +## New Features + +### MaxCtrl: Raw REST API Calls + +MaxCtrl is now able to perform raw HTTP GET calls that return the JSON +data from the REST API. It also supports value extraction with JavaScript +style syntax. + +For example, extracting just the state of all servers as a JSON array can be +done with the following command: + +``` +[markusjm@localhost ~]$ maxctrl api get servers data[].attributes.state +["Master, Running","Slave, Running","Slave, Running","Slave, Running"] +``` + +## Bug fixes + +* [MXS-1787](https://jira.mariadb.org/browse/MXS-1787) Crash with mysql client test `test_bug49972` +* [MXS-1786](https://jira.mariadb.org/browse/MXS-1786) Hang with COM_STATISTICS +* [MXS-1785](https://jira.mariadb.org/browse/MXS-1785) request 16M-1 normal sql + 'select 1' core dump with debug mode +* [MXS-1776](https://jira.mariadb.org/browse/MXS-1776) Hang with mysql test case `test_basic_cursors` +* [MXS-1773](https://jira.mariadb.org/browse/MXS-1773) LOAD DATA LOCAL INFILE confuses readwritesplit +* [MXS-1765](https://jira.mariadb.org/browse/MXS-1765) Internal client connections write data in wrong order +* [MXS-1757](https://jira.mariadb.org/browse/MXS-1757) Problem while linking libavrorouter.so on Ubuntu 14.04 +* [MXS-1751](https://jira.mariadb.org/browse/MXS-1751) Maxscale crashes when certain config is in play (with nodes down) +* [MXS-1747](https://jira.mariadb.org/browse/MXS-1747) Rejoin functions should print better errors +* [MXS-1746](https://jira.mariadb.org/browse/MXS-1746) The session-specific gtid_domain_id is queried instead of the global one +* [MXS-1743](https://jira.mariadb.org/browse/MXS-1743) Maxscale unable to enforce round-robin between read service for Slave + +## Known Issues and Limitations + +There are some limitations and known issues within this version of MaxScale. +For more information, please refer to the [Limitations](../About/Limitations.md) document. + +## Packaging + +RPM and Debian packages are provided for the Linux distributions supported +by MariaDB Enterprise. + +Packages can be downloaded [here](https://mariadb.com/downloads/mariadb-tx/maxscale). + +## Source Code + +The source code of MaxScale is tagged at GitHub with a tag, which is identical +with the version of MaxScale. For instance, the tag of version X.Y.Z of MaxScale +is X.Y.Z. Further, *master* always refers to the latest released non-beta version. + +The source code is available [here](https://github.com/mariadb-corporation/MaxScale). diff --git a/docker/Dockerfile b/docker/Dockerfile index 388710437..8855ddeed 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,53 +1,7 @@ -# This Dockerfile builds an image for MariaDB MaxScale: -# https://mariadb.com/products/technology/maxscale -# The example configuration file maxscale.cnf should be in the build directory -# when building the image. - -FROM alpine:latest - -# Packages required for building MaxScale and Avro-C -ARG DEPENDENCIES_PKGS="bash bison cmake curl flex gcc git gnutls gnutls-dev g++ \ -jansson jansson-dev libedit libedit-dev libgcrypt libgcrypt-dev libstdc++ lua \ -lua-dev make ncurses ncurses-dev openssl openssl-dev perl sqlite sqlite-dev \ -sqlite-libs tcl-dev util-linux-dev xz xz-dev" - -# Packages that can be removed after build -ARG REM_PKGS="bison bash cmake flex gcc git gnutls-dev g++ jansson-dev \ -libedit-dev libgcrypt-dev lua-dev make ncurses-dev openssl-dev perl sqlite-dev \ -tcl-dev xz-dev" - -# MaxScale-specific parameters -ARG MS_DIR=/MaxScale_workdir -ARG MS_CMAKE_PARS="-DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo \ --DWITH_SCRIPTS=N -DTARGET_COMPONENT=all" -ARG MS_BRANCH=develop -ARG MS_REPO=https://github.com/mariadb-corporation/MaxScale.git - -# Avro-specific parameters -ARG AV_DIR=/Avro_workdir -ARG AV_PREF=avro-c-1.8.2 -ARG AV_ARCH=$AV_PREF.tar.gz -ARG AV_URL=ftp://ftp.funet.fi/pub/mirrors/apache.org/avro/avro-1.8.2/c/$AV_ARCH -ARG AV_CMAKE_PARS="-DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo \ --DCMAKE_C_FLAGS=-fPIC -DCMAKE_CXX_FLAGS=-fPIC" - -RUN apk -U add $DEPENDENCIES_PKGS && \ - mkdir $MS_DIR && mkdir $AV_DIR && mkdir $MS_DIR/Build && mkdir $AV_DIR/Build && \ - cd $AV_DIR && \ -# Download Avro-C, build and install - curl --output $AV_ARCH $AV_URL && \ - tar -zxvf $AV_ARCH && cd Build && \ - cmake $AV_CMAKE_PARS ../$AV_PREF && \ - make install && \ - cd $MS_DIR && \ -# Download MaxScale, build and install - git clone --depth 1 --branch $MS_BRANCH $MS_REPO && cd Build && \ - cmake $MS_CMAKE_PARS ../MaxScale && \ - make install && (./postinst || true) && \ -# Remove unneeded packages and work directories - apk del $REM_PKGS && \ - cd / && rm -rf $MS_DIR $AV_DIR +# Dockerfile for the 2.2 GA version of MariaDB MaxScale +FROM centos:7 +RUN curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash && yum -y install maxscale COPY ./maxscale.cnf /etc/ -ENTRYPOINT ["maxscale", "-d"] +ENTRYPOINT ["maxscale", "-d", "-U", "maxscale"] CMD ["-lstdout"] diff --git a/docker/README.md b/docker/README.md index ff3d51972..fbe4ca69b 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,133 +1,58 @@ # MariaDB MaxScale Docker image -This Docker image runs MariaDB MaxScale. The MaxScale version used to build the -image is an unreleased development build so this should not be used for a -production system. +This Docker image runs the latest GA version of MariaDB MaxScale. + +## Building + +Run the following command in this directory to build the image. + +``` +docker build -t maxscale . +``` ## Usage -MaxScale is a proxy so its configuration is dependent on the use case and there -is no generally valid default. The configuration file inside the image (shown in -[Default configuration](#default-configuration)) includes only the bare minimum -to start MaxScale and has no useful services. The simplest way to add more to -the configuration is to place another file (*my_config.cnf*) in a directory -(*/my_dir/*) and then mount the directory to */etc/maxscale.cnf.d/* inside the -container when starting it. MaxScale will add any files inside -*/etc/maxscale.cnf.d/* to its configuration. +You must mount your configuration file into `/etc/maxscale.cnf.d/`. To do +this, pass it as an argument to the `-v` option: ``` -docker run --network host --rm -v /my_dir:/etc/maxscale.cnf.d/ maxscale +docker run -v $PWD/my-maxscale.cnf:/etc/maxscale.cnf.d/my-maxscale.cnf maxscale:latest ``` -In the examples, the Docker network mode is set to *host* so that the container -has full network access (`--network host`). - -To replace the configuration file completely, start MaxScale with `-f `. -Adding custom options removes all default options defined in the image. When -adding new flags to MaxScale, one should add back `-l stdout` to print log to -stdout. +By default, MaxScale runs with the `-l stdout` arguments. To explicitly +define a configuration file, use the `-f /path/to/maxscale.cnf` argument +and add `-l stdout` after it. ``` -docker run --network host --rm -v /my_dir:/container_dir maxscale -l stdout -f /container_dir/my_config.cnf -``` - -To save logs to */my_dir*, remove the `-l stdout` and set */container_dir* as -log directory with the option `-L /container_dir`. - -``` -docker run --network host --rm -v /my_dir:/container_dir maxscale -L /container_dir -f /container_dir/my_config.cnf +docker run --network host --rm -v /my_dir:/container_dir maxscale -f /path/to/maxscale.cnf -l stdout ``` ## Default configuration -``` -# MaxScale documentation on GitHub: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Documentation-Contents.md +The default configuration for the MaxScale docker image can be found in +[this configuration file](./maxscale.cnf). -# Complete list of configuration options: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Getting-Started/Configuration-Guide.md +## MaxScale docker-compose setup -# Global parameters - -[maxscale] -threads=2 - -# This service enables the use of the MaxAdmin interface -# MaxScale administration guide: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Reference/MaxAdmin.md -[MaxAdmin-Service] -type=service -router=cli - -[MaxAdmin-Listener] -type=listener -service=MaxAdmin-Service -protocol=maxscaled -socket=default -``` - -## Example configuration extension +[The MaxScale docker-compose setup](./docker-compose.yml) contains MaxScale +configured with a three node master-slave cluster. To start it, run the +following commands in this directory. ``` -# Server definitions -# Set the address of the server to the network address of a MySQL server. - -[server1] -type=server -address=127.0.0.1 -port=3306 -protocol=MySQLBackend - -# Monitor for the servers -# This will keep MaxScale aware of the state of the servers. -# MySQL Monitor documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Monitors/MySQL-Monitor.md - -[MySQL-Monitor] -type=monitor -module=mysqlmon -servers=server1 -user=myuser -passwd=mypwd -monitor_interval=1000 - -# Service definitions -# Service Definition for a read-only service and a read/write splitting service. - -# ReadConnRoute documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Routers/ReadConnRoute.md - -[Read-Only-Service] -type=service -router=readconnroute -servers=server1 -user=myuser -passwd=mypwd -router_options=slave - -# ReadWriteSplit documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Routers/ReadWriteSplit.md - -[Read-Write-Service] -type=service -router=readwritesplit -servers=server1 -user=myuser -passwd=mypwd -max_slave_connections=100% - -# Listener definitions for the services -# Listeners represent the ports the services will listen on. - -[Read-Only-Listener] -type=listener -service=Read-Only-Service -protocol=MySQLClient -port=4008 - -[Read-Write-Listener] -type=listener -service=Read-Write-Service -protocol=MySQLClient -port=4006 +docker-compose build +docker-compose up -d +``` + +After MaxScale and the servers have started (takes a few minutes), you can find +the readwritesplit router on port 4006 and the readconnroute on port 4008. The +user `maxuser` with the password `maxpwd` can be used to test the cluster. + +You can edit the [`maxscale.cnf.d/example.cnf`](./maxscale.cnf.d/example.cnf) +file and recreate the MaxScale container to change the configuration. + +To stop the containers, execute the following command. Optionally, use the -v +flag to also remove the volumes. + +``` +docker-compose down ``` diff --git a/docker/config_extension_example.cnf b/docker/config_extension_example.cnf deleted file mode 100644 index da707dc9c..000000000 --- a/docker/config_extension_example.cnf +++ /dev/null @@ -1,61 +0,0 @@ -# Server definitions -# Set the address of the server to the network address of a MySQL server. - -[server1] -type=server -address=127.0.0.1 -port=3306 -protocol=MySQLBackend - -# Monitor for the servers -# This will keep MaxScale aware of the state of the servers. -# MySQL Monitor documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Monitors/MySQL-Monitor.md - -[MySQL-Monitor] -type=monitor -module=mysqlmon -servers=server1 -user=myuser -passwd=mypwd -monitor_interval=1000 - -# Service definitions -# Service Definition for a read-only service and a read/write splitting service. - -# ReadConnRoute documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Routers/ReadConnRoute.md - -[Read-Only-Service] -type=service -router=readconnroute -servers=server1 -user=myuser -passwd=mypwd -router_options=slave - -# ReadWriteSplit documentation: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Routers/ReadWriteSplit.md - -[Read-Write-Service] -type=service -router=readwritesplit -servers=server1 -user=myuser -passwd=mypwd -max_slave_connections=100% - -# Listener definitions for the services -# Listeners represent the ports the services will listen on. - -[Read-Only-Listener] -type=listener -service=Read-Only-Service -protocol=MySQLClient -port=4008 - -[Read-Write-Listener] -type=listener -service=Read-Write-Service -protocol=MySQLClient -port=4006 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 000000000..773951561 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,34 @@ +version: '2' +services: + master: + image: mariadb:10.2 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: Y + volumes: + - ./sql/master:/docker-entrypoint-initdb.d + command: mysqld --log-bin=mariadb-bin --binlog-format=ROW --server-id=3000 + + slave1: + image: mariadb:10.2 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: Y + volumes: + - ./sql/slave:/docker-entrypoint-initdb.d + command: mysqld --log-bin=mariadb-bin --binlog-format=ROW --server-id=3001 + + slave2: + image: mariadb:10.2 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: Y + volumes: + - ./sql/slave:/docker-entrypoint-initdb.d + command: mysqld --log-bin=mariadb-bin --binlog-format=ROW --server-id=3002 + + maxscale: + build: . + container_name: maxscale + volumes: + - ./maxscale.cnf.d:/etc/maxscale.cnf.d + ports: + - "4006:4006" + - "4008:4008" diff --git a/docker/maxscale.cnf b/docker/maxscale.cnf index 9f7942abd..b0141f6a9 100644 --- a/docker/maxscale.cnf +++ b/docker/maxscale.cnf @@ -1,18 +1,12 @@ # MaxScale documentation on GitHub: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Documentation-Contents.md +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Documentation-Contents.md # Complete list of configuration options: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Getting-Started/Configuration-Guide.md - -# Global parameters - -[maxscale] -threads=2 +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Getting-Started/Configuration-Guide.md # This service enables the use of the MaxAdmin interface # MaxScale administration guide: -# https://github.com/mariadb-corporation/MaxScale/blob/develop/Documentation/Reference/MaxAdmin.md - +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Reference/MaxAdmin.md [MaxAdmin-Service] type=service router=cli diff --git a/docker/maxscale.cnf.d/example.cnf b/docker/maxscale.cnf.d/example.cnf new file mode 100644 index 000000000..28b629cce --- /dev/null +++ b/docker/maxscale.cnf.d/example.cnf @@ -0,0 +1,73 @@ +# Global parameters +[maxscale] +threads=auto + +[server1] +type=server +address=master +port=3306 +protocol=MariaDBBackend + +[server2] +type=server +address=slave1 +port=3306 +protocol=MariaDBBackend + +[server3] +type=server +address=slave2 +port=3306 +protocol=MariaDBBackend + +# Monitor for the servers +# This will keep MaxScale aware of the state of the servers. +# MySQL Monitor documentation: +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Monitors/MariaDB-Monitor.md + +[MariaDB-Monitor] +type=monitor +module=mariadbmon +servers=server1,server2,server3 +user=maxuser +passwd=maxpwd +monitor_interval=2000 + +# Service definitions +# Service Definition for a read-only service and a read/write splitting service. + +# ReadConnRoute documentation: +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Routers/ReadConnRoute.md + +[Read-Only-Service] +type=service +router=readconnroute +servers=server1,server2,server3 +user=maxuser +passwd=maxpwd +router_options=slave + +# ReadWriteSplit documentation: +# https://github.com/mariadb-corporation/MaxScale/blob/2.2/Documentation/Routers/ReadWriteSplit.md + +[Read-Write-Service] +type=service +router=readwritesplit +servers=server1,server2,server3 +user=maxuser +passwd=maxpwd + +# Listener definitions for the services +# Listeners represent the ports the services will listen on. + +[Read-Only-Listener] +type=listener +service=Read-Only-Service +protocol=MySQLClient +port=4008 + +[Read-Write-Listener] +type=listener +service=Read-Write-Service +protocol=MySQLClient +port=4006 diff --git a/docker/sql/master/users.sql b/docker/sql/master/users.sql new file mode 100644 index 000000000..ca1f44596 --- /dev/null +++ b/docker/sql/master/users.sql @@ -0,0 +1,10 @@ +RESET MASTER; +CREATE DATABASE test; + +CREATE USER 'maxuser'@'127.0.0.1' IDENTIFIED BY 'maxpwd'; +CREATE USER 'maxuser'@'%' IDENTIFIED BY 'maxpwd'; +GRANT ALL ON *.* TO 'maxuser'@'127.0.0.1' WITH GRANT OPTION; +GRANT ALL ON *.* TO 'maxuser'@'%' WITH GRANT OPTION; + +SET GLOBAL max_connections=10000; +SET GLOBAL gtid_strict_mode=ON; diff --git a/docker/sql/slave/replication.sql b/docker/sql/slave/replication.sql new file mode 100644 index 000000000..b38bf05c5 --- /dev/null +++ b/docker/sql/slave/replication.sql @@ -0,0 +1,4 @@ +CHANGE MASTER TO MASTER_HOST='master', MASTER_PORT=3306, MASTER_USER='maxuser', MASTER_PASSWORD='maxpwd', MASTER_LOG_POS=4, MASTER_LOG_FILE='mariadb-bin.000001', MASTER_CONNECT_RETRY=1; +START SLAVE; +SET GLOBAL max_connections=10000; +SET GLOBAL gtid_strict_mode=ON; diff --git a/docker/sql/users.sql b/docker/sql/users.sql new file mode 100644 index 000000000..4e2abd0f8 --- /dev/null +++ b/docker/sql/users.sql @@ -0,0 +1,7 @@ +RESET MASTER; + +CREATE USER 'maxuser'@'127.0.0.1' IDENTIFIED BY 'maxpwd'; +GRANT ALL ON *.* TO 'maxuser'@'127.0.0.1' WITH GRANT OPTION; + +CREATE USER 'maxuser'@'%' IDENTIFIED BY 'maxpwd'; +GRANT ALL ON *.* TO 'maxuser'@'%' WITH GRANT OPTION; diff --git a/maxctrl/lib/api.js b/maxctrl/lib/api.js new file mode 100644 index 000000000..835e43057 --- /dev/null +++ b/maxctrl/lib/api.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2020-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ +require('./common.js')() + +exports.command = 'api ' +exports.desc = 'Raw REST API access' +exports.handler = function() {} +exports.builder = function(yargs) { + yargs + .command('get [path]', 'Get raw JSON', function(yargs) { + return yargs.epilog('Perform a raw REST API call. ' + + 'The path definition uses JavaScript syntax to extract values. ' + + 'For example, the following command extracts all server states ' + + 'as an array of JSON values: maxctrl api get servers data[].attributes.state') + .usage('Usage: get [path]') + }, function(argv) { + maxctrl(argv, function(host) { + return doRequest(host, argv.resource, (res) => { + if (argv.path) { + res = _.getPath(res, argv.path, '') + } + + return JSON.stringify(res) + }) + }) + }) + .usage('Usage: api ') + .help() + .command('*', 'the default command', {}, function(argv) { + maxctrl(argv, function(host) { + return error('Unknown command. See output of `help api` for a list of commands.') + }) + }) +} diff --git a/maxctrl/lib/core.js b/maxctrl/lib/core.js index c3bd62a1a..74868a16f 100644 --- a/maxctrl/lib/core.js +++ b/maxctrl/lib/core.js @@ -100,6 +100,7 @@ program .command(require('./rotate.js')) .command(require('./call.js')) .command(require('./cluster.js')) + .command(require('./api.js')) .help() .demandCommand(1, 'At least one command is required') .command('*', 'the default command', {}, function(argv) { diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index f88588ec3..a2544e6ae 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -381,6 +381,9 @@ add_test_executable(max_connections.cpp max_connections replication LABELS MySQL # Test of Maxinfo interface (http) #add_test_executable(maxinfo.cpp maxinfocpp maxinfo LABELS maxinfo UNSTABLE HEAVY REPL_BACKEND) +# Test of Maxinfo SQL interface +add_test_executable(maxinfo_sql.cpp maxinfo_sql maxinfo_sql LABELS maxinfo REPL_BACKEND) + # Test of Maxinfo interface (http), python impelemntation add_test_script(maxinfo.py maxinfo.py maxinfo LABELS maxinfo LIGHT REPL_BACKEND) diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.maxinfo_sql b/maxscale-system-test/cnf/maxscale.cnf.template.maxinfo_sql new file mode 100644 index 000000000..1def8d09f --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.maxinfo_sql @@ -0,0 +1,71 @@ +[maxscale] +threads=4 + +[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 + +[MySQL Monitor] +type=monitor +module=mysqlmon +servers=server1,server2,server3,server4 +user=maxskysql +passwd=skysql +monitor_interval=1000 + +[Maxinfo] +type=service +router=maxinfo +user=maxuser +passwd=maxpwd +# Added here to allow users to be fetched from the backend server +servers=server1 + +[Maxinfo-SQL-Listener] +type=listener +service=Maxinfo +protocol=MySQLClient +port=4008 + +[RW Split Router] +type=service +router=readwritesplit +servers=server1,server2,server3,server4 +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 diff --git a/maxscale-system-test/maxinfo_sql.cpp b/maxscale-system-test/maxinfo_sql.cpp new file mode 100644 index 000000000..036544965 --- /dev/null +++ b/maxscale-system-test/maxinfo_sql.cpp @@ -0,0 +1,82 @@ +/** + * Test MaxInfo with the SQL interface + */ + +#include "testconnections.h" +#include +#include +#include +#include + +using namespace std; + +int main(int argc, char** argv) +{ + vector commands( + { + "SET SERVER server1 master", + "CLEAR SERVER server1 master", + "FLUSH LOGS", + "SHOW VARIABLES", + "SHOW VARIABLES LIKE '%version%'", + "SHOW STATUS", + "SHOW SERVICES", + "SHOW LISTENERS", + "SHOW SESSIONS", + "SHOW CLIENTS", + "SHOW SERVERS", + "SHOW MODULES", + "SHOW MONITORS", + "SHOW EVENTTIMES" + }); + + TestConnections test(argc, argv); + vector threads; + atomic run(true); + atomic wait(true); + + // Create some threads so that the SHOW SESSIONS will actually do something + for (int i = 0; i < 25; i++) + { + threads.emplace_back([&]() + { + while (wait) + { + sleep(1); + } + + while (run) + { + MYSQL* conn = test.maxscales->open_rwsplit_connection(); + for (int i = 0; i < 100; i++) + { + mysql_query(conn, "SELECT REPEAT('a', 10000), sleep(0.01) FROM dual"); + } + mysql_close(conn); + } + }); + } + + wait = false; + + MYSQL* conn = test.maxscales->open_readconn_master_connection(); + + for (int i = 0; i < 100; i++) + { + for (auto a : commands) + { + test.try_query(conn, "%s", a.c_str()); + } + } + + mysql_close(conn); + + run = false; + + for (auto& a : threads) + { + a.join(); + } + + return test.global_result; +} diff --git a/server/core/modulecmd.cc b/server/core/modulecmd.cc index 717fd19e1..970703eaa 100644 --- a/server/core/modulecmd.cc +++ b/server/core/modulecmd.cc @@ -124,7 +124,7 @@ static MODULECMD_DOMAIN* get_or_create_domain(const char *domain) for (dm = modulecmd_domains; dm; dm = dm->next) { - if (strcmp(dm->domain, domain) == 0) + if (strcasecmp(dm->domain, domain) == 0) { return dm; } @@ -210,7 +210,7 @@ static bool domain_has_command(MODULECMD_DOMAIN *dm, const char *id) { for (MODULECMD *cmd = dm->commands; cmd; cmd = cmd->next) { - if (strcmp(cmd->identifier, id) == 0) + if (strcasecmp(cmd->identifier, id) == 0) { return true; } @@ -463,11 +463,11 @@ const MODULECMD* modulecmd_find_command(const char *domain, const char *identifi for (MODULECMD_DOMAIN *dm = modulecmd_domains; dm; dm = dm->next) { - if (strcmp(effective_domain, dm->domain) == 0) + if (strcasecmp(effective_domain, dm->domain) == 0) { for (MODULECMD *cmd = dm->commands; cmd; cmd = cmd->next) { - if (strcmp(cmd->identifier, identifier) == 0) + if (strcasecmp(cmd->identifier, identifier) == 0) { rval = cmd; break; @@ -625,7 +625,7 @@ bool modulecmd_foreach(const char *domain_re, const char *ident_re, { int err; mxs_pcre2_result_t d_res = domain_re ? - mxs_pcre2_simple_match(domain_re, domain->domain, 0, &err) : + mxs_pcre2_simple_match(domain_re, domain->domain, PCRE2_CASELESS, &err) : MXS_PCRE2_MATCH; if (d_res == MXS_PCRE2_MATCH) @@ -633,7 +633,7 @@ bool modulecmd_foreach(const char *domain_re, const char *ident_re, for (MODULECMD *cmd = domain->commands; cmd && rval; cmd = cmd->next) { mxs_pcre2_result_t i_res = ident_re ? - mxs_pcre2_simple_match(ident_re, cmd->identifier, 0, &err) : + mxs_pcre2_simple_match(ident_re, cmd->identifier, PCRE2_CASELESS, &err) : MXS_PCRE2_MATCH; if (i_res == MXS_PCRE2_MATCH)