@ -105,7 +105,7 @@ trx_init(
trx - > op_info = " " ;
trx - > active_commit_ordered = 0 ;
trx - > active_commit_ordered = false ;
trx - > isolation_level = TRX_ISO_REPEATABLE_READ ;
@ -202,6 +202,15 @@ struct TrxFactory {
@ param trx the transaction for which to release resources */
static void destroy ( trx_t * trx )
{
# ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for AddressSanitizer */
MEM_UNDEFINED ( trx , sizeof * trx ) ;
# else
/* Declare the contents as initialized for Valgrind;
we checked this in trx_t : : free ( ) . */
MEM_MAKE_DEFINED ( trx , sizeof * trx ) ;
# endif
ut_a ( trx - > magic_n = = TRX_MAGIC_N ) ;
ut_ad ( ! trx - > in_rw_trx_list ) ;
ut_ad ( ! trx - > in_mysql_trx_list ) ;
@ -229,39 +238,6 @@ struct TrxFactory {
trx - > lock . table_locks . ~ lock_list ( ) ;
}
/** Enforce any invariants here, this is called before the transaction
is added to the pool .
@ return true if all OK */
static bool debug ( const trx_t * trx )
{
ut_a ( trx - > error_state = = DB_SUCCESS ) ;
ut_a ( trx - > magic_n = = TRX_MAGIC_N ) ;
ut_ad ( ! trx - > read_only ) ;
ut_ad ( trx - > state = = TRX_STATE_NOT_STARTED ) ;
ut_ad ( trx - > dict_operation = = TRX_DICT_OP_NONE ) ;
ut_ad ( trx - > mysql_thd = = 0 ) ;
ut_ad ( ! trx - > in_rw_trx_list ) ;
ut_ad ( ! trx - > in_mysql_trx_list ) ;
ut_a ( trx - > lock . wait_thr = = NULL ) ;
ut_a ( trx - > lock . wait_lock = = NULL ) ;
ut_a ( trx - > dict_operation_lock_mode = = 0 ) ;
ut_a ( UT_LIST_GET_LEN ( trx - > lock . trx_locks ) = = 0 ) ;
ut_ad ( trx - > autoinc_locks = = NULL ) ;
ut_ad ( trx - > lock . table_locks . empty ( ) ) ;
return ( true ) ;
}
} ;
/** The lock strategy for TrxPool */
@ -338,13 +314,23 @@ trx_pool_close()
trx_pools = 0 ;
}
/** @return a trx_t instance from trx_pools. */
static
trx_t *
trx_create_low ( )
/** @return allocated transaction object for internal operations */
trx_t * trx_allocate_for_background ( )
{
trx_t * trx = trx_pools - > get ( ) ;
# ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for AddressSanitizer.
It may have been poisoned in trx_t : : free ( ) . */
MEM_UNDEFINED ( trx , sizeof * trx ) ;
# else
/* Declare the memory initialized for Valgrind.
The trx_t that are released to the pool are
actually initialized ; we checked that by
MEM_CHECK_DEFINED ( ) in trx_t : : free ( ) . */
MEM_MAKE_DEFINED ( trx , sizeof * trx ) ;
# endif
assert_trx_is_free ( trx ) ;
mem_heap_t * heap ;
@ -360,14 +346,9 @@ trx_create_low()
alloc = ib_heap_allocator_create ( heap ) ;
/* Remember to free the vector explicitly in trx_free(). */
trx - > autoinc_locks = ib_vector_create ( alloc , sizeof ( void * * ) , 4 ) ;
/* Should have been either just initialized or .clear()ed by
trx_free ( ) . */
ut_ad ( trx - > mod_tables . empty ( ) ) ;
ut_ad ( trx - > lock . table_locks . empty ( ) ) ;
ut_ad ( UT_LIST_GET_LEN ( trx - > lock . trx_locks ) = = 0 ) ;
ut_ad ( trx - > lock . n_rec_locks = = 0 ) ;
ut_ad ( trx - > lock . table_cached = = 0 ) ;
ut_ad ( trx - > lock . rec_cached = = 0 ) ;
@ -379,71 +360,119 @@ trx_create_low()
return ( trx ) ;
}
/**
Release a trx_t instance back to the pool .
@ param trx the instance to release . */
static
void
trx_free ( trx_t * & trx )
/** Free the memory to trx_pools */
inline void trx_t : : free ( )
{
assert_trx_is_free ( trx ) ;
assert_trx_is_inactive ( this ) ;
trx - > mysql_thd = 0 ;
trx - > mysql_log_file_name = 0 ;
MEM_CHECK_DEFINED ( this , sizeof * this ) ;
// FIXME: We need to avoid this heap free/alloc for each commit.
if ( trx - > autoinc_locks ! = NULL ) {
ut_ad ( ib_vector_is_empty ( trx - > autoinc_locks ) ) ;
/* We allocated a dedicated heap for the vector. */
ib_vector_free ( trx - > autoinc_locks ) ;
trx - > autoinc_locks = NULL ;
}
ut_ad ( ! read_view ) ;
ut_ad ( ! will_lock ) ;
ut_ad ( error_state = = DB_SUCCESS ) ;
ut_ad ( magic_n = = TRX_MAGIC_N ) ;
ut_ad ( ! read_only ) ;
ut_ad ( ! in_mysql_trx_list ) ;
ut_ad ( ! lock . wait_lock ) ;
trx - > mod_tables . clear ( ) ;
mysql_thd = NULL ;
mysql_log_file_name = NULL ;
ut_ad ( trx - > read_view = = NULL ) ;
// FIXME: We need to avoid this heap free/alloc for each commit.
if ( autoinc_locks )
{
ut_ad ( ib_vector_is_empty ( autoinc_locks ) ) ;
/* We allocated a dedicated heap for the vector. */
ib_vector_free ( autoinc_locks ) ;
autoinc_locks = NULL ;
}
/* trx locking state should have been reset before returning trx
to pool */
ut_ad ( trx - > will_lock = = 0 ) ;
mod_tables . clear ( ) ;
trx_pools - > mem_free ( trx ) ;
# ifdef __SANITIZE_ADDRESS__
/* Unpoison the memory for innodb_monitor_set_option;
it is operating also on the freed transaction objects . */
MEM_UNDEFINED ( & trx - > mutex , sizeof trx - > mutex ) ;
MEM_UNDEFINED ( & trx - > undo_mutex , sizeof trx - > undo_mutex ) ;
/* For innobase_kill_connection() */
MEM_UNDEFINED ( & trx - > state , sizeof trx - > state ) ;
MEM_UNDEFINED ( & trx - > mysql_thd , sizeof trx - > mysql_thd ) ;
# endif
# ifdef HAVE_valgrind_or_MSAN
/* Unpoison the memory for innodb_monitor_set_option;
it is operating also on the freed transaction objects .
We checked that these were initialized in
trx_pools - > mem_free ( trx ) . */
MEM_MAKE_DEFINED ( & trx - > mutex , sizeof trx - > mutex ) ;
MEM_MAKE_DEFINED ( & trx - > undo_mutex , sizeof trx - > undo_mutex ) ;
/* For innobase_kill_connection() */
MEM_MAKE_DEFINED ( & trx - > state , sizeof trx - > state ) ;
MEM_MAKE_DEFINED ( & trx - > mysql_thd , sizeof trx - > mysql_thd ) ;
MEM_NOACCESS ( & n_ref , sizeof n_ref ) ;
/* do not poison mutex */
MEM_NOACCESS ( & id , sizeof id ) ;
MEM_NOACCESS ( & no , sizeof no ) ;
/* state is accessed by innobase_kill_connection() */
MEM_NOACCESS ( & is_recovered , sizeof is_recovered ) ;
# ifdef WITH_WSREP
MEM_NOACCESS ( & wsrep , sizeof wsrep ) ;
# endif
trx = NULL ;
}
/********************************************************************/ /**
Creates a transaction object for background operations by the master thread .
@ return own : transaction object */
trx_t *
trx_allocate_for_background ( void )
/*=============================*/
{
trx_t * trx ;
trx = trx_create_low ( ) ;
return ( trx ) ;
MEM_NOACCESS ( & read_view , sizeof read_view ) ;
MEM_NOACCESS ( & trx_list , sizeof trx_list ) ;
MEM_NOACCESS ( & no_list , sizeof no_list ) ;
MEM_NOACCESS ( & lock , sizeof lock ) ;
MEM_NOACCESS ( & op_info , sizeof op_info ) ;
MEM_NOACCESS ( & isolation_level , sizeof isolation_level ) ;
MEM_NOACCESS ( & check_foreigns , sizeof check_foreigns ) ;
MEM_NOACCESS ( & is_registered , sizeof is_registered ) ;
MEM_NOACCESS ( & active_commit_ordered , sizeof active_commit_ordered ) ;
MEM_NOACCESS ( & check_unique_secondary , sizeof check_unique_secondary ) ;
MEM_NOACCESS ( & flush_log_later , sizeof flush_log_later ) ;
MEM_NOACCESS ( & must_flush_log_later , sizeof must_flush_log_later ) ;
MEM_NOACCESS ( & duplicates , sizeof duplicates ) ;
MEM_NOACCESS ( & dict_operation , sizeof dict_operation ) ;
MEM_NOACCESS ( & declared_to_be_inside_innodb , sizeof declared_to_be_inside_innodb ) ;
MEM_NOACCESS ( & n_tickets_to_enter_innodb , sizeof n_tickets_to_enter_innodb ) ;
MEM_NOACCESS ( & dict_operation_lock_mode , sizeof dict_operation_lock_mode ) ;
MEM_NOACCESS ( & start_time , sizeof start_time ) ;
MEM_NOACCESS ( & start_time_micro , sizeof start_time_micro ) ;
MEM_NOACCESS ( & commit_lsn , sizeof commit_lsn ) ;
MEM_NOACCESS ( & table_id , sizeof table_id ) ;
/* mysql_thd is accessed by innobase_kill_connection() */
MEM_NOACCESS ( & mysql_log_file_name , sizeof mysql_log_file_name ) ;
MEM_NOACCESS ( & mysql_log_offset , sizeof mysql_log_offset ) ;
MEM_NOACCESS ( & n_mysql_tables_in_use , sizeof n_mysql_tables_in_use ) ;
MEM_NOACCESS ( & mysql_n_tables_locked , sizeof mysql_n_tables_locked ) ;
# ifdef UNIV_DEBUG
MEM_NOACCESS ( & in_rw_trx_list , sizeof in_rw_trx_list ) ;
# endif /* UNIV_DEBUG */
MEM_NOACCESS ( & mysql_trx_list , sizeof mysql_trx_list ) ;
# ifdef UNIV_DEBUG
MEM_NOACCESS ( & in_mysql_trx_list , sizeof in_mysql_trx_list ) ;
# endif /* UNIV_DEBUG */
MEM_NOACCESS ( & error_state , sizeof error_state ) ;
MEM_NOACCESS ( & error_info , sizeof error_info ) ;
MEM_NOACCESS ( & error_key_num , sizeof error_key_num ) ;
MEM_NOACCESS ( & graph , sizeof graph ) ;
MEM_NOACCESS ( & trx_savepoints , sizeof trx_savepoints ) ;
/* do not poison undo_mutex */
MEM_NOACCESS ( & undo_no , sizeof undo_no ) ;
MEM_NOACCESS ( & undo_rseg_space , sizeof undo_rseg_space ) ;
MEM_NOACCESS ( & last_sql_stat_start , sizeof last_sql_stat_start ) ;
MEM_NOACCESS ( & rsegs , sizeof rsegs ) ;
MEM_NOACCESS ( & roll_limit , sizeof roll_limit ) ;
# ifdef UNIV_DEBUG
MEM_NOACCESS ( & in_rollback , sizeof in_rollback ) ;
# endif /* UNIV_DEBUG */
MEM_NOACCESS ( & pages_undone , sizeof pages_undone ) ;
MEM_NOACCESS ( & n_autoinc_rows , sizeof n_autoinc_rows ) ;
MEM_NOACCESS ( & autoinc_locks , sizeof autoinc_locks ) ;
MEM_NOACCESS ( & read_only , sizeof read_only ) ;
MEM_NOACCESS ( & auto_commit , sizeof auto_commit ) ;
MEM_NOACCESS ( & will_lock , sizeof will_lock ) ;
MEM_NOACCESS ( & fts_trx , sizeof fts_trx ) ;
MEM_NOACCESS ( & fts_next_doc_id , sizeof fts_next_doc_id ) ;
MEM_NOACCESS ( & flush_tables , sizeof flush_tables ) ;
MEM_NOACCESS ( & ddl , sizeof ddl ) ;
MEM_NOACCESS ( & internal , sizeof internal ) ;
# ifdef UNIV_DEBUG
MEM_NOACCESS ( & start_line , sizeof start_line ) ;
MEM_NOACCESS ( & start_file , sizeof start_file ) ;
# endif /* UNIV_DEBUG */
MEM_NOACCESS ( & xid , sizeof xid ) ;
MEM_NOACCESS ( & mod_tables , sizeof mod_tables ) ;
MEM_NOACCESS ( & detailed_error , sizeof detailed_error ) ;
MEM_NOACCESS ( & flush_observer , sizeof flush_observer ) ;
MEM_NOACCESS ( & n_rec_lock_waits , sizeof n_rec_lock_waits ) ;
MEM_NOACCESS ( & n_table_lock_waits , sizeof n_table_lock_waits ) ;
MEM_NOACCESS ( & total_rec_lock_wait_time , sizeof total_rec_lock_wait_time ) ;
MEM_NOACCESS ( & total_table_lock_wait_time , sizeof total_table_lock_wait_time ) ;
# ifdef WITH_WSREP
MEM_NOACCESS ( & wsrep_event , sizeof wsrep_event ) ;
# endif /* WITH_WSREP */
MEM_NOACCESS ( & magic_n , sizeof magic_n ) ;
trx_pools - > mem_free ( this ) ;
}
/********************************************************************/ /**
@ -517,8 +546,7 @@ trx_free_resurrected(trx_t* trx)
trx_validate_state_before_free ( trx ) ;
trx_init ( trx ) ;
trx_free ( trx ) ;
trx - > free ( ) ;
}
/** Free a transaction that was allocated by background or user threads.
@ -527,8 +555,7 @@ void
trx_free_for_background ( trx_t * trx )
{
trx_validate_state_before_free ( trx ) ;
trx_free ( trx ) ;
trx - > free ( ) ;
}
/** Transition to committed state, to release implicit locks. */
@ -617,8 +644,7 @@ trx_free_prepared(
trx - > state = TRX_STATE_NOT_STARTED ;
ut_ad ( ! UT_LIST_GET_LEN ( trx - > lock . trx_locks ) ) ;
trx - > id = 0 ;
trx_free ( trx ) ;
trx - > free ( ) ;
}
/** Disconnect a transaction from MySQL and optionally mark it as if