From 1fc65ed8bb85a09dd8847c5f555d1afb4002aa0f Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Tue, 15 Dec 2009 17:33:06 +0000 Subject: [PATCH] Move code out of mysqlnd_conn::connect to mysqlnd_net::connect. Thus mysqlnd_conn::connect() does less of what it should not do - think about the transport level. --- ext/mysqlnd/mysqlnd.c | 83 ++------------------------- ext/mysqlnd/mysqlnd_structs.h | 1 + ext/mysqlnd/mysqlnd_wireprotocol.c | 90 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 77 deletions(-) diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index b63209dfecb..86afee7dd62 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -450,12 +450,8 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, TSRMLS_DC) { char *transport = NULL, *errstr = NULL; - char *hashed_details = NULL; - int transport_len, hashed_details_len, errcode = 0, host_len; - unsigned int streams_options = ENFORCE_SAFE_MODE; - unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; + int transport_len, errcode = 0, host_len; zend_bool self_alloced = FALSE; - struct timeval tv; zend_bool unix_socket = FALSE; const MYSQLND_CHARSET * charset; zend_bool reconnect = FALSE; @@ -535,89 +531,22 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND *conn, PACKET_INIT(auth_packet, PROT_AUTH_PACKET, php_mysql_packet_auth *, FALSE); PACKET_INIT_ALLOCA(ok_packet, PROT_OK_PACKET); - if (conn->persistent) { - hashed_details_len = spprintf(&hashed_details, 0, "%p", conn); - DBG_INF_FMT("hashed_details=%s", hashed_details); - } - CONN_SET_STATE(conn, CONN_ALLOCED); - conn->net->packet_no = conn->net->compressed_envelope_packet_no = 0; - if (conn->net->options.timeout_connect) { - tv.tv_sec = conn->net->options.timeout_connect; - tv.tv_usec = 0; - } if (conn->persistent) { conn->scheme = pestrndup(transport, transport_len, 1); mnd_efree(transport); } else { conn->scheme = transport; } - conn->scheme_len = strlen(conn->scheme); + conn->scheme_len = transport_len; DBG_INF(conn->scheme); - conn->net->stream = php_stream_xport_create(conn->scheme, transport_len, streams_options, streams_flags, - hashed_details, - (conn->net->options.timeout_connect) ? &tv : NULL, - NULL /*ctx*/, &errstr, &errcode); + if (FAIL == conn->net->m.connect(conn->net, conn->scheme, transport_len, conn->persistent, &errstr, &errcode TSRMLS_CC)) { + goto err; + } + DBG_INF_FMT("stream=%p", conn->net->stream); - if (errstr || !conn->net->stream) { - if (hashed_details) { - mnd_efree(hashed_details); - } - errcode = CR_CONNECTION_ERROR; - goto err; - } - - if (hashed_details) { - /* - If persistent, the streams register it in EG(persistent_list). - This is unwanted. ext/mysql or ext/mysqli are responsible to clean, - whatever they have to. - */ - zend_rsrc_list_entry *le; - - if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_len + 1, - (void*) &le) == SUCCESS) { - /* - in_free will let streams code skip destructing - big HACK, - but STREAMS suck big time regarding persistent streams. - Just not compatible for extensions that need persistency. - */ - conn->net->stream->in_free = 1; - zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1); - conn->net->stream->in_free = 0; - } -#if ZEND_DEBUG - /* Shut-up the streams, they don't know what they are doing */ - conn->net->stream->__exposed = 1; -#endif - mnd_efree(hashed_details); - } - - if (!conn->net->options.timeout_read) { - /* should always happen because read_timeout cannot be set via API */ - conn->net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout); - } - if (conn->net->options.timeout_read) - { - tv.tv_sec = conn->net->options.timeout_read; - tv.tv_usec = 0; - php_stream_set_option(conn->net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); - } - - if (!unix_socket) { - /* Set TCP_NODELAY */ - mysqlnd_set_sock_no_delay(conn->net->stream); - } - - { - unsigned int buf_size; - buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/ - conn->m->set_client_option(conn, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC); - } - - if (FAIL == PACKET_READ_ALLOCA(greet_packet, conn)) { DBG_ERR("Error while reading greeting packet"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet. PID=%d", getpid()); diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 6e4985d87b0..a791e7dc95b 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -230,6 +230,7 @@ typedef struct st_mysqlnd_read_buffer { struct st_mysqlnd_net_methods { + enum_func_status (*connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC); enum_func_status (*stream_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC); size_t (*stream_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC); enum_func_status (*set_client_option)(MYSQLND_NET * const net, enum_mysqlnd_option option, const char * const value TSRMLS_DC); diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 2068e58158f..f1eba6265c6 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -2290,6 +2290,95 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] = /* }}} */ +/* {{{ mysqlnd_net::connect */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC) +{ + unsigned int streams_options = ENFORCE_SAFE_MODE; + unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; + char * hashed_details = NULL; + int hashed_details_len = 0; + struct timeval tv; + DBG_ENTER("mysqlnd_net::connect"); + + if (persistent) { + hashed_details_len = spprintf(&hashed_details, 0, "%p", net); + DBG_INF_FMT("hashed_details=%s", hashed_details); + } + + net->packet_no = net->compressed_envelope_packet_no = 0; + + if (net->options.timeout_connect) { + tv.tv_sec = net->options.timeout_connect; + tv.tv_usec = 0; + } + + net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags, + hashed_details, (net->options.timeout_connect) ? &tv : NULL, + NULL /*ctx*/, errstr, errcode); + + + if (*errstr || !net->stream) { + if (hashed_details) { + efree(hashed_details); + } + *errcode = CR_CONNECTION_ERROR; + DBG_RETURN(FAIL); + } + + if (hashed_details) { + /* + If persistent, the streams register it in EG(persistent_list). + This is unwanted. ext/mysql or ext/mysqli are responsible to clean, + whatever they have to. + */ + zend_rsrc_list_entry *le; + + if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_len + 1, + (void*) &le) == SUCCESS) { + /* + in_free will let streams code skip destructing - big HACK, + but STREAMS suck big time regarding persistent streams. + Just not compatible for extensions that need persistency. + */ + net->stream->in_free = 1; + zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1); + net->stream->in_free = 0; + } +#if ZEND_DEBUG + /* Shut-up the streams, they don't know what they are doing */ + net->stream->__exposed = 1; +#endif + efree(hashed_details); + } + + if (!net->options.timeout_read) { + /* should always happen because read_timeout cannot be set via API */ + net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout); + } + if (net->options.timeout_read) + { + tv.tv_sec = net->options.timeout_read; + tv.tv_usec = 0; + php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); + } + + if (!memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) { + /* TCP -> Set TCP_NODELAY */ + mysqlnd_set_sock_no_delay(net->stream); + } + + { + unsigned int buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/ + net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC); + } + + + DBG_RETURN(PASS); +} +/* }}} */ + + /* {{{ mysqlnd_net::set_client_option */ static enum_func_status MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mysqlnd_option option, const char * const value TSRMLS_DC) @@ -2368,6 +2457,7 @@ mysqlnd_net_init(zend_bool persistent TSRMLS_DC) DBG_INF_FMT("persistent=%d", persistent); net->persistent = persistent; + net->m.connect = MYSQLND_METHOD(mysqlnd_net, connect); net->m.stream_read = MYSQLND_METHOD(mysqlnd_net, read_from_stream); net->m.stream_write = MYSQLND_METHOD(mysqlnd_net, stream_write); net->m.set_client_option = MYSQLND_METHOD(mysqlnd_net, set_client_option);