Commit 37ba4f37 authored by Michael Widenius's avatar Michael Widenius

Fixed memory overflow

parent a270e8ab
...@@ -2809,7 +2809,8 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) ...@@ -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) ...@@ -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)))
locked_tables= trnman_has_locked_tables(trn);
if (new_trn && trn && trn->used_tables)
{ {
MARIA_SHARE **used_tables_end;
MARIA_USED_TABLES *tables; MARIA_USED_TABLES *tables;
/* Save locked tables so that we can move them to another transaction */ /*
Save locked tables so that we can move them to another transaction
We are using a dynamic array as locked_tables in some cases can be
smaller than the used_tables list (for example when the server does
early unlock of tables.
*/
used_tables= (MARIA_SHARE**) my_malloc((locked_tables+1) * my_init_dynamic_array2(&used_tables, sizeof(MARIA_SHARE*), (void*) 0,
sizeof(MARIA_SHARE*), locked_tables, 8);
MY_WME);
used_tables_end= used_tables;
if (!used_tables)
{
/* Continue using the old transaction; Should be safe in most cases */
error= HA_ERR_OUT_OF_MEM;
goto end;
}
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) ...@@ -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) ...@@ -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)
uint i;
for (i= 0 ; i < used_tables.elements ; i++)
{ {
MARIA_SHARE **tables; MARIA_SHARE *share;
for (tables= used_tables; *tables ; tables++) LIST *handlers;
{
MARIA_SHARE *share= *tables;
LIST *handlers;
/* Find table instances that was used in this transaction */ share= *(dynamic_element(&used_tables, i, MARIA_SHARE**));
for (handlers= share->open_list; handlers; handlers= handlers->next) /* Find table instances that was used in this transaction */
{ for (handlers= share->open_list; handlers; handlers= handlers->next)
MARIA_HA *handler= (MARIA_HA*) handlers->data; {
if (handler->external_ref && MARIA_HA *handler= (MARIA_HA*) handlers->data;
((TABLE*) handler->external_ref)->in_use == thd) if (handler->external_ref &&
{ ((TABLE*) handler->external_ref)->in_use == thd)
_ma_set_trn_for_table(handler, trn); {
/* If handler uses versioning */ _ma_set_trn_for_table(handler, trn);
if (handler->s->lock_key_trees) /* If handler uses versioning */
{ if (handler->s->lock_key_trees)
if (_ma_setup_live_state(handler)) {
error= HA_ERR_OUT_OF_MEM; 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) ...@@ -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);
} }
......
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