Commit e0b0ec6b authored by unknown's avatar unknown

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
parent 883f11b6
......@@ -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