diff options
-rw-r--r-- | include/mysql.h.pp | 10 | ||||
-rw-r--r-- | include/mysql_com.h | 3 | ||||
-rw-r--r-- | mysql-test/r/mysql_client_test_comp.result | 4 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test_comp-master.opt | 2 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test_comp.test | 20 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test_nonblock-master.opt | 1 | ||||
-rw-r--r-- | sql-common/client.c | 4 | ||||
-rw-r--r-- | sql/mf_iocache.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 79 | ||||
-rw-r--r-- | sql/net_serv.cc | 43 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 104 |
15 files changed, 210 insertions, 70 deletions
diff --git a/include/mysql.h.pp b/include/mysql.h.pp index ca5b1ac05bf..6b60389acc3 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -49,9 +49,9 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, MYSQL_TYPE_BIT, - MYSQL_TYPE_TIMESTAMP2, - MYSQL_TYPE_DATETIME2, - MYSQL_TYPE_TIME2, + MYSQL_TYPE_TIMESTAMP2, + MYSQL_TYPE_DATETIME2, + MYSQL_TYPE_TIME2, MYSQL_TYPE_NEWDECIMAL=246, MYSQL_TYPE_ENUM=247, MYSQL_TYPE_SET=248, @@ -94,7 +94,7 @@ my_bool net_write_command(NET *net,unsigned char command, const unsigned char *header, size_t head_len, const unsigned char *packet, size_t len); int net_real_write(NET *net,const unsigned char *packet, size_t len); -unsigned long my_net_read(NET *net); +unsigned long my_net_read_packet(NET *net, my_bool read_from_server); struct sockaddr; int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen, unsigned int timeout); @@ -553,7 +553,7 @@ int mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg); int mysql_options4(MYSQL *mysql,enum mysql_option option, - const void *arg1, const void *arg2); + const void *arg1, const void *arg2); void mysql_free_result(MYSQL_RES *result); int mysql_free_result_start(MYSQL_RES *result); int mysql_free_result_cont(MYSQL_RES *result, int status); diff --git a/include/mysql_com.h b/include/mysql_com.h index 9486bd3ebb7..43be28f87a0 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -541,7 +541,8 @@ my_bool net_write_command(NET *net,unsigned char command, const unsigned char *header, size_t head_len, const unsigned char *packet, size_t len); int net_real_write(NET *net,const unsigned char *packet, size_t len); -unsigned long my_net_read(NET *net); +unsigned long my_net_read_packet(NET *net, my_bool read_from_server); +#define my_net_read(A) my_net_read_packet((A), 0) #ifdef MY_GLOBAL_INCLUDED void my_net_set_write_timeout(NET *net, uint timeout); diff --git a/mysql-test/r/mysql_client_test_comp.result b/mysql-test/r/mysql_client_test_comp.result new file mode 100644 index 00000000000..b9cac467b92 --- /dev/null +++ b/mysql-test/r/mysql_client_test_comp.result @@ -0,0 +1,4 @@ +SET @old_slow_query_log= @@global.slow_query_log; +call mtr.add_suppression(" Error reading file './client_test_db/test_frm_bug.frm'"); +ok +SET @@global.slow_query_log= @old_slow_query_log; diff --git a/mysql-test/t/mysql_client_test-master.opt b/mysql-test/t/mysql_client_test-master.opt index 5b347aa0416..fcaf2b69fbc 100644 --- a/mysql-test/t/mysql_client_test-master.opt +++ b/mysql-test/t/mysql_client_test-master.opt @@ -1,3 +1,4 @@ --general-log --general-log-file=$MYSQLTEST_VARDIR/log/master.log --log-output=FILE,TABLE +--max-allowed-packet=32000000 diff --git a/mysql-test/t/mysql_client_test_comp-master.opt b/mysql-test/t/mysql_client_test_comp-master.opt new file mode 100644 index 00000000000..783093c900b --- /dev/null +++ b/mysql-test/t/mysql_client_test_comp-master.opt @@ -0,0 +1,2 @@ +--loose-enable-performance-schema +--max-allowed-packet=32000000 diff --git a/mysql-test/t/mysql_client_test_comp.test b/mysql-test/t/mysql_client_test_comp.test new file mode 100644 index 00000000000..0a6b0ba1130 --- /dev/null +++ b/mysql-test/t/mysql_client_test_comp.test @@ -0,0 +1,20 @@ +# run mysql_client_test with performance schema + +# No need to run this with embedded server +-- source include/not_embedded.inc + +# need to have the dynamic loading turned on for the client plugin tests +--source include/have_plugin_auth.inc + +SET @old_slow_query_log= @@global.slow_query_log; + +call mtr.add_suppression(" Error reading file './client_test_db/test_frm_bug.frm'"); + +--exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test_comp.out.log 2>&1 +--exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test_comp.out.log 2>&1 + +# End of test +echo ok; + +# Restore state changed by mysql_test_run +SET @@global.slow_query_log= @old_slow_query_log; diff --git a/mysql-test/t/mysql_client_test_nonblock-master.opt b/mysql-test/t/mysql_client_test_nonblock-master.opt index 034d5340a23..5775e707c5f 100644 --- a/mysql-test/t/mysql_client_test_nonblock-master.opt +++ b/mysql-test/t/mysql_client_test_nonblock-master.opt @@ -1 +1,2 @@ --general-log --general-log-file=$MYSQLTEST_VARDIR/log/master.log --log-output=FILE,TABLE +--max-allowed-packet=32000000 diff --git a/sql-common/client.c b/sql-common/client.c index 72760560903..c7065925198 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -764,8 +764,8 @@ cli_safe_read(MYSQL *mysql) restart: if (net->vio != 0) - len=my_net_read(net); - + len= my_net_read_packet(net, 0); + if (len == packet_error || len == 0) { DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %lu", diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index d8848c1ee35..3ed9261f630 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -57,7 +57,7 @@ int _my_b_net_read(register IO_CACHE *info, uchar *Buffer, if (!info->end_of_file) DBUG_RETURN(1); /* because my_b_get (no _) takes 1 byte at a time */ - read_length=my_net_read(net); + read_length= my_net_read_packet(net, 0); if (read_length == packet_error) { info->error= -1; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 18c1ffefd8d..431009110b8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1115,65 +1115,60 @@ void net_before_header_psi(struct st_net *net, void *user_data, size_t /* unused thd= static_cast<THD*> (user_data); DBUG_ASSERT(thd != NULL); - if (thd->m_server_idle) - { - /* - The server is IDLE, waiting for the next command. - Technically, it is a wait on a socket, which may take a long time, - because the call is blocking. - Disable the socket instrumentation, to avoid recording a SOCKET event. - Instead, start explicitly an IDLE event. - */ - MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE); - MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state); - } + /* + We only come where when the server is IDLE, waiting for the next command. + Technically, it is a wait on a socket, which may take a long time, + because the call is blocking. + Disable the socket instrumentation, to avoid recording a SOCKET event. + Instead, start explicitly an IDLE event. + */ + MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE); + MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state); } -void net_after_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */, my_bool rc) +void net_after_header_psi(struct st_net *net, void *user_data, + size_t /* unused: count */, my_bool rc) { THD *thd; thd= static_cast<THD*> (user_data); DBUG_ASSERT(thd != NULL); - if (thd->m_server_idle) - { - /* - The server just got data for a network packet header, - from the network layer. - The IDLE event is now complete, since we now have a message to process. - We need to: - - start a new STATEMENT event - - start a new STAGE event, within this statement, - - start recording SOCKET WAITS events, within this stage. - The proper order is critical to get events numbered correctly, - and nested in the proper parent. - */ - MYSQL_END_IDLE_WAIT(thd->m_idle_psi); - - if (! rc) - { - thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, - stmt_info_new_packet.m_key, - thd->db, thd->db_length, - thd->charset()); + /* + The server just got data for a network packet header, + from the network layer. + The IDLE event is now complete, since we now have a message to process. + We need to: + - start a new STATEMENT event + - start a new STAGE event, within this statement, + - start recording SOCKET WAITS events, within this stage. + The proper order is critical to get events numbered correctly, + and nested in the proper parent. + */ + MYSQL_END_IDLE_WAIT(thd->m_idle_psi); - THD_STAGE_INFO(thd, stage_init); - } + if (! rc) + { + thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, + stmt_info_new_packet.m_key, + thd->db, thd->db_length, + thd->charset()); - /* - TODO: consider recording a SOCKET event for the bytes just read, - by also passing count here. - */ - MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE); + THD_STAGE_INFO(thd, stage_init); } + + /* + TODO: consider recording a SOCKET event for the bytes just read, + by also passing count here. + */ + MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE); } + void init_net_server_extension(THD *thd) { /* Start with a clean state for connection events. */ thd->m_idle_psi= NULL; thd->m_statement_psi= NULL; - thd->m_server_idle= false; /* Hook up the NET_SERVER callback in the net layer. */ thd->m_net_server_extension.m_user_data= thd; thd->m_net_server_extension.m_before_header= net_before_header_psi; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 546542fa207..eb34fcc2d77 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -824,7 +824,8 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, */ static ulong -my_real_read(NET *net, size_t *complen) +my_real_read(NET *net, size_t *complen, + my_bool header __attribute__((unused))) { uchar *pos; size_t length; @@ -839,14 +840,16 @@ my_real_read(NET *net, size_t *complen) NET_HEADER_SIZE); #ifdef MYSQL_SERVER size_t count= remain; - struct st_net_server *server_extension; - server_extension= static_cast<st_net_server*> (net->extension); - if (server_extension != NULL) + struct st_net_server *server_extension= 0; + + if (header) { - void *user_data= server_extension->m_user_data; - DBUG_ASSERT(server_extension->m_before_header != NULL); - DBUG_ASSERT(server_extension->m_after_header != NULL); - server_extension->m_before_header(net, user_data, count); + server_extension= static_cast<st_net_server*> (net->extension); + if (server_extension != NULL) + { + void *user_data= server_extension->m_user_data; + server_extension->m_before_header(net, user_data, count); + } } #endif @@ -1042,6 +1045,16 @@ end: } +/* Old interface. See my_net_read_packet() for function description */ + +#undef my_net_read + +ulong my_net_read(NET *net) +{ + return my_net_read_packet(net, 0); +} + + /** Read a packet from the client/server and return it without the internal package header. @@ -1053,13 +1066,17 @@ end: If the packet was compressed, its uncompressed and the length of the uncompressed packet is returned. + read_from_server is set when the server is reading a new command + from the client. + @return The function returns the length of the found packet or packet_error. net->read_pos points to the read data. */ + ulong -my_net_read(NET *net) +my_net_read_packet(NET *net, my_bool read_from_server) { size_t len, complen; @@ -1069,7 +1086,7 @@ my_net_read(NET *net) if (!net->compress) { #endif - len = my_real_read(net,&complen); + len = my_real_read(net,&complen, read_from_server); if (len == MAX_PACKET_LENGTH) { /* First packet of a multi-packet. Concatenate the packets */ @@ -1079,7 +1096,7 @@ my_net_read(NET *net) { net->where_b += len; total_length += len; - len = my_real_read(net,&complen); + len = my_real_read(net,&complen, 0); } while (len == MAX_PACKET_LENGTH); if (len != packet_error) len+= total_length; @@ -1171,11 +1188,13 @@ my_net_read(NET *net) } net->where_b=buf_length; - if ((packet_len = my_real_read(net,&complen)) == packet_error) + if ((packet_len = my_real_read(net,&complen, read_from_server)) + == packet_error) { MYSQL_NET_READ_DONE(1, 0); return packet_error; } + read_from_server= 0; if (my_uncompress(net->buff + net->where_b, packet_len, &complen)) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e3e52e1c3a2..27e195e52d4 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -876,7 +876,6 @@ THD::THD() accessed_rows_and_keys(0), m_statement_psi(NULL), m_idle_psi(NULL), - m_server_idle(false), thread_id(0), global_disable_checkpoint(0), failed_com_change_user(0), diff --git a/sql/sql_class.h b/sql/sql_class.h index b70c51f1aa4..68c9f802171 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2501,8 +2501,6 @@ public: /** Idle instrumentation state. */ PSI_idle_locker_state m_idle_state; #endif /* HAVE_PSI_IDLE_INTERFACE */ - /** True if the server code is IDLE for this connection. */ - bool m_server_idle; /* Id of current query. Statement can be reused to execute several queries diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d7fdb4d0473..8202dcaba10 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -934,9 +934,7 @@ bool do_command(THD *thd) */ DEBUG_SYNC(thd, "before_do_command_net_read"); - thd->m_server_idle= TRUE; - packet_length= my_net_read(net); - thd->m_server_idle= FALSE; + packet_length= my_net_read_packet(net, 1); if (packet_length == packet_error) { diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 898d67c5058..78dd24fe6d4 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18616,7 +18616,7 @@ static void test_bug56976() const char* query = "SELECT LENGTH(?)"; char *long_buffer; unsigned long i, packet_len = 256 * 1024L; - unsigned long dos_len = 2 * 1024 * 1024L; + unsigned long dos_len = 35000000; DBUG_ENTER("test_bug56976"); myheader("test_bug56976"); @@ -19255,6 +19255,106 @@ static void test_mdev4326() myquery(rc); } + +/* + Check compressed protocol +*/ + +static void test_compressed_protocol() +{ + MYSQL *mysql_local; + char query[4096], *end; + int i; + myheader("test_compressed_protocol"); + + if (!(mysql_local= mysql_client_init(NULL))) + { + fprintf(stderr, "\n mysql_client_init() failed"); + exit(1); + } + + if (!(mysql_real_connect(mysql_local, opt_host, opt_user, + opt_password, current_db, opt_port, + opt_unix_socket, CLIENT_COMPRESS))) + { + fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local)); + exit(1); + } + mysql_options(mysql_local,MYSQL_OPT_COMPRESS,NullS); + + end= strmov(strfill(strmov(query, "select length(\""),1000,'a'),"\")"); + + for (i=0 ; i < 2 ; i++) + { + MYSQL_RES *res; + + int rc= mysql_real_query(mysql, query, (int) (end-query)); + myquery(rc); + res= mysql_store_result(mysql); + DBUG_ASSERT(res != 0); + mysql_free_result(res); + } + + mysql_close(mysql_local); +} + +/* + Check big packets +*/ + +static void test_big_packet() +{ + MYSQL *mysql_local; + char *query, *end; + /* We run the tests with a server with max packet size of 3200000 */ + size_t big_packet= 31000000L; + int i; + MYSQL_PARAMETERS *mysql_params= mysql_get_parameters(); + long org_max_allowed_packet= *mysql_params->p_max_allowed_packet; + long opt_net_buffer_length= *mysql_params->p_net_buffer_length; + + myheader("test_big_packet"); + + query= (char*) my_malloc(big_packet+1024, MYF(MY_WME)); + DIE_UNLESS(query); + + if (!(mysql_local= mysql_client_init(NULL))) + { + fprintf(stderr, "\n mysql_client_init() failed"); + exit(1); + } + + if (!(mysql_real_connect(mysql_local, opt_host, opt_user, + opt_password, current_db, opt_port, + opt_unix_socket, 0))) + { + fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local)); + exit(1); + } + + *mysql_params->p_max_allowed_packet= big_packet+1000; + *mysql_params->p_net_buffer_length= 8L*256L*256L; + + end= strmov(strfill(strmov(query, "select length(\""), big_packet,'a'),"\")"); + + for (i=0 ; i < 2 ; i++) + { + MYSQL_RES *res; + int rc= mysql_real_query(mysql, query, (int) (end-query)); + myquery(rc); + res= mysql_store_result(mysql); + DBUG_ASSERT(res != 0); + mysql_free_result(res); + } + + mysql_close(mysql_local); + my_free(query); + + *mysql_params->p_max_allowed_packet= org_max_allowed_packet; + *mysql_params->p_net_buffer_length = opt_net_buffer_length; +} + + static struct my_tests_st my_tests[]= { { "disable_query_logs", disable_query_logs }, { "test_view_sp_list_fields", test_view_sp_list_fields }, @@ -19526,6 +19626,8 @@ static struct my_tests_st my_tests[]= { { "test_bug13001491", test_bug13001491 }, { "test_mdev4326", test_mdev4326 }, { "test_ps_sp_out_params", test_ps_sp_out_params }, + { "test_compressed_protocol", test_compressed_protocol }, + { "test_big_packet", test_big_packet }, { 0, 0 } }; |