Commit 74a1d68d authored by konstantin@mysql.com's avatar konstantin@mysql.com

Proposed (version #2) fix for bug #1948:

"system variable query_prealloc_size can be only global"
parent 348a184a
......@@ -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);
......
......@@ -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)
......
......@@ -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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment