summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
authorhf@deer.(none) <>2004-10-05 21:19:40 +0500
committerhf@deer.(none) <>2004-10-05 21:19:40 +0500
commitee3b6340b03b303997fc6bb54499b9ead0316025 (patch)
tree625041aef3296bd1708b8cfa02da1b5db3a04bff /sql/sql_cache.cc
parent19c112dfb5d2a1ab787c4ee10efd92e996b17799 (diff)
downloadmariadb-git-ee3b6340b03b303997fc6bb54499b9ead0316025.tar.gz
Fix for #5730 (Query cache crashes server)
Recusive part leads to stack overflow
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc75
1 files changed, 37 insertions, 38 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 5118421464b..60f0cfadc8e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1843,7 +1843,6 @@ inline ulong Query_cache::get_min_append_result_data_size()
/*
Allocate one or more blocks to hold data
*/
-
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
Query_cache_block *query_block,
@@ -1851,55 +1850,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
- ulong len= data_len + all_headers_len;
- ulong align_len= ALIGN_SIZE(len);
- DBUG_ENTER("Query_cache::allocate_data_chain");
- DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
- data_len, all_headers_len));
-
ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
- *result_block = allocate_block(max(min_size, align_len),
- min_result_data_size == 0,
- all_headers_len + min_result_data_size,
- 1);
- my_bool success = (*result_block != 0);
- if (success)
+ Query_cache_block *prev_block= NULL;
+ Query_cache_block *new_block;
+ DBUG_ENTER("Query_cache::allocate_data_chain");
+ DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
+ data_len, all_headers_len));
+
+ do
{
- Query_cache_block *new_block= *result_block;
+ ulong len= data_len + all_headers_len;
+ ulong align_len= ALIGN_SIZE(len);
+
+ if (!(new_block= allocate_block(max(min_size, align_len),
+ min_result_data_size == 0,
+ all_headers_len + min_result_data_size,
+ 1)))
+ {
+ DBUG_PRINT("warning", ("Can't allocate block for results"));
+ DBUG_RETURN(FALSE);
+ }
+
new_block->n_tables = 0;
- new_block->used = 0;
+ new_block->used = min(len, new_block->length);
new_block->type = Query_cache_block::RES_INCOMPLETE;
new_block->next = new_block->prev = new_block;
Query_cache_result *header = new_block->result();
header->parent(query_block);
- if (new_block->length < len)
- {
- /*
- We got less memory then we need (no big memory blocks) =>
- Continue to allocated more blocks until we got everything we need.
- */
- Query_cache_block *next_block;
- if ((success = allocate_data_chain(&next_block,
- len - new_block->length,
- query_block, first_block_arg)))
- double_linked_list_join(new_block, next_block);
- }
- if (success)
- {
- new_block->used = min(len, new_block->length);
-
- DBUG_PRINT("qcache", ("Block len %lu used %lu",
+ DBUG_PRINT("qcache", ("Block len %lu used %lu",
new_block->length, new_block->used));
- }
+
+ if (prev_block)
+ double_linked_list_join(prev_block, new_block);
else
- DBUG_PRINT("warning", ("Can't allocate block for continue"));
- }
- else
- DBUG_PRINT("warning", ("Can't allocate block for results"));
- DBUG_RETURN(success);
+ *result_block= new_block;
+ if (new_block->length >= len)
+ break;
+
+ /*
+ We got less memory then we need (no big memory blocks) =>
+ Continue to allocated more blocks until we got everything we need.
+ */
+ data_len= len - new_block->length;
+ prev_block= new_block;
+ } while(1);
+
+ DBUG_RETURN(TRUE);
}
/*****************************************************************************