Commit e9351c6f authored by marko's avatar marko

branches/zip: Initialize trx_dummy_sess only once. Require trx->sess to

be set always.

trx_rollback_active(): Split from trx_rollback_or_clean_all_without_sess().

row_undo_dictionary(): Do not return a value.  Assert that all operations
succeed.

row_merge_drop_index(): Remove bogus comment about void return value.

trx_dummy_sess: Move the declaration from trx0roll.h to trx0trx.h,
because the variable is defined in trx0trx.c.
parent fa5b997a
......@@ -48,7 +48,6 @@ Drop an index from the InnoDB system tables. */
void
row_merge_drop_index(
/*=================*/
/* out: error code or DB_SUCCESS */
dict_index_t* index, /* in: index to be removed */
dict_table_t* table, /* in: table */
trx_t* trx); /* in: transaction handle */
......
......@@ -63,10 +63,9 @@ row_undo_build_dict_undo_list(
/***************************************************************
Undo or redo a dictionary change */
ulint
void
row_undo_dictionary(
/*================*/
/* out: DB_SUCCESS or error code */
trx_t* trx, /* in: the transaction */
dict_undo_t* dict_undo); /* in: dict op to undo */
......
......@@ -247,8 +247,6 @@ trx_roll_savepoints_free(
if this is NULL, free all savepoints
of trx */
extern sess_t* trx_dummy_sess;
/* A cell in the array used during a rollback and a purge */
struct trx_undo_inf_struct{
dulint trx_no; /* transaction number: not defined during
......
......@@ -19,6 +19,11 @@ Created 3/26/1996 Heikki Tuuri
#include "dict0types.h"
#include "trx0xa.h"
/* Dummy session used currently in MySQL interface */
extern sess_t* trx_dummy_sess;
/* Number of transactions currently allocated for MySQL: protected by
the kernel mutex */
extern ulint trx_n_mysql_transactions;
/*****************************************************************
......@@ -87,7 +92,8 @@ trx_t*
trx_create(
/*=======*/
/* out, own: the transaction */
sess_t* sess); /* in: session or NULL */
sess_t* sess) /* in: session */
__attribute__((nonnull));
/************************************************************************
Creates a transaction object for MySQL. */
......
......@@ -1322,7 +1322,6 @@ Drop an index from the InnoDB system tables. */
void
row_merge_drop_index(
/*=================*/
/* out: error code or DB_SUCCESS */
dict_index_t* index, /* in: index to be removed */
dict_table_t* table, /* in: table */
trx_t* trx) /* in: transaction handle */
......
......@@ -483,8 +483,8 @@ row_undo_dictionary_parse_undo_rec(
}
/***************************************************************
Currently we gather all the information that is required to do the
UNDO. The actual UNDO is done later in row_undo_dictionary().*/
Currently we gather all the information that is required to do the
UNDO. The actual UNDO is done later in row_undo_dictionary(). */
ulint
row_undo_build_dict_undo_list(
......@@ -601,14 +601,16 @@ row_undo_build_dict_undo_list(
return(err);
}
ulint
/***************************************************************
Undo or redo a dictionary change. */
void
row_undo_dictionary(
/*================*/
/* out: DB_SUCCESS or error code */
trx_t* trx, /* in: transaction */
dict_undo_t* dict_undo) /* in: dict undo info */
{
ulint err = DB_SUCCESS;
ulint err;
switch (dict_undo->op_type) {
case TRX_UNDO_INDEX_CREATE_REC:
......@@ -625,6 +627,7 @@ row_undo_dictionary(
err = row_drop_table_for_mysql_no_commit(
dict_undo->data.table.old_table->name,
trx, FALSE);
ut_a(err == DB_SUCCESS);
}
break;
......@@ -643,30 +646,33 @@ row_undo_dictionary(
dict_undo->data.table.new_table->name,
trx, FALSE);
if (err == DB_SUCCESS) {
err = row_rename_table_for_mysql(
dict_undo->data.table.tmp_table->name,
dict_undo->data.table.old_table->name,
trx, FALSE);
}
ut_a(err == DB_SUCCESS);
if (err == DB_SUCCESS) {
err = row_rename_table_for_mysql(
dict_undo->data.table.tmp_table->name,
dict_undo->data.table.old_table->name,
trx, FALSE);
err = row_drop_table_for_mysql_no_commit(
dict_undo->data.table.new_table->name,
trx, FALSE);
}
ut_a(err == DB_SUCCESS);
err = row_drop_table_for_mysql_no_commit(
dict_undo->data.table.new_table->name,
trx, FALSE);
ut_a(err == DB_SUCCESS);
} else if (dict_undo->data.table.old_table) {
/* Rename to tmp failed.*/
ut_ad(!dict_undo->data.table.tmp_table);
ut_a(!dict_undo->data.table.tmp_table);
if (dict_undo->data.table.new_table) {
err = row_drop_table_for_mysql_no_commit(
dict_undo->data.table.new_table->name,
trx, FALSE);
ut_a(err == DB_SUCCESS);
}
} else if (dict_undo->data.table.tmp_table) {
......@@ -679,11 +685,15 @@ row_undo_dictionary(
dict_undo->data.table.old_table->name,
trx, FALSE);
ut_a(err == DB_SUCCESS);
if (dict_undo->data.table.new_table) {
err = row_drop_table_for_mysql_no_commit(
dict_undo->data.table.new_table->name,
trx, FALSE);
ut_a(err == DB_SUCCESS);
}
} else {
......@@ -694,7 +704,5 @@ row_undo_dictionary(
default:
ut_error;
}
return(err);
}
......@@ -135,22 +135,8 @@ trx_rollback_for_mysql(
the transaction object does not have an InnoDB session object, and we
set a dummy session that we use for all MySQL transactions. */
mutex_enter(&kernel_mutex);
if (trx->sess == NULL) {
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open();
}
trx->sess = trx_dummy_sess;
}
mutex_exit(&kernel_mutex);
err = trx_general_rollback_for_mysql(trx, FALSE, NULL);
trx->op_info = "";
return(err);
......@@ -404,94 +390,24 @@ trx_savept_take(
}
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread. */
os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
Roll back an active transaction. */
static
void
trx_rollback_active(
/*================*/
trx_t* trx) /* in/out: transaction */
{
mem_heap_t* heap;
que_fork_t* fork;
que_thr_t* thr;
roll_node_t* roll_node;
trx_t* trx;
dict_table_t* table;
ib_longlong rows_to_undo;
const char* unit = "";
int err = DB_SUCCESS;
ibool dictionary_locked = FALSE;
mutex_enter(&kernel_mutex);
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open();
}
mutex_exit(&kernel_mutex);
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
fprintf(stderr,
"InnoDB: Starting in background the rollback"
" of uncommitted transactions\n");
} else {
goto leave_function;
}
loop:
heap = mem_heap_create(512);
mutex_enter(&kernel_mutex);
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
while (trx) {
if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
trx = UT_LIST_GET_NEXT(trx_list, trx);
} else if (trx->conc_state == TRX_PREPARED) {
trx->sess = trx_dummy_sess;
trx = UT_LIST_GET_NEXT(trx_list, trx);
} else {
break;
}
}
mutex_exit(&kernel_mutex);
if (trx == NULL) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Rollback of non-prepared transactions"
" completed\n");
mem_heap_free(heap);
goto leave_function;
}
trx->sess = trx_dummy_sess;
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
(ulong) ut_dulint_get_high(trx->id),
(ulong) ut_dulint_get_low(trx->id));
trx_cleanup_at_db_startup(trx);
mem_heap_free(heap);
goto loop;
}
fork = que_fork_create(NULL, NULL, QUE_FORK_RECOVERY, heap);
fork->trx = trx;
......@@ -569,6 +485,8 @@ trx_rollback_or_clean_all_without_sess(
table = dict_table_get_on_id_low(trx->table_id);
if (table) {
ulint err;
fputs("InnoDB: Table found: dropping table ", stderr);
ut_print_name(stderr, trx, TRUE, table->name);
fputs(" in recovery\n", stderr);
......@@ -583,21 +501,12 @@ trx_rollback_or_clean_all_without_sess(
ut_a(trx->dict_undo_list);
dict_undo = UT_LIST_GET_FIRST(*trx->dict_undo_list);
fputs("InnoDB: UNDO dict entries\n", stderr);
while (dict_undo && err == DB_SUCCESS) {
dict_undo = UT_LIST_GET_NEXT(node, dict_undo);
if (dict_undo) {
err = row_undo_dictionary(trx, dict_undo);
}
for (dict_undo = UT_LIST_GET_FIRST(*trx->dict_undo_list);
dict_undo;
dict_undo = UT_LIST_GET_NEXT(node, dict_undo)) {
row_undo_dictionary(trx, dict_undo);
}
ut_a(err == (int) DB_SUCCESS);
dict_undo_free_list(trx);
mutex_enter(&kernel_mutex);
......@@ -615,8 +524,63 @@ trx_rollback_or_clean_all_without_sess(
mem_heap_free(heap);
trx_roll_crash_recv_trx = NULL;
}
goto loop;
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread. */
os_thread_ret_t
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
{
trx_t* trx;
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
fprintf(stderr,
"InnoDB: Starting in background the rollback"
" of uncommitted transactions\n");
} else {
goto leave_function;
}
loop:
mutex_enter(&kernel_mutex);
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
switch (trx->conc_state) {
case TRX_NOT_STARTED:
case TRX_PREPARED:
continue;
case TRX_COMMITTED_IN_MEMORY:
mutex_exit(&kernel_mutex);
fprintf(stderr,
"InnoDB: Cleaning up trx with id %lu %lu\n",
(ulong) ut_dulint_get_high(trx->id),
(ulong) ut_dulint_get_low(trx->id));
trx_cleanup_at_db_startup(trx);
goto loop;
case TRX_ACTIVE:
mutex_exit(&kernel_mutex);
trx_rollback_active(trx);
goto loop;
}
}
mutex_exit(&kernel_mutex);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Rollback of non-prepared transactions completed\n");
leave_function:
/* We count the number of threads in os_thread_exit(). A created
......
......@@ -984,6 +984,8 @@ trx_sys_init_at_db_start(void)
trx_purge_sys_create();
trx_dummy_sess = sess_open();
mutex_exit(&kernel_mutex);
mtr_commit(&mtr);
......
......@@ -87,11 +87,12 @@ trx_t*
trx_create(
/*=======*/
/* out, own: the transaction */
sess_t* sess) /* in: session or NULL */
sess_t* sess) /* in: session */
{
trx_t* trx;
ut_ad(mutex_own(&kernel_mutex));
ut_ad(sess);
trx = mem_alloc(sizeof(trx_t));
......@@ -206,12 +207,6 @@ trx_allocate_for_mysql(void)
mutex_enter(&kernel_mutex);
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open();
}
trx = trx_create(trx_dummy_sess);
trx_n_mysql_transactions++;
......@@ -239,12 +234,6 @@ trx_allocate_for_background(void)
mutex_enter(&kernel_mutex);
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open();
}
trx = trx_create(trx_dummy_sess);
mutex_exit(&kernel_mutex);
......@@ -455,7 +444,7 @@ trx_lists_init_at_db_start(void)
while (undo != NULL) {
trx = trx_create(NULL);
trx = trx_create(trx_dummy_sess);
trx->id = undo->trx_id;
trx->xid = undo->xid;
......@@ -533,7 +522,7 @@ trx_lists_init_at_db_start(void)
trx = trx_get_on_id(undo->trx_id);
if (NULL == trx) {
trx = trx_create(NULL);
trx = trx_create(trx_dummy_sess);
trx->id = undo->trx_id;
trx->xid = undo->xid;
......@@ -1573,22 +1562,8 @@ trx_commit_for_mysql(
trx->op_info = "committing";
/* If we are doing the XA recovery of prepared transactions, then
the transaction object does not have an InnoDB session object, and we
set the dummy session that we use for all MySQL transactions. */
mutex_enter(&kernel_mutex);
if (trx->sess == NULL) {
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open();
}
trx->sess = trx_dummy_sess;
}
trx_commit_off_kernel(trx);
mutex_exit(&kernel_mutex);
......
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