Fixed memory overflow
This commit is contained in:
parent
a270e8abc4
commit
37ba4f37ac
@ -2809,7 +2809,8 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
TRN *trn;
|
TRN *trn;
|
||||||
int error;
|
int error;
|
||||||
uint locked_tables;
|
uint locked_tables;
|
||||||
MARIA_SHARE **used_tables= 0;
|
DYNAMIC_ARRAY used_tables;
|
||||||
|
|
||||||
DBUG_ENTER("ha_maria::implicit_commit");
|
DBUG_ENTER("ha_maria::implicit_commit");
|
||||||
if (!maria_hton || !(trn= THD_TRN))
|
if (!maria_hton || !(trn= THD_TRN))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -2825,32 +2826,37 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
DBUG_PRINT("info", ("locked_tables, skipping"));
|
DBUG_PRINT("info", ("locked_tables, skipping"));
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
if ((locked_tables= trnman_has_locked_tables(trn)))
|
|
||||||
{
|
|
||||||
MARIA_SHARE **used_tables_end;
|
|
||||||
MARIA_USED_TABLES *tables;
|
|
||||||
/* Save locked tables so that we can move them to another transaction */
|
|
||||||
|
|
||||||
used_tables= (MARIA_SHARE**) my_malloc((locked_tables+1) *
|
locked_tables= trnman_has_locked_tables(trn);
|
||||||
sizeof(MARIA_SHARE*),
|
|
||||||
MY_WME);
|
if (new_trn && trn && trn->used_tables)
|
||||||
used_tables_end= used_tables;
|
{
|
||||||
if (!used_tables)
|
MARIA_USED_TABLES *tables;
|
||||||
{
|
/*
|
||||||
/* Continue using the old transaction; Should be safe in most cases */
|
Save locked tables so that we can move them to another transaction
|
||||||
error= HA_ERR_OUT_OF_MEM;
|
We are using a dynamic array as locked_tables in some cases can be
|
||||||
goto end;
|
smaller than the used_tables list (for example when the server does
|
||||||
}
|
early unlock of tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_init_dynamic_array2(&used_tables, sizeof(MARIA_SHARE*), (void*) 0,
|
||||||
|
locked_tables, 8);
|
||||||
for (tables= (MARIA_USED_TABLES*) trn->used_tables;
|
for (tables= (MARIA_USED_TABLES*) trn->used_tables;
|
||||||
tables;
|
tables;
|
||||||
tables= tables->next)
|
tables= tables->next)
|
||||||
{
|
{
|
||||||
if (tables->share->base.born_transactional)
|
if (tables->share->base.born_transactional)
|
||||||
*used_tables_end++= tables->share;
|
{
|
||||||
|
if (insert_dynamic(&used_tables, (uchar*) &tables->share))
|
||||||
|
{
|
||||||
|
error= HA_ERR_OUT_OF_MEM;
|
||||||
|
goto end_and_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*used_tables_end= 0; // End marker
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
bzero(&used_tables, sizeof(used_tables));
|
||||||
|
|
||||||
error= 0;
|
error= 0;
|
||||||
if (unlikely(ma_commit(trn)))
|
if (unlikely(ma_commit(trn)))
|
||||||
@ -2875,7 +2881,7 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
if (unlikely(trn == NULL))
|
if (unlikely(trn == NULL))
|
||||||
{
|
{
|
||||||
error= HA_ERR_OUT_OF_MEM;
|
error= HA_ERR_OUT_OF_MEM;
|
||||||
goto end;
|
goto end_and_free;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Move all locked tables to the new transaction
|
Move all locked tables to the new transaction
|
||||||
@ -2884,28 +2890,27 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
when we should call _ma_setup_live_state() and in some cases, like
|
when we should call _ma_setup_live_state() and in some cases, like
|
||||||
in check table, we use the table without calling start_stmt().
|
in check table, we use the table without calling start_stmt().
|
||||||
*/
|
*/
|
||||||
if (used_tables)
|
|
||||||
{
|
|
||||||
MARIA_SHARE **tables;
|
|
||||||
for (tables= used_tables; *tables ; tables++)
|
|
||||||
{
|
|
||||||
MARIA_SHARE *share= *tables;
|
|
||||||
LIST *handlers;
|
|
||||||
|
|
||||||
/* Find table instances that was used in this transaction */
|
uint i;
|
||||||
for (handlers= share->open_list; handlers; handlers= handlers->next)
|
for (i= 0 ; i < used_tables.elements ; i++)
|
||||||
{
|
{
|
||||||
MARIA_HA *handler= (MARIA_HA*) handlers->data;
|
MARIA_SHARE *share;
|
||||||
if (handler->external_ref &&
|
LIST *handlers;
|
||||||
((TABLE*) handler->external_ref)->in_use == thd)
|
|
||||||
{
|
share= *(dynamic_element(&used_tables, i, MARIA_SHARE**));
|
||||||
_ma_set_trn_for_table(handler, trn);
|
/* Find table instances that was used in this transaction */
|
||||||
/* If handler uses versioning */
|
for (handlers= share->open_list; handlers; handlers= handlers->next)
|
||||||
if (handler->s->lock_key_trees)
|
{
|
||||||
{
|
MARIA_HA *handler= (MARIA_HA*) handlers->data;
|
||||||
if (_ma_setup_live_state(handler))
|
if (handler->external_ref &&
|
||||||
error= HA_ERR_OUT_OF_MEM;
|
((TABLE*) handler->external_ref)->in_use == thd)
|
||||||
}
|
{
|
||||||
|
_ma_set_trn_for_table(handler, trn);
|
||||||
|
/* If handler uses versioning */
|
||||||
|
if (handler->s->lock_key_trees)
|
||||||
|
{
|
||||||
|
if (_ma_setup_live_state(handler))
|
||||||
|
error= HA_ERR_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2913,8 +2918,9 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
/* This is just a commit, tables stay locked if they were: */
|
/* This is just a commit, tables stay locked if they were: */
|
||||||
trnman_reset_locked_tables(trn, locked_tables);
|
trnman_reset_locked_tables(trn, locked_tables);
|
||||||
|
|
||||||
|
end_and_free:
|
||||||
|
delete_dynamic(&used_tables);
|
||||||
end:
|
end:
|
||||||
my_free(used_tables);
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user