Merge branch '2.2' into develop
This commit is contained in:
		@ -21,7 +21,7 @@ Here is a list of all possible values for the `router_options`.
 | 
			
		||||
Role|Description
 | 
			
		||||
------|---------
 | 
			
		||||
master|A server assigned as a master by one of MariaDB MaxScale monitors. Depending on the monitor implementation, this could be a master server of a Master-Slave replication cluster or a Write-Master of a Galera cluster.
 | 
			
		||||
slave|A server assigned as a slave of a master.
 | 
			
		||||
slave|A server assigned as a slave of a master. If all slaves are down, but the master is still available, then the router will use the master.
 | 
			
		||||
synced| A Galera cluster node which is in a synced state with the cluster.
 | 
			
		||||
ndb|A MySQL Replication Cluster node
 | 
			
		||||
running|A server that is up and running. All servers that MariaDB MaxScale can connect to are labeled as running.
 | 
			
		||||
 | 
			
		||||
@ -980,6 +980,10 @@ add_test_executable(mxs1836_show_eventTimes.cpp mxs1836_show_eventTimes mxs1836_
 | 
			
		||||
# MXS-173 throttling filter
 | 
			
		||||
add_test_executable(mxs173.cpp mxs173_throttle_filter mxs173_throttle_filter LABELS REPL_BACKEND)
 | 
			
		||||
 | 
			
		||||
 # MXS-1889: A single remaining master is valid for readconnroute configured with 'router_options=slave'
 | 
			
		||||
 # https://jira.mariadb.org/browse/MXS-1889
 | 
			
		||||
add_test_executable(mxs1889.cpp mxs1889 mxs1889 LABELS REPL_BACKEND)
 | 
			
		||||
 | 
			
		||||
configure_file(templates.h.in templates.h @ONLY)
 | 
			
		||||
 | 
			
		||||
include(CTest)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										89
									
								
								maxscale-system-test/cnf/maxscale.cnf.template.mxs1889
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								maxscale-system-test/cnf/maxscale.cnf.template.mxs1889
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
[maxscale]
 | 
			
		||||
threads=###threads###
 | 
			
		||||
log_info=on
 | 
			
		||||
 | 
			
		||||
[MySQL Monitor]
 | 
			
		||||
type=monitor
 | 
			
		||||
module=mysqlmon
 | 
			
		||||
###repl51###
 | 
			
		||||
servers=server1,server2,server3,server4
 | 
			
		||||
user=maxskysql
 | 
			
		||||
passwd=skysql
 | 
			
		||||
monitor_interval=1000
 | 
			
		||||
 | 
			
		||||
[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=###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
 | 
			
		||||
							
								
								
									
										85
									
								
								maxscale-system-test/mxs1889.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								maxscale-system-test/mxs1889.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
/**
 | 
			
		||||
 * MXS-1889: A single remaining master is valid for readconnroute configured with 'router_options=slave'
 | 
			
		||||
 *
 | 
			
		||||
 * https://jira.mariadb.org/browse/MXS-1889
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "testconnections.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
string get_server_id(TestConnections& test, MYSQL* pMysql)
 | 
			
		||||
{
 | 
			
		||||
    string id;
 | 
			
		||||
 | 
			
		||||
    int rv = mysql_query(pMysql, "SELECT @@server_id");
 | 
			
		||||
    test.add_result(rv, "Could not execute query.");
 | 
			
		||||
 | 
			
		||||
    if (rv == 0)
 | 
			
		||||
    {
 | 
			
		||||
        MYSQL_RES* pResult = mysql_store_result(pMysql);
 | 
			
		||||
        test.assert(pResult, "Could not store result.");
 | 
			
		||||
 | 
			
		||||
        if (pResult)
 | 
			
		||||
        {
 | 
			
		||||
            unsigned int n = mysql_field_count(pMysql);
 | 
			
		||||
            test.assert(n == 1, "Unexpected number of fields.");
 | 
			
		||||
 | 
			
		||||
            MYSQL_ROW pzRow = mysql_fetch_row(pResult);
 | 
			
		||||
            test.assert(pzRow, "Returned row was NULL.");
 | 
			
		||||
 | 
			
		||||
            if (pzRow)
 | 
			
		||||
            {
 | 
			
		||||
                id = pzRow[0];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mysql_free_result(pResult);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
    TestConnections test(argc, argv);
 | 
			
		||||
 | 
			
		||||
    test.tprintf("Taking down all slaves.");
 | 
			
		||||
    test.repl->stop_node(1);
 | 
			
		||||
    test.repl->stop_node(2);
 | 
			
		||||
    test.repl->stop_node(3);
 | 
			
		||||
 | 
			
		||||
    test.tprintf("Giving monitor time to detect the situation...");
 | 
			
		||||
    sleep(5);
 | 
			
		||||
 | 
			
		||||
    test.maxscales->connect();
 | 
			
		||||
 | 
			
		||||
    // All slaves down, so we expect a connection to the master.
 | 
			
		||||
    string master_id = get_server_id(test, test.maxscales->conn_slave[0]);
 | 
			
		||||
    test.tprintf("Master id: %s", master_id.c_str());
 | 
			
		||||
 | 
			
		||||
    test.maxscales->disconnect();
 | 
			
		||||
 | 
			
		||||
    test.tprintf("Starting all slaves.");
 | 
			
		||||
    test.repl->start_node(3);
 | 
			
		||||
    test.repl->start_node(2);
 | 
			
		||||
    test.repl->start_node(1);
 | 
			
		||||
 | 
			
		||||
    test.tprintf("Giving monitor time to detect the situation...");
 | 
			
		||||
    sleep(5);
 | 
			
		||||
 | 
			
		||||
    test.maxscales->connect();
 | 
			
		||||
 | 
			
		||||
    string slave_id = get_server_id(test, test.maxscales->conn_slave[0]);
 | 
			
		||||
    test.tprintf("Server id: %s", slave_id.c_str());
 | 
			
		||||
    test.assert(slave_id != master_id, "Expected something else but %s", master_id.c_str());
 | 
			
		||||
 | 
			
		||||
    return test.global_result;
 | 
			
		||||
}
 | 
			
		||||
@ -49,6 +49,7 @@ typedef struct router_client_session
 | 
			
		||||
    SERVER_REF *backend; /*< Backend used by the client session */
 | 
			
		||||
    DCB *backend_dcb; /*< DCB Connection to the backend      */
 | 
			
		||||
    DCB *client_dcb; /**< Client DCB */
 | 
			
		||||
    unsigned int bitvalue; /*< Session specific required value of server->status */
 | 
			
		||||
    struct router_client_session *next;
 | 
			
		||||
#if defined(SS_DEBUG)
 | 
			
		||||
    skygw_chk_t rses_chk_tail;
 | 
			
		||||
 | 
			
		||||
@ -286,6 +286,7 @@ newSession(MXS_ROUTER *instance, MXS_SESSION *session)
 | 
			
		||||
    client_rses->rses_chk_tail = CHK_NUM_ROUTER_SES;
 | 
			
		||||
#endif
 | 
			
		||||
    client_rses->client_dcb = session->client_dcb;
 | 
			
		||||
    client_rses->bitvalue = inst->bitvalue;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Find the Master host from available servers
 | 
			
		||||
@ -397,6 +398,17 @@ newSession(MXS_ROUTER *instance, MXS_SESSION *session)
 | 
			
		||||
        if (master_host)
 | 
			
		||||
        {
 | 
			
		||||
            candidate = master_host;
 | 
			
		||||
            // Even if we had 'router_options=slave' in the configuration file, we
 | 
			
		||||
            // will still end up here if there are no slaves, but a sole master. So
 | 
			
		||||
            // that the server will be considered valid in connection_is_valid(), we
 | 
			
		||||
            // turn on the SERVER_MASTER bit.
 | 
			
		||||
            //
 | 
			
		||||
            // We must do that so that readconnroute in MaxScale 2.2 will again behave
 | 
			
		||||
            // the same way as it did up until 2.1.12.
 | 
			
		||||
            if (client_rses->bitvalue & SERVER_SLAVE)
 | 
			
		||||
            {
 | 
			
		||||
                client_rses->bitvalue |= SERVER_MASTER;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
@ -542,10 +554,17 @@ static inline bool connection_is_valid(ROUTER_INSTANCE* inst, ROUTER_CLIENT_SES*
 | 
			
		||||
{
 | 
			
		||||
    bool rval = false;
 | 
			
		||||
 | 
			
		||||
    // inst->bitvalue and router_cli_ses->bitvalue are different, if we had
 | 
			
		||||
    // 'router_options=slave' in the configuration file and there was only
 | 
			
		||||
    // the sole master available at session creation time.
 | 
			
		||||
 | 
			
		||||
    if (SERVER_IS_RUNNING(router_cli_ses->backend->server) &&
 | 
			
		||||
        (router_cli_ses->backend->server->status & inst->bitmask & inst->bitvalue))
 | 
			
		||||
        (router_cli_ses->backend->server->status & inst->bitmask & router_cli_ses->bitvalue))
 | 
			
		||||
    {
 | 
			
		||||
        if ((inst->bitvalue == SERVER_MASTER) && router_cli_ses->backend->active)
 | 
			
		||||
        // Note the use of '==' and not '|'. We must use the former to exclude a
 | 
			
		||||
        // 'router_options=slave' that uses the master due to no slave having been
 | 
			
		||||
        // available at session creation time. Its bitvalue is (SERVER_MASTER | SERVER_SLAVE).
 | 
			
		||||
        if ((router_cli_ses->bitvalue == SERVER_MASTER) && router_cli_ses->backend->active)
 | 
			
		||||
        {
 | 
			
		||||
            // If we're using an active master server, verify that it is still a master
 | 
			
		||||
            rval = router_cli_ses->backend == get_root_master(inst->service->dbref);
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user