From 9cdebef9ca91a3310013f7e3bac29fe925c570e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Tue, 17 Feb 2015 18:43:48 +0000 Subject: [PATCH] Bug fix and improved debugging For better debugging, added functions: MySQL_Data_Stream::clean_net_failure() MySQL_Data_Stream::set_net_failure() MySQL_Data_Stream::setDSS_STATE_QUERY_SENT_NET() MySQL_Session::set_unhealthy() Added condition mybe->server_myds->PSarrayOUTpending->len==0 to determine if DSS can be STATE_QUERY_SENT_NET --- include/mysql_data_stream.h | 4 +++ include/mysql_session.h | 1 + lib/MySQL_Session.cpp | 46 +++++++++++++++++++++-------------- lib/Standard_MySQL_Thread.cpp | 9 ++++--- lib/mysql_connection.cpp | 1 + lib/mysql_data_stream.cpp | 26 +++++++++++++++++--- 6 files changed, 62 insertions(+), 25 deletions(-) diff --git a/include/mysql_data_stream.h b/include/mysql_data_stream.h index 670ef35ae..65853cd80 100644 --- a/include/mysql_data_stream.h +++ b/include/mysql_data_stream.h @@ -97,6 +97,10 @@ class MySQL_Data_Stream void set_pollout(); void mysql_free(); + void clean_net_failure(); + void set_net_failure(); + void setDSS_STATE_QUERY_SENT_NET(); + int read_pkts(); int write_pkts(); diff --git a/include/mysql_session.h b/include/mysql_session.h index f415172bb..62b277be4 100644 --- a/include/mysql_session.h +++ b/include/mysql_session.h @@ -104,6 +104,7 @@ class MySQL_Session // MySQL_Session(int); ~MySQL_Session(); + void set_unhealthy(); //MySQL_Protocol myprot_client; //MySQL_Protocol myprot_server; diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index b54ba914c..0e79f8bc7 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -341,7 +341,7 @@ int MySQL_Session::handler() { // server_myds=mybe->server_myds; //} mybe->server_myds->PSarrayOUT->add(pkt.ptr, pkt.size); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); } else { // this is processed by the admin module admin_func(this, GloAdmin, &pkt); @@ -535,6 +535,8 @@ __exit_DSS__STATE_NOT_INITIALIZED: && mybe->server_myds->PSarrayOUT->len==0 && + mybe->server_myds->PSarrayOUTpending->len==0 + && mybe->server_myds->net_failure==false && mybe->server_myds->available_data_out()==false @@ -542,11 +544,12 @@ __exit_DSS__STATE_NOT_INITIALIZED: if (connections_handler) { mybe->server_myds->DSS=STATE_PING_SENT_NET; } else { - mybe->server_myds->DSS=STATE_QUERY_SENT_NET; + mybe->server_myds->setDSS_STATE_QUERY_SENT_NET(); } } if (mybe && mybe->server_myds) { if (mybe->server_myds->net_failure) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess:%p , MYDS:%p , myds_type=%d, DSS=%d , myconn:%p\n" , this, mybe->server_myds , mybe->server_myds->myds_type , mybe->server_myds->DSS, mybe->server_myds->myconn); if (( mybe->server_myds->DSS==STATE_READY || mybe->server_myds->DSS==STATE_QUERY_SENT_DS ) && mybe->server_myds->myds_type==MYDS_BACKEND) { mybe->server_myds->myconn=NULL; mybe->server_myds->DSS=STATE_NOT_INITIALIZED; @@ -556,17 +559,18 @@ __exit_DSS__STATE_NOT_INITIALIZED: mybe->server_myds->myconn=NULL; } if (mybe->server_myds->fd) { - shutdown(mybe->server_myds->fd,SHUT_RDWR); - close(mybe->server_myds->fd); + mybe->server_myds->shut_hard(); +// shutdown(mybe->server_myds->fd,SHUT_RDWR); +// close(mybe->server_myds->fd); mybe->server_myds->fd=0; thread->mypolls.remove_index_fast(mybe->server_myds->poll_fds_idx); //server_fd=0; } - mybe->server_myds->net_failure=false; + mybe->server_myds->clean_net_failure(); mybe->server_myds->active=1; goto __get_a_backend; } else { - healthy=0; + set_unhealthy(); } } } @@ -606,7 +610,7 @@ bool MySQL_Session::handler___status_CHANGING_SCHEMA(PtrSize_t *pkt) { return true; } else { l_free(pkt->size,pkt->ptr); - healthy=0; + set_unhealthy(); //mybe->myconn=server_myds->myconn; // if we reach here, server_myds->DSS should be STATE_QUERY_SENT , therefore the connection to the backend should be dropped anyway // although we enforce this here @@ -633,7 +637,7 @@ bool MySQL_Session::handler___status_CHANGING_USER_SERVER(PtrSize_t *pkt) { return true; } else { l_free(pkt->size,pkt->ptr); - healthy=0; + set_unhealthy(); //mybe->myconn=server_myds->myconn; // if we reach here, server_myds->DSS should be STATE_QUERY_SENT , therefore the connection to the backend should be dropped anyway // although we enforce this here @@ -813,7 +817,7 @@ void MySQL_Session::handler___status_CONNECTING_SERVER___STATE_CLIENT_HANDSHAKE( proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Wrong credentials for backend: disconnecting\n"); l_free(pkt->size,pkt->ptr); *wrong_pass=true; - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); char *_s=(char *)malloc(strlen(client_myds->myconn->userinfo->username)+100); sprintf(_s,"Access denied for user '%s' (using password: %s)", client_myds->myconn->userinfo->username, (client_myds->myconn->userinfo->password ? "YES" : "NO")); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,1045,(char *)"#28000", _s); @@ -862,7 +866,7 @@ void MySQL_Session::handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE( proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Wrong credentials for frontend: disconnecting\n"); *wrong_pass=true; // FIXME: this should become close connection - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); char *_s=(char *)malloc(strlen(client_myds->myconn->userinfo->username)+100); sprintf(_s,"Access denied for user '%s' (using password: %s)", client_myds->myconn->userinfo->username, (client_myds->myconn->userinfo->password ? "YES" : "NO")); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,2,1045,(char *)"#28000", _s); @@ -896,7 +900,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C v=*((char *)pkt->ptr+3); proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_SET_OPTION packet , value %d\n", v); // FIXME: ProxySQL doesn't support yet CLIENT_MULTI_STATEMENTS - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); if (v==1) { client_myds->myprot.generate_pkt_EOF(true,NULL,NULL,1,0,0); } else { @@ -909,7 +913,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_PING(PtrSize_t *pkt) { proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_PING packet\n"); l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_pkt_OK(true,NULL,NULL,1,0,0,2,0,NULL); client_myds->DSS=STATE_SLEEP; } @@ -918,12 +922,12 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (admin==false) { /* FIXME: temporary */ l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,1045,(char *)"#28000",(char *)"Command not supported"); client_myds->DSS=STATE_SLEEP; } else { l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,1045,(char *)"#28000",(char *)"Command not supported"); client_myds->DSS=STATE_SLEEP; } @@ -965,7 +969,7 @@ __exit_from_debug: l_free(query_length,query); l_free(query_length,query_no_space); l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); if (result) { // SQLite3_result * result = thread->SQL3_Thread_status(this); SQLite3_to_MySQL(result,NULL,0,&client_myds->myprot); @@ -983,12 +987,12 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (admin==false) { client_myds->myconn->userinfo->set_schemaname((char *)pkt->ptr+sizeof(mysql_hdr)+1,pkt->size-sizeof(mysql_hdr)-1); l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_pkt_OK(true,NULL,NULL,1,0,0,2,0,NULL); client_myds->DSS=STATE_SLEEP; } else { l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_pkt_OK(true,NULL,NULL,1,0,0,2,0,NULL); client_myds->DSS=STATE_SLEEP; } @@ -1027,7 +1031,7 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_STATISTICS(PtrSize_t *pkt) { proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_STATISTICS packet\n"); l_free(pkt->size,pkt->ptr); - client_myds->DSS=STATE_QUERY_SENT_NET; + client_myds->setDSS_STATE_QUERY_SENT_NET(); client_myds->myprot.generate_statistics_response(true,NULL,NULL); client_myds->DSS=STATE_SLEEP; } @@ -1218,3 +1222,9 @@ SQLite3_result * MySQL_Session::SQL3_Session_status() { free(pta); return result; } + + +void MySQL_Session::set_unhealthy() { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess:%p\n", this); + healthy=0; +} diff --git a/lib/Standard_MySQL_Thread.cpp b/lib/Standard_MySQL_Thread.cpp index 7c4ed9216..ef8e907f6 100644 --- a/lib/Standard_MySQL_Thread.cpp +++ b/lib/Standard_MySQL_Thread.cpp @@ -728,6 +728,7 @@ virtual void run() { while (shutdown==0) { +/* int num_idles; if (processing_idles==false && (last_processing_idles < curtime-5*1000000) ) { int i; @@ -778,7 +779,7 @@ virtual void run() { } } - +*/ for (n = 0; n < mypolls.len; n++) { mypolls.fds[n].revents=0; @@ -870,7 +871,7 @@ virtual void run() { // detected an error on backend if ( (mypolls.fds[n].revents & POLLERR) || (mypolls.fds[n].revents & POLLHUP) ) { // FIXME: try to handle it in a more graceful way - myds->sess->healthy=0; + myds->sess->set_unhealthy(); } break; default: @@ -896,7 +897,7 @@ void process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned int n) { && ( (mypolls.fds[n].revents & POLLERR) || (mypolls.fds[n].revents & POLLHUP) ) ) { - myds->net_failure=true; + myds->set_net_failure(); } myds->check_data_flow(); @@ -906,7 +907,7 @@ void process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned int n) { if (myds->active==FALSE) { if (myds->sess->client_myds==myds) { proxy_debug(PROXY_DEBUG_NET,1, "Session=%p, DataStream=%p -- Deleting FD %d\n", myds->sess, myds, myds->fd); - myds->sess->healthy=0; + myds->sess->set_unhealthy(); } } diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 7646a0756..212a2c2d8 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -142,6 +142,7 @@ MySQL_Connection::~MySQL_Connection() { if (myds) { myds->shut_hard(); } else { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "MySQL_Connection %p , fd:%d\n", this, fd); shutdown(fd, SHUT_RDWR); close(fd); } diff --git a/lib/mysql_data_stream.cpp b/lib/mysql_data_stream.cpp index 9c0c652d7..a0195e7a9 100644 --- a/lib/mysql_data_stream.cpp +++ b/lib/mysql_data_stream.cpp @@ -160,7 +160,7 @@ MySQL_Data_Stream::~MySQL_Data_Stream() { if (mypolls) mypolls->remove_index_fast(poll_fds_idx); if (fd>0) { if (myconn==NULL || myconn->reusable==false) { - proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "MySQL_Connection %p %s: shutdown socket\n", myconn, (myconn ? "not reusable" : "is empty")); + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess:%p , MYDS:%p , MySQL_Connection %p %s: shutdown socket\n", sess, this, myconn, (myconn ? "not reusable" : "is empty")); shut_hard(); // shutdown(fd,SHUT_RDWR); // close(fd); @@ -203,14 +203,14 @@ void MySQL_Data_Stream::init(enum MySQL_DS_type _type, MySQL_Session *_sess, int void MySQL_Data_Stream::shut_soft() { proxy_debug(PROXY_DEBUG_NET, 4, "Shutdown soft fd=%d. Session=%p, DataStream=%p\n", fd, sess, this); active=FALSE; - net_failure=true; + set_net_failure(); //if (sess) sess->net_failure=1; } // Hard shutdown of socket void MySQL_Data_Stream::shut_hard() { proxy_debug(PROXY_DEBUG_NET, 4, "Shutdown hard fd=%d. Session=%p, DataStream=%p\n", fd, sess, this); - net_failure=true; + set_net_failure(); if (fd >= 0) { shutdown(fd, SHUT_RDWR); close(fd); @@ -605,3 +605,23 @@ void MySQL_Data_Stream::unplug_backend() { mypolls=NULL; fd=0; } + +void MySQL_Data_Stream::clean_net_failure() { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p, myds=%p\n", this->sess, this); + net_failure=false; +} + +void MySQL_Data_Stream::set_net_failure() { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p, myds=%p , myds_type:%d\n", this->sess, this, myds_type); +#ifdef DEBUG + if (myds_type!=MYDS_FRONTEND) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p, myds=%p , myds_type:%d not frontend\n", this->sess, this, myds_type); + } +#endif /* DEBUG */ + net_failure=true; +} + +void MySQL_Data_Stream::setDSS_STATE_QUERY_SENT_NET() { + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p, myds=%p\n", this->sess, this); + DSS=STATE_QUERY_SENT_NET; +}