diff --git a/deps/Makefile b/deps/Makefile index 3c616b1e8..e2a7c0e7e 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -41,6 +41,7 @@ mariadb-client-library/mariadb_client/include/my_config.h: cd mariadb-client-library/mariadb_client && cmake . cd mariadb-client-library/mariadb_client && patch libmariadb/libmariadb.c < ../libmariadb.c.patch cd mariadb-client-library/mariadb_client && patch libmariadb/net.c < ../net.c.patch + cd mariadb-client-library/mariadb_client && patch libmariadb/mysql_async.c < ../mysql_async.c.patch cd mariadb-client-library/mariadb_client && patch include/mysql.h < ../mysql.h.patch cd mariadb-client-library/mariadb_client && CC=${CC} CXX=${CXX} ${MAKE} # cd mariadb-client-library/mariadb_client/include && make my_config.h diff --git a/deps/mariadb-client-library/libmariadb.c.patch b/deps/mariadb-client-library/libmariadb.c.patch index c478ffcb1..e67aa82cd 100644 --- a/deps/mariadb-client-library/libmariadb.c.patch +++ b/deps/mariadb-client-library/libmariadb.c.patch @@ -15,3 +15,40 @@ } my_free((gptr)mysql->options.extension, MYF(MY_ALLOW_ZERO_PTR)); /* clear all pointer */ +@@ -2256,6 +2266,36 @@ + + /* reset the connection in all active statements + todo: check stmt->mysql in mysql_stmt* functions ! */ ++ for (;li_stmt;li_stmt= li_stmt->next) ++ { ++ stmt= (MYSQL_STMT *)li_stmt->data; ++ stmt->mysql= NULL; ++ SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); ++ } ++ mysql_close_memory(mysql); ++ mysql_close_options(mysql); ++ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; ++ ++ /* Clear pointers for better safety */ ++ bzero((char*) &mysql->options,sizeof(mysql->options)); ++ mysql->net.vio= 0; ++ if (mysql->free_me) ++ my_free((gptr) mysql,MYF(0)); ++ } ++ DBUG_VOID_RETURN; ++} ++ ++void STDCALL ++mysql_close_no_command(MYSQL *mysql) ++{ ++ MYSQL_STMT *stmt; ++ DBUG_ENTER("mysql_close"); ++ if (mysql) /* Some simple safety */ ++ { ++ LIST *li_stmt= mysql->stmts; ++ ++ /* reset the connection in all active statements ++ todo: check stmt->mysql in mysql_stmt* functions ! */ + for (;li_stmt;li_stmt= li_stmt->next) + { + stmt= (MYSQL_STMT *)li_stmt->data; diff --git a/deps/mariadb-client-library/mysql.h.patch b/deps/mariadb-client-library/mysql.h.patch index 331871ccd..79f981869 100644 --- a/deps/mariadb-client-library/mysql.h.patch +++ b/deps/mariadb-client-library/mysql.h.patch @@ -1,9 +1,10 @@ -@@ -420,6 +420,8 @@ +@@ -420,6 +420,9 @@ unsigned long clientflag); void STDCALL mysql_close(MYSQL *sock); int STDCALL mysql_select_db(MYSQL *mysql, const char *db); +int STDCALL mysql_select_db_start(int *ret, MYSQL *mysql, const char *db); +int STDCALL mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status); ++void STDCALL mysql_close_no_command(MYSQL *sock); int STDCALL mysql_query(MYSQL *mysql, const char *q); int STDCALL mysql_send_query(MYSQL *mysql, const char *q, unsigned long length); diff --git a/deps/mariadb-client-library/mysql_async.c.patch b/deps/mariadb-client-library/mysql_async.c.patch new file mode 100644 index 000000000..ef4712767 --- /dev/null +++ b/deps/mariadb-client-library/mysql_async.c.patch @@ -0,0 +1,9 @@ +@@ -805,7 +805,7 @@ + int res; + + /* It is legitimate to have NULL sock argument, which will do nothing. */ +- if (sock) ++ if (sock && sock->net.vio) + { + res= mysql_close_slow_part_start(sock); + /* If we need to block, return now and do the rest in mysql_close_cont(). */ diff --git a/include/MySQL_Data_Stream.h b/include/MySQL_Data_Stream.h index 0cf3fc0c8..0adff907a 100644 --- a/include/MySQL_Data_Stream.h +++ b/include/MySQL_Data_Stream.h @@ -184,10 +184,11 @@ class MySQL_Data_Stream void return_MySQL_Connection_To_Pool(); - void destroy_MySQL_Connection_From_Pool() { + void destroy_MySQL_Connection_From_Pool(bool sq) { MySQL_Connection *mc=myconn; detach_connection(); unplug_backend(); + mc->send_quit=sq; MyHGM->destroy_MyConn_from_pool(mc); } void free_mysql_real_query(); diff --git a/include/mysql_connection.h b/include/mysql_connection.h index 95c0af95b..b19744fcb 100644 --- a/include/mysql_connection.h +++ b/include/mysql_connection.h @@ -39,6 +39,7 @@ class MySQL_Connection { short wait_events; unsigned long long timeout; char scramble_buff[40]; + bool send_quit; int async_exit_status; // exit status of MariaDB Client Library Non blocking API int interr; // integer return my_bool ret_bool; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index e76c833c4..9028d151f 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -703,10 +703,10 @@ void MySQL_HostGroups_Manager::destroy_MyConn_from_pool(MySQL_Connection *c) { MySrvC *mysrvc=(MySrvC *)c->parent; proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "Destroying MySQL_Connection %p, server %s:%d\n", c, mysrvc->address, mysrvc->port); mysrvc->ConnectionsUsed->remove(c); - delete c; status.myconnpoll_destroy++; status.server_connections_created--; wrunlock(); + delete c; } diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 17d27631b..ff42de5b7 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -742,7 +742,7 @@ handler_again: } else { if (rc==-1) { proxy_error("Detected a broken connection during ping on %s , %d\n", myconn->parent->address, myconn->parent->port); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; delete mybe->server_myds; mybe->server_myds=NULL; @@ -898,7 +898,7 @@ handler_again: retry_conn=true; } } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -920,7 +920,7 @@ handler_again: retry_conn=true; } } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -945,7 +945,7 @@ handler_again: if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) { retry_conn=true; } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(true); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -1021,7 +1021,7 @@ handler_again: if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) { retry_conn=true; } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -1037,7 +1037,7 @@ handler_again: char sqlstate[10]; sprintf(sqlstate,"#%s",mysql_sqlstate(myconn->mysql)); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,mysql_errno(myconn->mysql),sqlstate,mysql_error(myconn->mysql)); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(true); myds->fd=0; status=WAITING_CLIENT_DATA; client_myds->DSS=STATE_SLEEP; @@ -1077,7 +1077,7 @@ handler_again: if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) { retry_conn=true; } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -1093,7 +1093,7 @@ handler_again: char sqlstate[10]; sprintf(sqlstate,"#%s",mysql_sqlstate(myconn->mysql)); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,mysql_errno(myconn->mysql),sqlstate,mysql_error(myconn->mysql)); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(true); myds->fd=0; status=WAITING_CLIENT_DATA; client_myds->DSS=STATE_SLEEP; @@ -1133,7 +1133,7 @@ handler_again: if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) { retry_conn=true; } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -1149,7 +1149,7 @@ handler_again: char sqlstate[10]; sprintf(sqlstate,"#%s",mysql_sqlstate(myconn->mysql)); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,mysql_errno(myconn->mysql),sqlstate,mysql_error(myconn->mysql)); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(true); myds->fd=0; status=WAITING_CLIENT_DATA; client_myds->DSS=STATE_SLEEP; @@ -1190,7 +1190,7 @@ handler_again: if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) { retry_conn=true; } - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); myds->fd=0; if (retry_conn) { myds->DSS=STATE_NOT_INITIALIZED; @@ -1208,7 +1208,7 @@ handler_again: client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,mysql_errno(myconn->mysql),sqlstate,mysql_error(myconn->mysql)); // CurrentQuery.end(); // myds->free_mysql_real_query(); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(true); myds->fd=0; // status=WAITING_CLIENT_DATA; // client_myds->DSS=STATE_SLEEP; @@ -1239,10 +1239,10 @@ handler_again: } if (mybe->server_myds->myconn) { //mybe->server_myds->destroy_MySQL_Connection(); - mybe->server_myds->destroy_MySQL_Connection_From_Pool(); + mybe->server_myds->destroy_MySQL_Connection_From_Pool(false); } mybe->server_myds->max_connect_time=0; - NEXT_IMMEDIATE(WAITING_CLIENT_DATA); + NEXT_IMMEDIATE(WAITING_CLIENT_DATA); } } if (mybe->server_myds->myconn==NULL) { @@ -1288,7 +1288,7 @@ handler_again: if (myds->connect_retries_on_failure >0 ) { myds->connect_retries_on_failure--; //myds->destroy_MySQL_Connection(); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool(false); NEXT_IMMEDIATE(CONNECTING_SERVER); } else { int myerr=mysql_errno(myconn->mysql); @@ -1310,7 +1310,7 @@ handler_again: previous_status.pop(); } //myds->destroy_MySQL_Connection(); - myds->destroy_MySQL_Connection_From_Pool(); + myds->destroy_MySQL_Connection_From_Pool( myerr ? true : false ); myds->max_connect_time=0; NEXT_IMMEDIATE(WAITING_CLIENT_DATA); } diff --git a/lib/mysql_backend.cpp b/lib/mysql_backend.cpp index 416ac08eb..573fdb371 100644 --- a/lib/mysql_backend.cpp +++ b/lib/mysql_backend.cpp @@ -30,7 +30,7 @@ void MySQL_Backend::reset() { //server_myds->myconn=NULL; //server_myds->unplug_backend(); } else { - server_myds->destroy_MySQL_Connection_From_Pool(); + server_myds->destroy_MySQL_Connection_From_Pool(true); //MyHGM->destroy_MyConn_from_pool(server_myds->myconn); //server_myds->myconn=NULL; } diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 7b6261d53..4b6cc4fa9 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -139,6 +139,7 @@ MySQL_Connection::MySQL_Connection() { mysql=NULL; async_state_machine=ASYNC_CONNECT_START; ret_mysql=NULL; + send_quit=true; myds=NULL; inserted_into_pool=0; reusable=false; @@ -169,7 +170,10 @@ MySQL_Connection::~MySQL_Connection() { } if (mysql) { async_free_result(); - mysql_close(mysql); + if (send_quit) { + mysql_close_start(mysql); + } + mysql_close_no_command(mysql); mysql=NULL; } // // FIXME: with the use of mysql client library , this part should be gone.