diff options
author | unknown <konstantin@mysql.com> | 2004-02-02 23:01:58 +0300 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-02-02 23:01:58 +0300 |
commit | e0b0ec6b2c98f05547018655b6030a8d62bc511f (patch) | |
tree | f3ac440023264a510364912fe7f9dbaa97266806 | |
parent | 883f11b68c402b106dbff2542435782a8af3b55d (diff) | |
download | mariadb-git-e0b0ec6b2c98f05547018655b6030a8d62bc511f.tar.gz |
Proposed (version #2) fix for bug #1948:
"system variable query_prealloc_size can be only global"
include/my_sys.h:
Fix for bug #1948:
- added reset_root_defaults function declaration
mysys/my_alloc.c:
Fix for bug #1948:
- implementation and description of reset_root_defaults
sql/set_var.cc:
Fix for bug #1948:
- fix_thd_mem_root and fix_trans_mem_root after update triggers
implemented for variables query_prealloc_size, query_alloc_block_size,
trans_prealloc_size, trans_alloc_block_size
-rw-r--r-- | include/my_sys.h | 2 | ||||
-rw-r--r-- | mysys/my_alloc.c | 66 | ||||
-rw-r--r-- | sql/set_var.cc | 32 |
3 files changed, 96 insertions, 4 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index e1656cfc626..75e22629a19 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -740,6 +740,8 @@ extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size, extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size); extern void free_root(MEM_ROOT *root, myf MyFLAGS); extern void set_prealloc_root(MEM_ROOT *root, char *ptr); +extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, + uint prealloc_size); extern char *strdup_root(MEM_ROOT *root,const char *str); extern char *strmake_root(MEM_ROOT *root,const char *str,uint len); extern char *memdup_root(MEM_ROOT *root,const char *str,uint len); diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 4d3b0604984..d03ec5841af 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -47,6 +47,72 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, #endif } +/* + SYNOPSIS + reset_root_defaults() + mem_root memory root to change defaults of + block_size new value of block size. Must be + greater than ~68 bytes (the exact value depends on + platform and compilation flags) + pre_alloc_size new size of preallocated block. If not zero, + must be equal to or greater than block size, + otherwise means 'no prealloc'. + DESCRIPTION + Function aligns and assigns new value to block size; then it tries to + reuse one of existing blocks as prealloc block, or malloc new one of + requested size. If no blocks can be reused, all unused blocks are freed + before allocation. + */ + +void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, + uint pre_alloc_size) +{ + mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; +#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) + if (pre_alloc_size) + { + uint size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)); + if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size) + { + USED_MEM *mem, **prev= &mem_root->free; + /* + Free unused blocks, so that consequent calls + to reset_root_defaults won't eat away memory. + */ + while (*prev) + { + mem= *prev; + if (mem->size == size) + { + /* We found a suitable block, no need to do anything else */ + mem_root->pre_alloc= mem; + return; + } + if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size) + { + /* remove block from the list and free it */ + *prev= mem->next; + my_free((gptr) mem, MYF(0)); + } + else + prev= &mem->next; + } + /* Allocate new prealloc block and add it to the end of free list */ + if ((mem= (USED_MEM *) my_malloc(size, MYF(0)))) + { + mem->size= size; + mem->left= pre_alloc_size; + mem->next= *prev; + *prev= mem_root->pre_alloc= mem; + } + } + } + else +#endif + mem_root->pre_alloc= 0; +} + + gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) { #if defined(HAVE_purify) && defined(EXTRA_DEBUG) diff --git a/sql/set_var.cc b/sql/set_var.cc index 693d8e4c958..475beb798e6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -88,6 +88,8 @@ static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type); static void fix_max_connections(THD *thd, enum_var_type type); +static void fix_thd_mem_root(THD *thd, enum_var_type type); +static void fix_trans_mem_root(THD *thd, enum_var_type type); /* Variable definition list @@ -209,13 +211,17 @@ sys_var_long_ptr sys_query_cache_size("query_cache_size", sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size", &SV::range_alloc_block_size); sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", - &SV::query_alloc_block_size); + &SV::query_alloc_block_size, + fix_thd_mem_root); sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", - &SV::query_prealloc_size); + &SV::query_prealloc_size, + fix_thd_mem_root); sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", - &SV::trans_alloc_block_size); + &SV::trans_alloc_block_size, + fix_trans_mem_root); sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size", - &SV::trans_prealloc_size); + &SV::trans_prealloc_size, + fix_trans_mem_root); #ifdef HAVE_QUERY_CACHE sys_var_long_ptr sys_query_cache_limit("query_cache_limit", @@ -763,6 +769,24 @@ static void fix_max_connections(THD *thd, enum_var_type type) } +static void fix_thd_mem_root(THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(&thd->mem_root, + thd->variables.query_alloc_block_size, + thd->variables.query_prealloc_size); +} + + +static void fix_trans_mem_root(THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(&thd->transaction.mem_root, + thd->variables.trans_alloc_block_size, + thd->variables.trans_prealloc_size); +} + + bool sys_var_long_ptr::update(THD *thd, set_var *var) { ulonglong tmp= var->value->val_int(); |