From 2b147a9ea4fac4e02a1caec67fc6774a7398025e Mon Sep 17 00:00:00 2001 From: VilhoRaatikka Date: Wed, 24 Sep 2014 12:03:04 +0300 Subject: [PATCH 1/2] Monitors waited monitor check interval time before checking backend servers for the first time. Removed wait for the first check. Added extra debugging to query_classifier to assist in issue resolution regarding to optimized MaxScale builds and pthread_mutex_lock in sql/sql_class.h --- query_classifier/query_classifier.cc | 37 +++++++++++++++++++++---- server/modules/monitor/galera_mon.c | 6 ++-- server/modules/monitor/mysql_mon.c | 6 ++-- server/modules/monitor/ndbcluster_mon.c | 6 ++-- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index f034d770f..ecf305308 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -359,17 +359,37 @@ static bool create_parse_tree( Parser_state parser_state; bool failp = FALSE; const char* virtual_db = "skygw_virtual"; - +#if defined(SS_DEBUG_EXTRA) + LOGIF(LM, (skygw_log_write_flush( + LOGFILE_MESSAGE, + "[readwritesplit:create_parse_tree] 1."))); +#endif if (parser_state.init(thd, thd->query(), thd->query_length())) { failp = TRUE; goto return_here; } - mysql_reset_thd_for_next_command(thd); - - /** Set some database to thd so that parsing won't fail because of - * missing database. Then parse. */ - failp = thd->set_db(virtual_db, strlen(virtual_db)); +#if defined(SS_DEBUG_EXTRA) + LOGIF(LM, (skygw_log_write_flush( + LOGFILE_MESSAGE, + "[readwritesplit:create_parse_tree] 2."))); +#endif + mysql_reset_thd_for_next_command(thd); +#if defined(SS_DEBUG_EXTRA) + LOGIF(LM, (skygw_log_write_flush( + LOGFILE_MESSAGE, + "[readwritesplit:create_parse_tree] 3."))); +#endif + /** + * Set some database to thd so that parsing won't fail because of + * missing database. Then parse. + */ + failp = thd->set_db(virtual_db, strlen(virtual_db)); +#if defined(SS_DEBUG_EXTRA) + LOGIF(LM, (skygw_log_write_flush( + LOGFILE_MESSAGE, + "[readwritesplit:create_parse_tree] 4."))); +#endif if (failp) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, @@ -377,6 +397,11 @@ static bool create_parse_tree( } failp = parse_sql(thd, &parser_state, NULL); +#if defined(SS_DEBUG_EXTRA) + LOGIF(LM, (skygw_log_write_flush( + LOGFILE_MESSAGE, + "[readwritesplit:create_parse_tree] 5."))); +#endif if (failp) { LOGIF(LD, (skygw_log_write( LOGFILE_DEBUG, diff --git a/server/modules/monitor/galera_mon.c b/server/modules/monitor/galera_mon.c index d2ad38264..f2e633db7 100644 --- a/server/modules/monitor/galera_mon.c +++ b/server/modules/monitor/galera_mon.c @@ -447,13 +447,15 @@ size_t nrounds = 0; } /** Wait base interval */ thread_millisleep(MON_BASE_INTERVAL_MS); - nrounds += 1; /** If monitor interval time isn't consumed skip checks */ - if ((nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) + if (nrounds != 0 && + (nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) { + nrounds += 1; continue; } + nrounds += 1; master_id = -1; ptr = handle->databases; diff --git a/server/modules/monitor/mysql_mon.c b/server/modules/monitor/mysql_mon.c index d7e0b34bd..4d917314f 100644 --- a/server/modules/monitor/mysql_mon.c +++ b/server/modules/monitor/mysql_mon.c @@ -611,13 +611,15 @@ size_t nrounds = 0; } /** Wait base interval */ thread_millisleep(MON_BASE_INTERVAL_MS); - nrounds += 1; /** If monitor interval time isn't consumed skip checks */ - if ((nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) + if (nrounds != 0 && + (nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) { + nrounds += 1; continue; } + nrounds += 1; /* reset num_servers */ num_servers = 0; diff --git a/server/modules/monitor/ndbcluster_mon.c b/server/modules/monitor/ndbcluster_mon.c index 2e009e000..46f5dd9ec 100644 --- a/server/modules/monitor/ndbcluster_mon.c +++ b/server/modules/monitor/ndbcluster_mon.c @@ -445,13 +445,15 @@ size_t nrounds = 0; /** Wait base interval */ thread_millisleep(MON_BASE_INTERVAL_MS); - nrounds += 1; /** If monitor interval time isn't consumed skip checks */ - if ((nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) + if (nrounds != 0 && + (nrounds*MON_BASE_INTERVAL_MS)%handle->interval != 0) { + nrounds += 1; continue; } + nrounds += 1; master_id = -1; ptr = handle->databases; From e8b5c2cbdf04820c4a12f5337336dafd79d1ddbd Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 24 Sep 2014 10:04:36 +0100 Subject: [PATCH 2/2] Updates to maxadmin to prevent hang when maxscale shuts down Addition of maxadmin test script --- client/maxadmin.c | 23 +++- client/test/maxadmin_test.sh | 189 ++++++++++++++++++++++++++++ server/modules/protocol/maxscaled.c | 2 +- 3 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 client/test/maxadmin_test.sh diff --git a/client/maxadmin.c b/client/maxadmin.c index dfb4dcfb5..97459171e 100644 --- a/client/maxadmin.c +++ b/client/maxadmin.c @@ -273,7 +273,10 @@ char c; } else if (*buf) { - sendCommand(so, buf); + if (!sendCommand(so, buf)) + { + return 0; + } } } @@ -298,6 +301,7 @@ connectMaxScale(char *hostname, char *port) { struct sockaddr_in addr; int so; +int keepalive = 1; if ((so = socket(AF_INET, SOCK_STREAM, 0)) < 0) { @@ -315,6 +319,9 @@ int so; hostname, port, strerror(errno)); return -1; } + if (setsockopt(so, SOL_SOCKET, + SO_KEEPALIVE, &keepalive , sizeof(keepalive ))) + perror("setsockopt"); return so; } @@ -387,11 +394,14 @@ authMaxScale(int so, char *user, char *password) { char buf[20]; - read(so, buf, 4); + if (read(so, buf, 4) != 4) + return 0; write(so, user, strlen(user)); - read(so, buf, 8); + if (read(so, buf, 8) != 8) + return 0; write(so, password, strlen(password)); - read(so, buf, 6); + if (read(so, buf, 6) != 6) + return 0; return strncmp(buf, "FAILED", 6); } @@ -412,10 +422,11 @@ sendCommand(int so, char *cmd) char buf[80]; int i, j, newline = 1; - write(so, cmd, strlen(cmd)); + if (write(so, cmd, strlen(cmd)) == -1) + return 0; while (1) { - if ((i = read(so, buf, 80)) == -1) + if ((i = read(so, buf, 80)) <= 0) return 0; for (j = 0; j < i; j++) { diff --git a/client/test/maxadmin_test.sh b/client/test/maxadmin_test.sh new file mode 100644 index 000000000..bb290b75a --- /dev/null +++ b/client/test/maxadmin_test.sh @@ -0,0 +1,189 @@ +#!/bin/sh +failure=0 +passed=0 +maxadmin -pskysql help >& /dev/null +if [ $? -eq "1" ]; then + echo "Auth test (correct password): Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Auth test (correct password): Passed" +fi +maxadmin -pwrongpasswd help >& /dev/null +if [ $? -eq "0" ]; then + echo "Auth test (wrong password): Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Auth test (wrong password): Passed" +fi +maxadmin --password=skysql help >& /dev/null +if [ $? -eq "1" ]; then + echo "Auth test (long option): Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Auth test (long option): Passed" +fi + +maxadmin -pskysql enable log debug >& /dev/null +if [ $? -eq "1" ]; then + echo "Enable debug log: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Enable debug log: Passed" +fi + +maxadmin -pskysql enable log trace >& /dev/null +if [ $? -eq "1" ]; then + echo "Enable trace log: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Enable trace log: Passed" +fi + +maxadmin -pskysql disable log debug >& /dev/null +if [ $? -eq "1" ]; then + echo "Disable debug log: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Disable debug log: Passed" +fi + +maxadmin -pskysql disable log trace >& /dev/null +if [ $? -eq "1" ]; then + echo "Disable trace log: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Disable trace log: Passed" +fi + +for cmd in clients dcbs filters listeners modules monitors services servers sessions threads +do + maxadmin -pskysql list $cmd | grep -s '-' >& /dev/null + if [ $? -eq "1" ]; then + echo "list command ($cmd): Failed" + failure=`expr $failure + 1` + else + passed=`expr $passed + 1` + echo "list command ($cmd): Passed" + fi +done + +for cmd in dcbs dbusers epoll filters modules monitors services servers sessions threads users +do + maxadmin -pskysql show $cmd | grep -s ' ' >& /dev/null + if [ $? -eq "1" ]; then + echo "show command ($cmd): Failed" + failure=`expr $failure + 1` + else + passed=`expr $passed + 1` + echo "show command ($cmd): Passed" + fi +done + +master=`maxadmin -pskysql list servers | awk '/Master/ { print $1; }'` +if [ $? -eq "1" ]; then + echo "Extract master server: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Extract master server: Passed" +fi +if [ "$master" = "" ]; then + echo "Get master server: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Get master server: Passed" +fi +maxadmin -pskysql show server $master | grep -s 'Master' >& /dev/null +if [ $? -eq "1" ]; then + echo "show server master: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "show server master: Passed" +fi + +maxadmin -pskysql set server $master maint >& /dev/null +if [ $? -eq "1" ]; then + echo "set server: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "set server: Passed" +fi +maxadmin -pskysql list servers | grep $master | grep -s Maint >& /dev/null +if [ $? -eq "1" ]; then + echo "set maintenance mode: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "set maintenance mode: Passed" +fi +maxadmin -pskysql clear server $master maint >& /dev/null +if [ $? -eq "1" ]; then + echo "clear server: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "clear server: Passed" +fi +maxadmin -pskysql list servers | grep $master | grep -s Maint >& /dev/null +if [ $? -eq "0" ]; then + echo "clear maintenance mode: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "clear maintenance mode: Passed" +fi + +dcbs=`maxadmin -pskysql list dcbs | awk -F\| '/listening/ { if ( NF > 1 ) print $1 }'` +if [ $? -eq "1" ]; then + echo "Get dcb listeners: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Get dcb listeners: Passed" +fi + +for i in $dcbs +do + maxadmin -pskysql show dcb $i | grep -s 'listening' >& /dev/null + if [ $? -eq "1" ]; then + echo "show dcb listeners: Failed" + failure=`expr $failure + 1` + else + passed=`expr $passed + 1` + echo "show dcb listeners: Passed" + fi +done + +sessions=`maxadmin -pskysql list sessions | awk -F\| '/Listener/ { if ( NF > 1 ) print $1 }'` +if [ $? -eq "1" ]; then + echo "Get listener sessions: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Get listener sessions: Passed" +fi + +for i in $sessions +do + maxadmin -pskysql show session $i | grep -s 'Listener' >& /dev/null + if [ $? -eq "1" ]; then + echo "show session listeners: Failed" + failure=`expr $failure + 1` + else + passed=`expr $passed + 1` + echo "show session listeners: Passed" + fi +done + +echo "Test run complete. $passed passes, $failure failures" +exit $failure diff --git a/server/modules/protocol/maxscaled.c b/server/modules/protocol/maxscaled.c index f580764f8..1ece013f9 100644 --- a/server/modules/protocol/maxscaled.c +++ b/server/modules/protocol/maxscaled.c @@ -279,6 +279,7 @@ int n_connect = 0; client_dcb->session = session_alloc(dcb->session->service, client_dcb); maxscaled_pr = (MAXSCALED *)malloc(sizeof(MAXSCALED)); + maxscaled_pr->username = NULL; client_dcb->protocol = (void *)maxscaled_pr; if (maxscaled_pr == NULL) @@ -294,7 +295,6 @@ int n_connect = 0; } n_connect++; maxscaled_pr->state = MAXSCALED_STATE_LOGIN; - maxscaled_pr->username = NULL; dcb_printf(client_dcb, "USER"); } }