Merge branch '2.1' into develop
This commit is contained in:
commit
457fc80647
@ -1,4 +1,4 @@
|
||||
# MariaDB MaxScale 2.1.2 Release Notes
|
||||
# MariaDB MaxScale 2.1.2 Release Notes -- 2017-04-03
|
||||
|
||||
Release 2.1.2 is a Beta release.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# MariaDB MaxScale 2.1.3 Release Notes
|
||||
# MariaDB MaxScale 2.1.3 Release Notes -- 2017-05-23
|
||||
|
||||
Release 2.1.3 is a GA release.
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <maxscale/version.h>
|
||||
|
||||
@ -253,6 +254,11 @@ main(int argc, char **argv)
|
||||
|
||||
if ((so = connectUsingInetSocket(hostname, port, user, passwd)) == -1)
|
||||
{
|
||||
if (access(MAXADMIN_DEFAULT_SOCKET, R_OK) == 0)
|
||||
{
|
||||
fprintf(stderr, "Found default MaxAdmin socket in: %s\n", MAXADMIN_DEFAULT_SOCKET);
|
||||
fprintf(stderr, "Try connecting with:\n\n\tmaxadmin -S %s\n\n", MAXADMIN_DEFAULT_SOCKET);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -597,7 +603,13 @@ authUnixSocket(int so)
|
||||
|
||||
if (!authenticated)
|
||||
{
|
||||
fprintf(stderr, "Could connect to MaxScale, but was not authorized.\n");
|
||||
uid_t id = geteuid();
|
||||
struct passwd* pw = getpwuid(id);
|
||||
fprintf(stderr, "Could connect to MaxScale, but was not authorized.\n"
|
||||
"Check that the current user is added to the list of allowed users.\n"
|
||||
"To add this user to the list, execute:\n\n"
|
||||
"\tsudo maxadmin enable account %s\n\n"
|
||||
"This assumes that the root user account is enabled in MaxScale.\n", pw->pw_name);
|
||||
}
|
||||
|
||||
return authenticated;
|
||||
|
@ -121,7 +121,7 @@ add_test_executable(bug547.cpp bug547 replication LABELS readwritesplit REPL_BAC
|
||||
add_test_executable(bug681.cpp bug681 galera.bug681 LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Regression case for the bug "crash with tee filter"
|
||||
add_test_executable(bug643.cpp bug643 bug643 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug643.cpp bug643 bug643 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug ""Different error messages from MariaDB and Maxscale"
|
||||
add_test_script(bug561.sh bug561.sh replication LABELS MySQLAuth REPL_BACKEND)
|
||||
@ -166,13 +166,13 @@ add_test_executable(bug626.cpp bug626 replication LABELS MySQLAuth MySQLProtocol
|
||||
add_test_executable(bug634.cpp bug634 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Regression cases for several TEE filter hangs
|
||||
add_test_executable(bug645.cpp bug645 bug645 LABELS tee REPL_BACKEND)
|
||||
add_test_executable(bug645_1.cpp bug645_1 bug645_1 LABELS tee REPL_BACKEND)
|
||||
add_test_executable(bug649.cpp bug649 bug645 LABELS tee)
|
||||
add_test_executable(bug650.cpp bug650 bug650 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug645.cpp bug645 bug645 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug645_1.cpp bug645_1 bug645_1 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug649.cpp bug649 bug645 LABELS tee)
|
||||
#add_test_executable(bug650.cpp bug650 bug650 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Heavy test for TEE filter
|
||||
add_test_script(bug648 sql_queries bug648 LABELS tee UNSTABLE HEAVY REPL_BACKEND)
|
||||
#add_test_script(bug648 sql_queries bug648 LABELS tee UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Crash when host name for some user in mysql.user is very long
|
||||
add_test_executable(bug653.cpp bug653 replication LABELS MySQLAuth MySQLProtocol REPL_BACKEND)
|
||||
@ -181,7 +181,7 @@ add_test_executable(bug653.cpp bug653 replication LABELS MySQLAuth MySQLProtocol
|
||||
add_test_executable(bug654.cpp bug654 replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Tee filter: closing child session causes MaxScale to fail"
|
||||
add_test_executable(bug657.cpp bug657 bug657 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug657.cpp bug657 bug657 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Block backends (master or all slaves) and tries to connect Maxscale
|
||||
add_test_executable(bug658.cpp bug658 replication LABELS readwritesplit readconnroute maxscale REPL_BACKEND)
|
||||
@ -193,7 +193,7 @@ add_test_executable(bug662.cpp bug662 replication LABELS readwritesplit readconn
|
||||
add_test_executable(bug664.cpp bug664 bug664 LABELS MySQLAuth MySQLProtocol)
|
||||
|
||||
# TEE fileter: execute long sequence of queries ans session commands in the loop
|
||||
add_test_executable(bug670.cpp bug670 bug670 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(bug670.cpp bug670 bug670 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "MaxScale crashes if "Users table data" is empty and "show dbusers" is executed in maxadmin"
|
||||
add_test_executable(bug673.cpp bug673 bug673 LABELS MySQLAuth REPL_BACKEND)
|
||||
@ -327,7 +327,7 @@ add_test_executable(mm.cpp mm mm LABELS mmmon BREAKS_REPL)
|
||||
add_test_executable(mm_mysqlmon.cpp mm_mysqlmon mm_mysqlmon LABELS mysqlmon REPL_BACKEND BREAKS_REPL)
|
||||
|
||||
# MySQL Monitor crash safety
|
||||
add_test_executable(mysqlmon_backup.cpp mysqlmon_backup mysqlmon_backup LABELS mysqlmon REPL_BACKEND)
|
||||
#add_test_executable(mysqlmon_backup.cpp mysqlmon_backup mysqlmon_backup LABELS mysqlmon REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Two monitors loaded at the same time result into not working installation"
|
||||
add_test_executable(mxs118.cpp mxs118 mxs118 LABELS maxscale LIGHT REPL_BACKEND)
|
||||
@ -366,7 +366,7 @@ add_test_executable(mxs431.cpp mxs431 sharding LABELS schemarouter REPL_BACKEND
|
||||
add_test_executable(mxs47.cpp mxs47 replication LABELS MySQLProtocol LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "USE <db> hangs when Tee filter uses matching"
|
||||
add_test_executable(mxs501_tee_usedb.cpp mxs501_tee_usedb mxs501 LABELS tee REPL_BACKEND)
|
||||
#add_test_executable(mxs501_tee_usedb.cpp mxs501_tee_usedb mxs501 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Open connection, execute 'change user', close connection in the loop
|
||||
add_test_executable(mxs548_short_session_change_user.cpp mxs548_short_session_change_user mxs548 LABELS MySQLProtocol REPL_BACKEND)
|
||||
@ -422,7 +422,7 @@ add_test_executable(mxs822_maxpasswd.cpp mxs822_maxpasswd maxpasswd LABELS maxsc
|
||||
|
||||
# Do only SELECTS during time > wait_timeout and then do INSERT
|
||||
# This test will fail because the functionality hasn't been implemented
|
||||
add_test_executable(mxs827_write_timeout.cpp mxs827_write_timeout mxs827_write_timeout LABELS readwritesplit REPL_BACKEND)
|
||||
#add_test_executable(mxs827_write_timeout.cpp mxs827_write_timeout mxs827_write_timeout LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Block and unblock first and second slaves and check that they are recovered
|
||||
add_test_executable(mxs874_slave_recovery.cpp mxs874_slave_recovery mxs874 LABELS readwritesplit REPL_BACKEND)
|
||||
@ -536,8 +536,8 @@ add_test_executable(rwsplit_read_only_trx.cpp rwsplit_read_only_trx rwsplit_read
|
||||
|
||||
# Test replication-manager with MaxScale
|
||||
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)
|
||||
#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)
|
||||
|
||||
# Schemarouter duplicate database detection test: create DB on all nodes and then try query againt schema router
|
||||
add_test_executable(schemarouter_duplicate_db.cpp schemarouter_duplicate_db schemarouter_duplicate_db LABELS schemarouter REPL_BACKEND)
|
||||
@ -584,8 +584,12 @@ add_test_script(sql_queries_pers10 sql_queries sql_queries_pers10 LABELS maxscal
|
||||
# Execute queries of different size, check data is the same when accessing via Maxscale and directly to backend, client ssl is ON
|
||||
add_test_script(ssl sql_queries ssl LABELS maxscale readwritesplit REPL_BACKEND)
|
||||
|
||||
|
||||
# Check load balancing, client ssl is ON
|
||||
add_test_script(ssl_load load_balancing ssl_load LABELS maxscale readwritesplit REPL_BACKEND)
|
||||
|
||||
# Disabled due to some strangeness in Connector-C 3.0 TLS connections which
|
||||
# cause uneven distribution of connections.
|
||||
#add_test_script(ssl_load load_balancing ssl_load LABELS maxscale readwritesplit REPL_BACKEND)
|
||||
|
||||
# Check load balancing, client ssl is ON, Galera backend
|
||||
add_test_script(ssl_load_galera load_balancing_galera ssl_load_galera LABELS maxscale readwritesplit GALERA_BACKEND)
|
||||
@ -606,7 +610,7 @@ add_test_executable(test_hints.cpp test_hints hints2 LABELS hintfilter LIGHT REP
|
||||
add_test_executable(avro.cpp avro avro LABELS avrorouter binlogrouter LIGHT BREAKS_REPL)
|
||||
|
||||
# Test avrorouter file compression
|
||||
add_test_script(avro_compression avro avro_compression LABELS avrorouter binlogrouter LIGHT BREAKS_REPL)
|
||||
#add_test_script(avro_compression avro avro_compression LABELS avrorouter binlogrouter LIGHT BREAKS_REPL)
|
||||
|
||||
# In the binlog router setup stop Master and promote one of the Slaves to be new Master
|
||||
add_test_executable(binlog_change_master.cpp binlog_change_master setup_binlog_tx_safe LABELS binlogrouter BREAKS_REPL)
|
||||
@ -680,7 +684,7 @@ add_test_executable(kerberos_setup.cpp kerberos_setup kerberos LABELS HEAVY gssa
|
||||
#add_test_executable(bad_pers.cpp bad_pers bad_pers LABELS REPL_BACKEND)
|
||||
|
||||
# Test Aurora RDS monitor
|
||||
add_test_executable(auroramon.cpp auroramon auroramon LABELS HEAVY EXTERNAL_BACKEND)
|
||||
#add_test_executable(auroramon.cpp auroramon auroramon LABELS HEAVY EXTERNAL_BACKEND)
|
||||
|
||||
# Disabled for the time being
|
||||
# add_test_executable(gatekeeper.cpp gatekeeper gatekeeper LABELS gatekeeper)
|
||||
|
@ -25,45 +25,33 @@ using std::endl;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(600);
|
||||
Test->stop_maxscale();
|
||||
Test->ssh_maxscale(true, (char *) "rm -rf /var/lib/maxscale/avro");
|
||||
TestConnections test(argc, argv);
|
||||
test.set_timeout(600);
|
||||
test.ssh_maxscale(true, (char *) "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], "DROP TABLE IF EXISTS t1");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
/** Start master to binlogrouter replication */
|
||||
if (!test.replicate_from_master())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
test.set_timeout(120);
|
||||
test.repl->connect();
|
||||
|
||||
Test->start_binlog();
|
||||
create_t1(test.repl->nodes[0]);
|
||||
insert_into_t1(test.repl->nodes[0], 3);
|
||||
execute_query(test.repl->nodes[0], "FLUSH LOGS");
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->stop_maxscale();
|
||||
|
||||
Test->ssh_maxscale(true, "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->start_maxscale();
|
||||
|
||||
Test->set_timeout(60);
|
||||
|
||||
Test->repl->connect();
|
||||
create_t1(Test->repl->nodes[0]);
|
||||
insert_into_t1(Test->repl->nodes[0], 3);
|
||||
execute_query(Test->repl->nodes[0], "FLUSH LOGS");
|
||||
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->set_timeout(120);
|
||||
test.repl->close_connections();
|
||||
|
||||
/** Give avrorouter some time to process the events */
|
||||
test.stop_timeout();
|
||||
sleep(10);
|
||||
test.set_timeout(120);
|
||||
|
||||
char * avro_check = Test->ssh_maxscale_output(true,
|
||||
"maxavrocheck -vv /var/lib/maxscale/avro/test.t1.000001.avro | grep \"{\"");
|
||||
char * output = Test->ssh_maxscale_output(true, "maxavrocheck -d /var/lib/maxscale/avro/test.t1.000001.avro");
|
||||
char * avro_check = test.ssh_maxscale_output(true,
|
||||
"maxavrocheck -vv /var/lib/maxscale/avro/test.t1.000001.avro | grep \"{\"");
|
||||
char * output = test.ssh_maxscale_output(true, "maxavrocheck -d /var/lib/maxscale/avro/test.t1.000001.avro");
|
||||
|
||||
std::istringstream iss;
|
||||
iss.str(output);
|
||||
@ -74,13 +62,13 @@ int main(int argc, char *argv[])
|
||||
for (std::string line; std::getline(iss, line);)
|
||||
{
|
||||
long long int x1, fl;
|
||||
Test->set_timeout(20);
|
||||
test.set_timeout(20);
|
||||
get_x_fl_from_json((char*)line.c_str(), &x1, &fl);
|
||||
|
||||
if (x1 != x1_exp || fl != fl_exp)
|
||||
{
|
||||
Test->add_result(1, "Output:x1 %lld, fl %lld, Expected: x1 %d, fl %d",
|
||||
x1, fl, x1_exp, fl_exp);
|
||||
test.add_result(1, "Output:x1 %lld, fl %lld, Expected: x1 %d, fl %d",
|
||||
x1, fl, x1_exp, fl_exp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -89,19 +77,17 @@ int main(int argc, char *argv[])
|
||||
x1_exp = 0;
|
||||
x = x * 16;
|
||||
fl_exp++;
|
||||
Test->tprintf("fl = %d", fl_exp);
|
||||
test.tprintf("fl = %d", fl_exp);
|
||||
}
|
||||
}
|
||||
|
||||
if (fl_exp != 3)
|
||||
{
|
||||
Test->add_result(1, "not enough lines in avrocheck output\n");
|
||||
test.add_result(1, "not enough lines in avrocheck output");
|
||||
}
|
||||
|
||||
Test->set_timeout(120);
|
||||
execute_query(test.repl->nodes[0], "DROP TABLE test.t1;RESET MASTER");
|
||||
test.repl->fix_replication();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
return test.global_result;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,10 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the connections to clean up
|
||||
Test->stop_timeout();
|
||||
sleep(5);
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
|
@ -25,6 +25,7 @@ TestConnections * Test ;
|
||||
int exit_flag;
|
||||
int master = 0;
|
||||
int i_trans = 0;
|
||||
const int trans_max = 100;
|
||||
int failed_transaction_num = 0;
|
||||
|
||||
/** The amount of rows each transaction inserts */
|
||||
@ -294,7 +295,7 @@ void *transaction_thread( void *ptr )
|
||||
Test->add_result(mysql_errno(conn), "Error connecting to Binlog router, error: %s\n", mysql_error(conn));
|
||||
create_t1(conn);
|
||||
|
||||
while ((exit_flag == 0))
|
||||
while ((exit_flag == 0) && i_trans < trans_max)
|
||||
{
|
||||
Test->tprintf("Transaction %d\n", i_trans);
|
||||
trans_result = transaction(conn, i_trans);
|
||||
|
@ -43,12 +43,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Trying some queries, expecting failure, but not a crash\n");
|
||||
execute_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t1");
|
||||
execute_query(Test->conn_rwsplit, (char *) "CREATE TABLE t1 (x INT)");
|
||||
execute_query(Test->conn_rwsplit, (char *) "INSERT INTO t1 (x) VALUES (1)");
|
||||
execute_query(Test->conn_rwsplit, (char *) "select * from t1");
|
||||
execute_query(Test->conn_master, (char *) "select * from t1");
|
||||
execute_query(Test->conn_slave, (char *) "select * from t1");
|
||||
execute_query(Test->conn_rwsplit, "DROP TABLE IF EXISTS t1");
|
||||
execute_query(Test->conn_rwsplit, "CREATE TABLE t1 (x INT)");
|
||||
execute_query(Test->conn_rwsplit, "INSERT INTO t1 (x) VALUES (1)");
|
||||
execute_query(Test->conn_rwsplit, "select * from t1");
|
||||
execute_query(Test->conn_master, "select * from t1");
|
||||
execute_query(Test->conn_slave, "select * from t1");
|
||||
|
||||
Test->set_timeout(10);
|
||||
Test->close_maxscale_connections();
|
||||
@ -58,12 +58,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
Test->stop_timeout();
|
||||
sleep(15);
|
||||
Test->check_log_err((char *) "fatal signal 11", false);
|
||||
Test->check_log_err((char *) "Failed to create new router session for service 'RW-Split-Router'", true);
|
||||
Test->check_log_err((char *)
|
||||
"Failed to create new router session for service 'Read-Connection-Router-Master'", true);
|
||||
Test->check_log_err((char *) "Failed to create new router session for service 'Read-Connection-Router-Slave'",
|
||||
true);
|
||||
Test->check_log_err("fatal signal 11", false);
|
||||
Test->check_log_err("Failed to create new router session for service", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
|
@ -22,16 +22,6 @@ service=RW Split Router
|
||||
* - check warnig in the log "RW Split Router: Recursive use of tee filter in service"
|
||||
*/
|
||||
|
||||
/*
|
||||
Mark Riddoch 2014-12-11 11:59:19 UTC
|
||||
There is a recursive use of the tee filter in the configuration.
|
||||
|
||||
The "RW Split Router" uses the"duplicate" filter that will then duplicate all traffic to the original destination and another copy of the "RW Split Router", which again will duplicate all traffic to the original destination and another copy of the "RW Split Router"...
|
||||
|
||||
Really this needs to be trapped as a configuration error.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
@ -56,7 +46,7 @@ int main(int argc, char *argv[])
|
||||
Test->add_result(1, "FAIL: Query to broken service succeeded!\n");
|
||||
}
|
||||
Test->close_maxscale_connections();
|
||||
Test->check_log_err((char *) "RW-Split-Router: Recursive use of tee filter in service", true);
|
||||
Test->check_log_err("Recursive use of tee filter in service", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
|
@ -124,6 +124,11 @@ int main(int argc, char *argv[])
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "show processlist;");
|
||||
Test->close_rwsplit();
|
||||
|
||||
/** Clean up */
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], "DROP DATABASE test");
|
||||
execute_query(Test->repl->nodes[0], "CREATE DATABASE test");
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
|
@ -40,42 +40,6 @@ service=RW Split Router
|
||||
* - Reconnect readconnrouter
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-12-22 08:35:52 UTC
|
||||
How to reproduce:
|
||||
1. Configure readconnrouter with tee filter and tee filter with a readwritesplit as a child service.
|
||||
2. Start MaxScale
|
||||
3. Connect readconnrouter
|
||||
4. Fail the master node
|
||||
5. Reconnect readconnrouter
|
||||
|
||||
As a consequence, next routeQuery will be duplicated to closed readwritesplit router and eventually fred memory will be accessed which causes SEGFAULT.
|
||||
|
||||
Reason for this is that situation where child (=branch -) session is closed as a consequence of node failure, is not handled in tee filter. Tee filter handles the case where client closes the session.
|
||||
Comment 1 Vilho Raatikka 2014-12-22 09:14:13 UTC
|
||||
Background: client session may be closed for different reasons. If client actively closes it by sending COM_QUIT packet, it happens from top to bottom: packet is identified and client DCB is closed. Client's DCB close routine also closes the client router session.
|
||||
|
||||
If backend fails and monitor detects it, then every DCB that isn't running or isn't master, slave, joined (Galera) nor ndb calls its hangup function. If the failed node was master then client session gets state SESSION_STATE_STOPPING which triggers first closing the client DCB and as a part of it, the whole session.
|
||||
|
||||
In tee filter, the first issue is the client DCB's close routine which doesn't trigger closing the session. The other issue is that if child session gets closed there's no mechanism that would prevent future queries being routed to tee's child service. As a consequence, future calls to routeQuery will access closed child session including freed memory etc.
|
||||
Comment 2 Vilho Raatikka 2014-12-22 22:32:25 UTC
|
||||
session.c:session_free:if session is child of another service (tee in this case), it is the parent which releases child's allocated memory back to the system. This now also includes the child router session.
|
||||
dcb.h: Added DCB_IS_CLONE macro
|
||||
tee.c:freeSession:if parent session triggered closing of tee, then child session may not be closed yet. In that case free the child session first and only then free child router session and release child session's memory back to system.
|
||||
tee.c:routeQuery: only route if child session is ready for routing. Log if session is not ready for routing and set tee session inactive
|
||||
mysql_client.c:gw_client_close:if DCB is cloned one don't close the protocol because they it is shared with the original DCB.
|
||||
Comment 3 Vilho Raatikka 2014-12-23 10:04:11 UTC
|
||||
If monitor haven't yet changed the status for failed backend, even the fixed won't notice the failure, and the client is left waiting for reply until some lower level timeout exceeds and closes the socket.
|
||||
|
||||
The solution is to register a callback function to readconnrouter's backend DCB in the same way that it is done in readwritesplit. Callback needs to be implemented and tests added.
|
||||
By using this mechanism the client must wait at most one monitor interval before the session is closed.
|
||||
|
||||
Vilho Raatikka 2014-12-31 23:19:41 UTC
|
||||
filter.c:filter_free:if filter parameter is NULL, return.
|
||||
tee.c:freeSession: if my_session->dummy_filterdef is NULL, don't try to release the memory
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
|
@ -44,8 +44,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_log_err((char *)
|
||||
"Unable to start RW-Split-Router service. There are too few backend servers configured in", true);
|
||||
Test->check_log_err("There are too few backend servers configured in", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
|
@ -204,6 +204,14 @@ bool Connection::readRow(std::string& dest)
|
||||
else
|
||||
{
|
||||
dest += buf;
|
||||
|
||||
if (dest[0] == 'E' && dest[1] == 'R' & dest[2] == 'R')
|
||||
{
|
||||
m_error = "Server responded with an error: ";
|
||||
m_error += dest;
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,6 +143,7 @@ bool run_test(TestConnections& test)
|
||||
{
|
||||
bool rval = true;
|
||||
|
||||
test.tprintf("Inserting data");
|
||||
for (int x = 0; test_set[x].types; x++)
|
||||
{
|
||||
for (int i = 0; test_set[x].types[i]; i++)
|
||||
@ -152,6 +153,7 @@ bool run_test(TestConnections& test)
|
||||
}
|
||||
}
|
||||
|
||||
test.tprintf("Waiting for avrorouter to process data");
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[0], "FLUSH LOGS");
|
||||
test.repl->close_connections();
|
||||
@ -196,6 +198,7 @@ bool run_test(TestConnections& test)
|
||||
std::string err = conn.getError();
|
||||
test.tprintf("Failed to request data: %s", err.c_str());
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
test.stop_timeout();
|
||||
}
|
||||
@ -209,8 +212,7 @@ int main(int argc, char *argv[])
|
||||
TestConnections::check_nodes(false);
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
test.start_binlog();
|
||||
test.restart_maxscale();
|
||||
test.replicate_from_master();
|
||||
|
||||
if (!run_test(test))
|
||||
{
|
||||
|
@ -38,7 +38,9 @@ public:
|
||||
|
||||
bool operator ==(const TestOutput& output) const
|
||||
{
|
||||
return m_value == output.getValue();
|
||||
return m_value == output.getValue() ||
|
||||
(m_type.find("BLOB") != std::string::npos &&
|
||||
output.getValue().length() == 0);
|
||||
}
|
||||
|
||||
bool operator !=(const TestOutput& output) const
|
||||
|
@ -1,6 +1,5 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
log_warning=1
|
||||
|
||||
[Galera Monitor]
|
||||
type=monitor
|
||||
@ -17,11 +16,13 @@ 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
|
||||
router_options=slave
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
@ -39,7 +40,6 @@ type=listener
|
||||
service=RW Split Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
#socket=/tmp/rwsplit.sock
|
||||
|
||||
[Read Connection Listener Slave]
|
||||
type=listener
|
||||
@ -53,6 +53,16 @@ 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###
|
||||
@ -76,14 +86,3 @@ type=server
|
||||
address=###galera_server_IP_4###
|
||||
port=###galera_server_port_4###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
#address=localhost
|
||||
socket=default
|
||||
|
@ -44,6 +44,16 @@ protocol=MySQLClient
|
||||
port=4008
|
||||
#socket=/tmp/readconn.sock
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
socket=default
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=###galera_server_IP_1###
|
||||
|
@ -101,3 +101,13 @@ type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
socket=default
|
||||
|
@ -87,4 +87,3 @@ type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
||||
|
||||
|
@ -17,6 +17,7 @@ max_slave_connections=1
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
router_options=disable_sescmd_history=false
|
||||
|
||||
[Read Connection Router Slave]
|
||||
type=service
|
||||
@ -53,6 +54,16 @@ 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###
|
||||
|
@ -36,7 +36,7 @@ int main(int argc, char *argv[])
|
||||
sprintf(str, "rules%d", i);
|
||||
Test->set_timeout(180);
|
||||
copy_rules(Test, str, rules_dir);
|
||||
Test->ssh_maxscale(true, "maxadmin call command dbfwfilter rules/reload Database-Firewall");
|
||||
Test->ssh_maxscale(true, "maxadmin call command dbfwfilter rules/reload \"Database Firewall\"");
|
||||
|
||||
int local_result = 0;
|
||||
sprintf(pass_file, "%s/fw/pass%d", test_dir, i);
|
||||
|
@ -461,14 +461,14 @@ int get_conn_num(MYSQL *conn, char * ip, char *hostname, char * db)
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
unsigned long long int num_fields;
|
||||
//unsigned long long int row_i=0;
|
||||
unsigned long long int rows;
|
||||
unsigned long long int i;
|
||||
unsigned int conn_num = 0;
|
||||
char * hostname_internal;
|
||||
const char * hostname_internal;
|
||||
|
||||
if (strcmp(ip, "127.0.0.1") == 0)
|
||||
{
|
||||
hostname_internal = (char*) "localhost";
|
||||
hostname_internal = "localhost";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -516,9 +516,9 @@ int get_conn_num(MYSQL *conn, char * ip, char *hostname, char * db)
|
||||
}
|
||||
if (strcmp(ip, "127.0.0.1") == 0)
|
||||
{
|
||||
// one extra connection i svisible in the processlist
|
||||
// one extra connection is visible in the process list
|
||||
// output in case of local test
|
||||
// (when maxscale is on the same machine as backends)
|
||||
// (when MaxScale is on the same machine as backends)
|
||||
conn_num--;
|
||||
}
|
||||
return conn_num;
|
||||
|
@ -18,13 +18,22 @@ function(add_java_test name src entry_point template)
|
||||
endfunction()
|
||||
|
||||
# Some constants that make changing the connector easier
|
||||
set(JDBC_JAR ${CMAKE_CURRENT_SOURCE_DIR}/mariadb-java-client-1.5.4.jar CACHE INTERNAL "")
|
||||
set(JDBC_JAR_NAME "mariadb-java-client-1.5.9.jar")
|
||||
set(JDBC_JAR ${CMAKE_CURRENT_BINARY_DIR}/${JDBC_JAR_NAME} CACHE INTERNAL "")
|
||||
set(MXS_JAR ${CMAKE_CURRENT_BINARY_DIR}/maxscale_java.jar CACHE INTERNAL "")
|
||||
set(TEST_JARPATH "${MXS_JAR}:${JDBC_JAR}" CACHE INTERNAL "")
|
||||
|
||||
# If we don't have the JDBC driver, download it
|
||||
if(NOT EXISTS ${JDBC_JAR})
|
||||
message(STATUS "Downloading MariaDB Connector-J: ${JDBC_JAR_NAME}")
|
||||
file(DOWNLOAD https://downloads.mariadb.com/Connectors/java/connector-java-1.5.9/mariadb-java-client-1.5.9.jar
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${JDBC_JAR_NAME}
|
||||
SHOW_PROGRESS)
|
||||
endif()
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/MaxScaleConfiguration.java.in ${CMAKE_CURRENT_BINARY_DIR}/MaxScaleConfiguration.java @ONLY)
|
||||
add_jar(maxscale_java SOURCES MaxScaleConnection.java MaxScaleConfiguration.java
|
||||
INCLUDE_JARS mariadb-java-client-1.5.4.jar)
|
||||
INCLUDE_JARS ${JDBC_JAR_NAME})
|
||||
add_subdirectory(test1)
|
||||
add_subdirectory(prep_stmt)
|
||||
add_subdirectory(batch)
|
||||
|
Binary file not shown.
@ -42,7 +42,7 @@ void check_status(TestConnections *Test, const char *server, const char *status)
|
||||
void check_group(TestConnections *Test, const char *server, const char *group)
|
||||
{
|
||||
|
||||
char *output = Test->ssh_maxscale_output(true, "maxadmin show monitor MySQL-Monitor");
|
||||
char *output = Test->ssh_maxscale_output(true, "maxadmin show monitor \"MySQL Monitor\"");
|
||||
|
||||
if (output == NULL)
|
||||
{
|
||||
|
@ -34,9 +34,10 @@ int main(int argc, char *argv[])
|
||||
test->ssh_maxscale(true, "cp /etc/maxscale.cnf.backup /etc/maxscale.cnf");
|
||||
|
||||
/** Set router_options to a bad value */
|
||||
test->ssh_maxscale(true, "sed -i -e 's/router_options.*/router_options=bad_option=true/' /etc/maxscale.cnf");
|
||||
test->add_result(baseline == test->ssh_maxscale(true, "maxscale -c --user=maxscale"),
|
||||
"Bad router_options should be detected.\n");
|
||||
// Disabled for 2.0
|
||||
//test->ssh_maxscale(true, "sed -i -e 's/router_options.*/router_options=bad_option=true/' /etc/maxscale.cnf");
|
||||
//test->add_result(baseline == test->ssh_maxscale(true, "maxscale -c --user=maxscale"),
|
||||
// "Bad router_options should be detected.\n");
|
||||
|
||||
test->ssh_maxscale(true, "cp /etc/maxscale.cnf.backup /etc/maxscale.cnf");
|
||||
|
||||
|
@ -31,7 +31,7 @@ void try_password(TestConnections* Test, char * pass)
|
||||
*/
|
||||
Test->tprintf("Encrypting password: %s", pass);
|
||||
Test->set_timeout(30);
|
||||
int rc = Test->ssh_maxscale(true, "maxpasswd '%s' | tr -dc '[:xdigit:]' > /tmp/pw.txt && "
|
||||
int rc = Test->ssh_maxscale(true, "maxpasswd /var/lib/maxscale/ '%s' | tr -dc '[:xdigit:]' > /tmp/pw.txt && "
|
||||
"sed -i 's/user=.*/user=test/' /etc/maxscale.cnf && "
|
||||
"sed -i \"s/passwd=.*/passwd=$(cat /tmp/pw.txt)/\" /etc/maxscale.cnf && "
|
||||
"service maxscale restart && "
|
||||
|
@ -132,7 +132,7 @@ int main(int argc, char *argv[])
|
||||
Test->tprintf("Connecting to RWSplit %s\n", Test->maxscale_IP);
|
||||
Test->connect_rwsplit();
|
||||
|
||||
Test->execute_maxadmin_command((char *) "shutdown monitor MySQL-Monitor");
|
||||
Test->execute_maxadmin_command((char *) "shutdown monitor \"MySQL Monitor\"");
|
||||
|
||||
get_global_status_allnodes(&selects[0], &inserts[0], Test->repl, silent);
|
||||
|
||||
|
@ -30,7 +30,7 @@ int main(int argc, char *argv[])
|
||||
Test->try_query(Test->routers[j], (char*) "select 1;");
|
||||
Test->try_query(Test->routers[j], (char*) "set autocommit=1;");
|
||||
Test->try_query(Test->routers[j], (char*) "select 2;");
|
||||
if ((i / 100) * 100 == i)
|
||||
if ((i / 1000) * 1000 == i)
|
||||
{
|
||||
Test->tprintf("i=%d\n", i);
|
||||
}
|
||||
|
@ -16,59 +16,37 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(20);
|
||||
TestConnections test(argc, argv);
|
||||
printf("Connecting to RWSplit");
|
||||
test.set_timeout(60);
|
||||
test.add_result(test.connect_rwsplit(), "Error connection to RWSplit! Exiting");
|
||||
sleep(5);
|
||||
|
||||
test.tprintf("Checking current slave");
|
||||
int res = 0;
|
||||
int old_slave = test.find_connected_slave(&res);
|
||||
test.add_result(res, "no current slave");
|
||||
|
||||
unsigned int current_slave;
|
||||
unsigned int old_slave;
|
||||
test.tprintf("Setup firewall to block mysql on old slave (oldslave is node %d)", old_slave);
|
||||
|
||||
printf("Connecting to RWSplit %s\n", Test->maxscale_IP);
|
||||
if (Test->connect_rwsplit() != 0)
|
||||
{
|
||||
Test->add_result(1, "Error connection to RWSplit! Exiting\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
test.add_result((old_slave < 0) || (old_slave >= test.repl->N), "Active slave is not found");
|
||||
test.repl->block_node(old_slave);
|
||||
|
||||
Test->tprintf("Checking current slave\n");
|
||||
old_slave = Test->find_connected_slave( &res);
|
||||
test.tprintf("Waiting for MaxScale to find a new slave");
|
||||
test.stop_timeout();
|
||||
sleep(10);
|
||||
|
||||
Test->add_result(res, "no current slave\n");
|
||||
test.set_timeout(20);
|
||||
int current_slave = test.find_connected_slave(&res);
|
||||
test.add_result((current_slave == old_slave) || (current_slave < 0), "No failover happened");
|
||||
|
||||
Test->tprintf("Setup firewall to block mysql on old slave (oldslave is node %d)\n", old_slave);
|
||||
if ((old_slave < 0) || (old_slave >= Test->repl->N))
|
||||
{
|
||||
Test->add_result(1, "Active slave is not found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->repl->block_node(old_slave);
|
||||
test.tprintf("Unblock old node");
|
||||
test.repl->unblock_node(old_slave);
|
||||
test.close_rwsplit();
|
||||
|
||||
Test->tprintf("Sleeping 60 seconds to let MaxScale to find new slave\n");
|
||||
Test->stop_timeout();
|
||||
sleep(60);
|
||||
Test->set_timeout(20);
|
||||
test.check_maxscale_alive();
|
||||
test.stop_timeout();
|
||||
test.repl->fix_replication();
|
||||
|
||||
current_slave = Test->find_connected_slave(&res);
|
||||
if ((current_slave == old_slave) || (current_slave < 0))
|
||||
{
|
||||
Test->add_result(1, "No failover happened\n");
|
||||
}
|
||||
|
||||
Test->tprintf("Setup firewall back to allow mysql\n");
|
||||
Test->repl->unblock_node(old_slave);
|
||||
|
||||
Test->close_rwsplit();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
Test->set_timeout(20);
|
||||
}
|
||||
Test->set_timeout(200);
|
||||
Test->repl->start_replication();
|
||||
}
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
return test.global_result;
|
||||
}
|
||||
|
@ -954,6 +954,44 @@ int TestConnections::start_binlog()
|
||||
return global_result;
|
||||
}
|
||||
|
||||
bool TestConnections::replicate_from_master()
|
||||
{
|
||||
bool rval = true;
|
||||
|
||||
/** Stop the binlogrouter */
|
||||
MYSQL* conn = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
|
||||
|
||||
if (execute_query(conn, "stop slave"))
|
||||
{
|
||||
rval = false;
|
||||
}
|
||||
mysql_close(conn);
|
||||
|
||||
/** Clean up MaxScale directories */
|
||||
prepare_binlog();
|
||||
ssh_maxscale(true, "service maxscale restart");
|
||||
|
||||
char log_file[256] = "";
|
||||
char log_pos[256] = "4";
|
||||
|
||||
repl->execute_query_all_nodes("STOP SLAVE");
|
||||
repl->connect();
|
||||
execute_query(repl->nodes[0], "RESET MASTER");
|
||||
|
||||
conn = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
|
||||
|
||||
if (find_field(repl->nodes[0], "show master status", "File", log_file) ||
|
||||
repl->set_slave(conn, repl->IP[0], repl->port[0], log_file, log_pos) ||
|
||||
execute_query(conn, "start slave"))
|
||||
{
|
||||
rval = false;
|
||||
}
|
||||
|
||||
mysql_close(conn);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int TestConnections::start_mm()
|
||||
{
|
||||
int i;
|
||||
|
@ -442,6 +442,11 @@ public:
|
||||
*/
|
||||
int start_binlog();
|
||||
|
||||
/**
|
||||
* @brief Start binlogrouter replication from master
|
||||
*/
|
||||
bool replicate_from_master();
|
||||
|
||||
/**
|
||||
* @brief prepare_binlog clean up binlog directory, set proper access rights to it
|
||||
* @return 0
|
||||
|
@ -413,19 +413,34 @@ auto_ptr<MaskingRules::Rule> create_rule_from_elements(json_t* pReplace,
|
||||
json_t* pValue = json_object_get(pWith, KEY_VALUE);
|
||||
json_t* pFill = json_object_get(pWith, KEY_FILL);
|
||||
|
||||
if ((pValue || pFill) &&
|
||||
(!pValue || json_is_string(pValue)) &&
|
||||
(!pFill || json_is_string(pFill)))
|
||||
if (!pFill)
|
||||
{
|
||||
sRule = create_rule_from_elements(pColumn, pTable, pDatabase,
|
||||
pValue, pFill,
|
||||
pApplies_to, pExempted);
|
||||
// Allowed. Use default value for fill and add it to pWith.
|
||||
pFill = json_string("X");
|
||||
if (pFill)
|
||||
{
|
||||
json_object_set_new(pWith, KEY_FILL, pFill);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("json_string() error, cannot produce a valid rule.");
|
||||
}
|
||||
}
|
||||
else
|
||||
if (pFill)
|
||||
{
|
||||
MXS_ERROR("The '%s' object of a masking rule does not have either '%s' "
|
||||
"or '%s' as keys, or their values are not strings.",
|
||||
KEY_WITH, KEY_VALUE, KEY_FILL);
|
||||
if ((!pValue || (json_is_string(pValue) && json_string_length(pValue))) &&
|
||||
(json_is_string(pFill) && json_string_length(pFill)))
|
||||
{
|
||||
sRule = create_rule_from_elements(pColumn, pTable, pDatabase,
|
||||
pValue, pFill,
|
||||
pApplies_to, pExempted);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("One of the keys '%s' or '%s' of masking rule object '%s' "
|
||||
"has a non-string value or the string is empty.",
|
||||
KEY_VALUE, KEY_FILL, KEY_WITH);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -16,7 +16,6 @@
|
||||
# pip install kafka-python
|
||||
#
|
||||
|
||||
import json
|
||||
import sys
|
||||
import argparse
|
||||
from kafka import KafkaProducer
|
||||
@ -30,8 +29,6 @@ parser.add_argument("-T", "--kafka-topic", dest="kafka_topic",
|
||||
default=None, required=True)
|
||||
|
||||
opts = parser.parse_args(sys.argv[1:])
|
||||
decoder = json.JSONDecoder()
|
||||
rbuf = bytes()
|
||||
producer = KafkaProducer(bootstrap_servers=[opts.kafka_broker])
|
||||
|
||||
while True:
|
||||
@ -41,18 +38,9 @@ while True:
|
||||
if len(buf) == 0:
|
||||
break
|
||||
|
||||
rbuf += buf.encode()
|
||||
|
||||
while True:
|
||||
rbuf = rbuf.lstrip()
|
||||
data = decoder.raw_decode(rbuf.decode('utf_8'))
|
||||
rbuf = rbuf[data[1]:]
|
||||
producer.send(topic=opts.kafka_topic, value=json.dumps(data[0]).encode())
|
||||
producer.flush()
|
||||
|
||||
# JSONDecoder will return a ValueError if a partial JSON object is read
|
||||
except ValueError as err:
|
||||
pass
|
||||
data = buf.encode().strip()
|
||||
producer.send(topic=opts.kafka_topic, value=data)
|
||||
producer.flush()
|
||||
|
||||
# All other errors should interrupt the processing
|
||||
except Exception as ex:
|
||||
|
@ -426,6 +426,12 @@ createInstance(SERVICE *service, char **options)
|
||||
inst->block_size = config_get_integer(params, "block_size");
|
||||
|
||||
MXS_CONFIG_PARAMETER *param = config_get_param(params, "source");
|
||||
inst->gtid.domain = 0;
|
||||
inst->gtid.event_num = 0;
|
||||
inst->gtid.seq = 0;
|
||||
inst->gtid.server_id = 0;
|
||||
inst->gtid.timestamp = 0;
|
||||
memset(&inst->active_maps, 0, sizeof(inst->active_maps));
|
||||
bool err = false;
|
||||
|
||||
if (param)
|
||||
@ -719,11 +725,9 @@ static void freeSession(MXS_ROUTER* router_instance, MXS_ROUTER_SESSION* router_
|
||||
{
|
||||
AVRO_INSTANCE *router = (AVRO_INSTANCE *) router_instance;
|
||||
AVRO_CLIENT *client = (AVRO_CLIENT *) router_client_ses;
|
||||
int prev_val;
|
||||
|
||||
prev_val = atomic_add(&router->stats.n_clients, -1);
|
||||
ss_debug(int prev_val = )atomic_add(&router->stats.n_clients, -1);
|
||||
ss_dassert(prev_val > 0);
|
||||
(void) prev_val;
|
||||
|
||||
free(client->uuid);
|
||||
maxavro_file_close(client->file_handle);
|
||||
@ -778,9 +782,6 @@ static void closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_sessio
|
||||
|
||||
spinlock_release(&client->file_lock);
|
||||
spinlock_release(&client->catch_lock);
|
||||
|
||||
/* decrease server registered slaves counter */
|
||||
atomic_add(&router->stats.n_clients, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,6 +114,7 @@ AVRO_TABLE* avro_table_alloc(const char* filepath, const char* json_schema, cons
|
||||
&table->avro_schema))
|
||||
{
|
||||
MXS_ERROR("Avro error: %s", avro_strerror());
|
||||
MXS_INFO("Avro schema: %s", json_schema);
|
||||
MXS_FREE(table);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ void avro_index_file(AVRO_INSTANCE *router, const char* filename)
|
||||
errmsg = NULL;
|
||||
prev_gtid = gtid;
|
||||
}
|
||||
json_decref(row);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -205,7 +206,7 @@ void avro_update_index(AVRO_INSTANCE* router)
|
||||
/** The SQL for the in-memory used_tables table */
|
||||
static const char *insert_sql = "INSERT OR IGNORE INTO "MEMORY_TABLE_NAME
|
||||
"(domain, server_id, sequence, binlog_timestamp, table_name)"
|
||||
" VALUES (%lu, %lu, %lu, %lu, \"%s\")";
|
||||
" VALUES (%lu, %lu, %lu, %u, \"%s\")";
|
||||
|
||||
/**
|
||||
* @brief Add a used table to the current transaction
|
||||
|
@ -102,16 +102,16 @@ char* json_new_schema_from_table(TABLE_MAP *map)
|
||||
json_object_set_new(schema, "name", json_string("ChangeRecord"));
|
||||
|
||||
json_t *array = json_array();
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_domain, "type", "int"));
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_server_id, "type", "int"));
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_sequence, "type", "int"));
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_event_number, "type", "int"));
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_timestamp, "type", "int"));
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_domain, "type", "int"));
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_server_id, "type", "int"));
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_sequence, "type", "int"));
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_event_number, "type", "int"));
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s}", "name",
|
||||
avro_timestamp, "type", "int"));
|
||||
|
||||
/** Enums and other complex types are defined with complete JSON objects
|
||||
* instead of string values */
|
||||
@ -119,16 +119,19 @@ char* json_new_schema_from_table(TABLE_MAP *map)
|
||||
"name", "EVENT_TYPES", "symbols", "insert",
|
||||
"update_before", "update_after", "delete");
|
||||
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:o}", "name", avro_event_type,
|
||||
"type", event_types));
|
||||
// Ownership of `event_types` is stolen when using the `o` format
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:o}", "name", avro_event_type,
|
||||
"type", event_types));
|
||||
|
||||
for (uint64_t i = 0; i < map->columns; i++)
|
||||
{
|
||||
json_array_append(array, json_pack_ex(&err, 0, "{s:s, s:s, s:s, s:i}",
|
||||
"name", create->column_names[i],
|
||||
"type", column_type_to_avro_type(map->column_types[i]),
|
||||
"real_type", create->column_types[i],
|
||||
"length", create->column_lengths[i]));
|
||||
ss_info_dassert(create->column_names[i] && *create->column_names[i],
|
||||
"Column name should not be empty or NULL");
|
||||
json_array_append_new(array, json_pack_ex(&err, 0, "{s:s, s:s, s:s, s:i}",
|
||||
"name", create->column_names[i],
|
||||
"type", column_type_to_avro_type(map->column_types[i]),
|
||||
"real_type", create->column_types[i],
|
||||
"length", create->column_lengths[i]));
|
||||
}
|
||||
json_object_set_new(schema, "fields", array);
|
||||
char* rval = json_dumps(schema, JSON_PRESERVE_ORDER);
|
||||
@ -543,6 +546,7 @@ static const char *extract_field_name(const char* ptr, char* dest, size_t size)
|
||||
dest[bytes] = '\0';
|
||||
|
||||
make_valid_avro_identifier(dest);
|
||||
ss_dassert(strlen(dest) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -555,7 +559,7 @@ static const char *extract_field_name(const char* ptr, char* dest, size_t size)
|
||||
int extract_type_length(const char* ptr, char *dest)
|
||||
{
|
||||
/** Skip any leading whitespace */
|
||||
while (isspace(*ptr) || *ptr == '`')
|
||||
while (*ptr && (isspace(*ptr) || *ptr == '`'))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
@ -565,7 +569,7 @@ int extract_type_length(const char* ptr, char *dest)
|
||||
|
||||
/** Skip characters until we either hit a whitespace character or the start
|
||||
* of the length definition. */
|
||||
while (!isspace(*ptr) && *ptr != '(')
|
||||
while (*ptr && !isspace(*ptr) && *ptr != '(')
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
@ -576,7 +580,7 @@ int extract_type_length(const char* ptr, char *dest)
|
||||
dest[typelen] = '\0';
|
||||
|
||||
/** Skip whitespace */
|
||||
while (isspace(*ptr))
|
||||
while (*ptr && isspace(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
@ -641,6 +645,7 @@ static int process_column_definition(const char *nameptr, char*** dest, char***
|
||||
lengths[i] = len;
|
||||
types[i] = MXS_STRDUP_A(type);
|
||||
names[i] = MXS_STRDUP_A(colname);
|
||||
ss_info_dassert(*names[i] && *types[i], "`name` and `type` must not be empty");
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -1575,8 +1575,8 @@ struct subcommand alteroptions[] =
|
||||
"\n"
|
||||
"address Server address\n"
|
||||
"port Server port\n"
|
||||
"monuser Monitor user for this server\n"
|
||||
"monpw Monitor password for this server\n"
|
||||
"monitoruser Monitor user for this server\n"
|
||||
"monitorpw Monitor password for this server\n"
|
||||
"ssl Enable SSL, value must be 'required'\n"
|
||||
"ssl_key Path to SSL private key\n"
|
||||
"ssl_cert Path to SSL certificate\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user