diff options
author | Dmitry Shulga <Dmitry.Shulga@Sun.COM> | 2010-09-16 17:38:13 +0700 |
---|---|---|
committer | Dmitry Shulga <Dmitry.Shulga@Sun.COM> | 2010-09-16 17:38:13 +0700 |
commit | deacb7c8ab3dc0bf097ec7598dcfa84007e16fc4 (patch) | |
tree | 53ee44a010c3a3787074d14e894edbed17daaddc /sql/sql_cache.cc | |
parent | 5f2bfccec41d0b5d693355628a1c51c66b47b75b (diff) | |
parent | 0c91b53d10ad74fd26a2e3ba565d117539d8983c (diff) | |
download | mariadb-git-deacb7c8ab3dc0bf097ec7598dcfa84007e16fc4.tar.gz |
Auto-merge from mysql-5.1-bugteam for bug#42503.
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r-- | sql/sql_cache.cc | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index d6dc9edc502..7b288948885 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1346,6 +1346,55 @@ end: } +/** + Send a single memory block from the query cache. + + Respects the client/server protocol limits for the + size of the network packet, and splits a large block + in pieces to ensure that individual piece doesn't exceed + the maximal allowed size of the network packet (16M). + + @param[in] net NET handler + @param[in] packet packet to send + @param[in] len packet length + + @return Operation status + @retval FALSE On success + @retval TRUE On error +*/ +static bool +send_data_in_chunks(NET *net, const uchar *packet, ulong len) +{ + /* + On the client we may require more memory than max_allowed_packet + to keep, both, the truncated last logical packet, and the + compressed next packet. This never (or in practice never) + happens without compression, since without compression it's very + unlikely that a) a truncated logical packet would remain on the + client when it's time to read the next packet b) a subsequent + logical packet that is being read would be so large that + size-of-new-packet + size-of-old-packet-tail > + max_allowed_packet. To remedy this issue, we send data in 1MB + sized packets, that's below the current client default of 16MB + for max_allowed_packet, but large enough to ensure there is no + unnecessary overhead from too many syscalls per result set. + */ + static const ulong MAX_CHUNK_LENGTH= 1024*1024; + + while (len > MAX_CHUNK_LENGTH) + { + if (net_real_write(net, packet, MAX_CHUNK_LENGTH)) + return TRUE; + packet+= MAX_CHUNK_LENGTH; + len-= MAX_CHUNK_LENGTH; + } + if (len && net_real_write(net, packet, len)) + return TRUE; + + return FALSE; +} + + /* Check if the query is in the cache. If it was cached, send it to the user. @@ -1655,11 +1704,11 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", ALIGN_SIZE(sizeof(Query_cache_result))))); Query_cache_result *result = result_block->result(); - if (net_real_write(&thd->net, result->data(), - result_block->used - - result_block->headers_len() - - ALIGN_SIZE(sizeof(Query_cache_result)))) - break; // Client aborted + if (send_data_in_chunks(&thd->net, result->data(), + result_block->used - + result_block->headers_len() - + ALIGN_SIZE(sizeof(Query_cache_result)))) + break; // Client aborted result_block = result_block->next; thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated } while (result_block != first_result_block); |