Commit c673fcb8 authored by pem@mysql.com's avatar pem@mysql.com

Getting rid of lots of memory leaks (but not quite all of them yet,

some will go away when temporary code is replaced).
parent 5eaa5954
......@@ -20,6 +20,7 @@ delete from t1;
drop procedure foo42;
create procedure u()
use sptmp;
drop database if exists sptmp;
create database sptmp;
use test;
call u();
......
......@@ -35,6 +35,9 @@ drop procedure foo42;
create procedure u()
use sptmp;
--disable_warnings
drop database if exists sptmp;
--enable_warnings
create database sptmp;
use test;
call u();
......
......@@ -19,8 +19,8 @@
#include "sp.h"
#include "sp_head.h"
static sp_head *
sp_find_cached_function(THD *thd, char *name, uint namelen);
static sp_head *
sp_find_cached_function(THD *thd, char *name, uint namelen);
/*
*
......@@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex)
void
sp_clear_function_cache(THD *thd)
{
//QQ This doesn't work for some completely mysterious reason, but since this
//QQ is tempoarary code anyway, we just ignore it for now.
//QQ List_iterator_fast<sp_head> li(thd->spfuns);
//QQ sp_head *sp;
//QQ while ((sp= li++))
//QQ sp->destroy();
thd->spfuns.empty();
}
......
......@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type)
}
sp_head::sp_head(LEX_STRING *name, LEX *lex)
: m_simple_case(FALSE)
: Sql_alloc(), m_simple_case(FALSE)
{
const char *dstr = (const char*)lex->buf;
......@@ -126,19 +126,34 @@ sp_head::create(THD *thd)
DBUG_RETURN(ret);
}
void
sp_head::destroy()
{
delete_dynamic(&m_instr);
m_pcont->destroy();
}
int
sp_head::execute(THD *thd)
{
DBUG_ENTER("sp_head::execute");
char *olddbname;
char olddbname[128];
char *olddbptr= thd->db;
int ret= 0;
uint ip= 0;
LINT_INIT(olddbname);
if (olddbptr)
olddbname= my_strdup(olddbptr, MYF(MY_WME));
{
uint i= 0;
char *p= olddbptr;
/* Fast inline strncpy without padding... */
while (*p && i < sizeof(olddbname))
olddbname[i++]= *p++;
if (i == sizeof(olddbname))
i-= 1; // QQ Error or warning for truncate?
olddbname[i]= '\0';
}
do
{
......@@ -156,13 +171,12 @@ sp_head::execute(THD *thd)
ret= -1;
/* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */
if (olddbptr && olddbptr != thd->db && olddbname)
if (olddbptr && olddbptr != thd->db)
{
/* QQ Maybe we should issue some special error message or warning here,
if this fails?? */
if (! thd->killed)
ret= mysql_change_db(thd, olddbname);
my_free(olddbname, MYF(0));
}
DBUG_RETURN(ret);
}
......@@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd)
void
sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
{
bp_t *bp= (bp_t *)my_malloc(sizeof(bp_t), MYF(MY_WME));
bp_t *bp= (bp_t *)sql_alloc(sizeof(bp_t));
if (bp)
{
......
......@@ -52,21 +52,15 @@ public:
List<char *> m_tables; // Used tables.
#endif
static void *operator new(size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr, size_t size)
{
/* Empty */
}
sp_head(LEX_STRING *name, LEX *lex);
int
create(THD *thd);
// Free memory
void
destroy();
int
execute_function(THD *thd, Item **args, uint argcount, Item **resp);
......@@ -134,11 +128,13 @@ private:
inline sp_instr *
get_instr(uint i)
{
sp_instr *in= NULL;
sp_instr *ip;
if (i < m_instr.elements)
get_dynamic(&m_instr, (gptr)&in, i);
return in;
get_dynamic(&m_instr, (gptr)&ip, i);
else
ip= NULL;
return ip;
}
int
......
......@@ -27,30 +27,20 @@
#include "sp_head.h"
sp_pcontext::sp_pcontext()
: m_params(0), m_framesize(0), m_i(0), m_genlab(0)
: Sql_alloc(), m_params(0), m_framesize(0), m_genlab(0)
{
m_pvar_size = 16;
m_pvar = (sp_pvar_t *)my_malloc(m_pvar_size * sizeof(sp_pvar_t), MYF(MY_WME));
if (m_pvar)
memset(m_pvar, 0, m_pvar_size * sizeof(sp_pvar_t));
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
m_label.empty();
}
void
sp_pcontext::grow()
sp_pcontext::destroy()
{
uint sz = m_pvar_size + 8;
sp_pvar_t *a = (sp_pvar_t *)my_realloc((char *)m_pvar,
sz * sizeof(sp_pvar_t),
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (a)
{
m_pvar_size = sz;
m_pvar = a;
}
delete_dynamic(&m_pvar);
m_label.empty();
}
/* This does a linear search (from newer to older variables, in case
** we have shadowed names).
** It's possible to have a more efficient allocation and search method,
......@@ -61,19 +51,20 @@ sp_pcontext::grow()
sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name)
{
uint i = m_i;
uint i = m_pvar.elements;
while (i-- > 0)
{
uint len= (m_pvar[i].name.length > name->length ?
m_pvar[i].name.length : name->length);
sp_pvar_t *p= find_pvar(i);
uint len= (p->name.length > name->length ?
p->name.length : name->length);
if (my_strncasecmp(system_charset_info,
name->str,
m_pvar[i].name.str,
p->name.str,
len) == 0)
{
return m_pvar + i;
return p;
}
}
return NULL;
......@@ -83,26 +74,26 @@ void
sp_pcontext::push(LEX_STRING *name, enum enum_field_types type,
sp_param_mode_t mode)
{
if (m_i >= m_pvar_size)
grow();
if (m_i < m_pvar_size)
sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
if (p)
{
if (m_i == m_framesize)
if (m_pvar.elements == m_framesize)
m_framesize += 1;
m_pvar[m_i].name.str= name->str;
m_pvar[m_i].name.length= name->length,
m_pvar[m_i].type= type;
m_pvar[m_i].mode= mode;
m_pvar[m_i].offset= m_i;
m_pvar[m_i].isset= (mode == sp_param_out ? FALSE : TRUE);
m_i += 1;
p->name.str= name->str;
p->name.length= name->length;
p->type= type;
p->mode= mode;
p->offset= m_pvar.elements;
p->isset= (mode == sp_param_out ? FALSE : TRUE);
insert_dynamic(&m_pvar, (gptr)&p);
}
}
sp_label_t *
sp_pcontext::push_label(char *name, uint ip)
{
sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME));
sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
if (lab)
{
......
......@@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc
sp_pcontext();
// Free memory
void
destroy();
inline uint
max_framesize()
{
......@@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc
inline uint
current_framesize()
{
return m_i;
return m_pvar.elements;
}
inline uint
......@@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc
inline void
set_params()
{
m_params= m_i;
m_params= m_pvar.elements;
}
inline void
set_type(uint i, enum enum_field_types type)
{
if (i < m_i)
m_pvar[i].type= type;
sp_pvar_t *p= find_pvar(i);
if (p)
p->type= type;
}
inline void
set_isset(uint i, my_bool val)
{
if (i < m_i)
m_pvar[i].isset= val;
sp_pvar_t *p= find_pvar(i);
if (p)
p->isset= val;
}
void
......@@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc
inline void
pop(uint num = 1)
{
if (num < m_i)
m_i -= num;
while (num--)
pop_dynamic(&m_pvar);
}
// Find by name
......@@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc
sp_pvar_t *
find_pvar(uint i)
{
if (i >= m_i)
return NULL;
return m_pvar+i;
sp_pvar_t *p;
if (i < m_pvar.elements)
get_dynamic(&m_pvar, (gptr)&p, i);
else
p= NULL;
return p;
}
sp_label_t *
......@@ -138,13 +150,8 @@ private:
uint m_params; // The number of parameters
uint m_framesize; // The maximum framesize
uint m_i; // The current index (during parsing)
sp_pvar_t *m_pvar;
uint m_pvar_size; // Current size of m_pvar.
void
grow();
DYNAMIC_ARRAY m_pvar;
List<sp_label_t> m_label; // The label list
uint m_genlab; // Gen. label counter
......
......@@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0),
pthread_mutex_unlock(&LOCK_thread_count);
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
}
/* QQ init the temporary function cache */
spfuns.empty();
}
......@@ -282,6 +285,10 @@ void THD::cleanup(void)
pthread_mutex_unlock(&LOCK_user_locks);
ull= 0;
}
// extern void sp_clear_function_cache(THD *);
// sp_clear_function_cache(this);
cleanup_done=1;
DBUG_VOID_RETURN;
}
......
......@@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd)
sp_head *sph= sp_find_function(thd, &lex->udf.name);
if (sph)
{
sph->destroy(); // QQ Free memory. Remove this when caching!!!
net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
goto error;
}
......@@ -3050,6 +3051,8 @@ mysql_execute_command(THD *thd)
thd->net.no_send_ok= nsok;
#endif
sp->destroy(); // QQ Free memory. Remove this when caching!!!
if (res == 0)
send_ok(thd);
else
......@@ -3075,6 +3078,7 @@ mysql_execute_command(THD *thd)
{
/* QQ This is an no-op right now, since we haven't
put the characteristics in yet. */
sp->destroy(); // QQ Free memory. Remove this when caching!!!
send_ok(thd);
}
}
......
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