mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 22:12:30 +01:00
branches/zip: Free all resources at shutdown. Set pointers to NULL, so
that Valgrind will not complain about freed data structures that are reachable via pointers. This addresses Bug #45992 and Bug #46656. This patch is mostly based on changes copied from branches/embedded-1.0, mainly c5432, c3439, c3134, c2994, c2978, but also some other code was copied. Some added cleanup code is specific to MySQL/InnoDB. rb://199 approved by Sunny Bains
This commit is contained in:
parent
215f53bba3
commit
dda7217e08
48 changed files with 1003 additions and 159 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
2009-01-01 The InnoDB Team
|
||||
|
||||
* btr/btr0sea.c, buf/buf0buf.c, dict/dict0dict.c, fil/fil0fil.c,
|
||||
ibuf/ibuf0ibuf.c, include/btr0sea.h, include/dict0dict.h,
|
||||
include/fil0fil.h, include/ibuf0ibuf.h, include/lock0lock.h,
|
||||
include/log0log.h, include/log0recv.h, include/mem0mem.h,
|
||||
include/mem0pool.h, include/os0file.h, include/pars0pars.h,
|
||||
include/srv0srv.h, include/thr0loc.h, include/trx0i_s.h,
|
||||
include/trx0purge.h, include/trx0rseg.h, include/trx0sys.h,
|
||||
include/trx0undo.h, include/usr0sess.h, lock/lock0lock.c,
|
||||
log/log0log.c, log/log0recv.c, mem/mem0dbg.c, mem/mem0pool.c,
|
||||
os/os0file.c, os/os0sync.c, os/os0thread.c, pars/lexyy.c,
|
||||
pars/pars0lex.l, que/que0que.c, srv/srv0srv.c, srv/srv0start.c,
|
||||
sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c,
|
||||
trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c,
|
||||
usr/usr0sess.c, ut/ut0mem.c:
|
||||
Fix Bug #45992 innodb memory not freed after shutdown
|
||||
Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind)
|
||||
|
||||
2009-10-29 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
|
|
|
@ -175,6 +175,21 @@ btr_search_sys_create(
|
|||
btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Frees the adaptive search system at a database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_sys_free(void)
|
||||
/*=====================*/
|
||||
{
|
||||
mem_free(btr_search_latch_temp);
|
||||
btr_search_latch_temp = NULL;
|
||||
mem_heap_free(btr_search_sys->hash_index->heap);
|
||||
hash_table_free(btr_search_sys->hash_index);
|
||||
mem_free(btr_search_sys);
|
||||
btr_search_sys = NULL;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Disable the adaptive hash search system and empty the index. */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -1020,7 +1020,11 @@ buf_pool_free(void)
|
|||
os_mem_free_large(chunk->mem, chunk->mem_size);
|
||||
}
|
||||
|
||||
buf_pool->n_chunks = 0;
|
||||
mem_free(buf_pool->chunks);
|
||||
hash_table_free(buf_pool->page_hash);
|
||||
hash_table_free(buf_pool->zip_hash);
|
||||
mem_free(buf_pool);
|
||||
buf_pool = NULL;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
|
|
@ -4652,6 +4652,26 @@ dict_ind_init(void)
|
|||
dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Frees dict_ind_redundant and dict_ind_compact. */
|
||||
static
|
||||
void
|
||||
dict_ind_free(void)
|
||||
/*===============*/
|
||||
{
|
||||
dict_table_t* table;
|
||||
|
||||
table = dict_ind_compact->table;
|
||||
dict_mem_index_free(dict_ind_compact);
|
||||
dict_ind_compact = NULL;
|
||||
dict_mem_table_free(table);
|
||||
|
||||
table = dict_ind_redundant->table;
|
||||
dict_mem_index_free(dict_ind_redundant);
|
||||
dict_ind_redundant = NULL;
|
||||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************************//**
|
||||
Get index by name
|
||||
|
@ -4777,4 +4797,55 @@ dict_table_check_for_dup_indexes(
|
|||
}
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/**************************************************************************
|
||||
Closes the data dictionary module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_close(void)
|
||||
/*============*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
/* Free the hash elements. We don't remove them from the table
|
||||
because we are going to destroy the table anyway. */
|
||||
for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
|
||||
dict_table_t* table;
|
||||
|
||||
table = HASH_GET_FIRST(dict_sys->table_hash, i);
|
||||
|
||||
while (table) {
|
||||
dict_table_t* prev_table = table;
|
||||
|
||||
table = HASH_GET_NEXT(name_hash, prev_table);
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
#endif
|
||||
/* Acquire only because it's a pre-condition. */
|
||||
mutex_enter(&dict_sys->mutex);
|
||||
|
||||
dict_table_remove_from_cache(prev_table);
|
||||
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
hash_table_free(dict_sys->table_hash);
|
||||
|
||||
/* The elements are the same instance as in dict_sys->table_hash,
|
||||
therefore we don't delete the individual elements. */
|
||||
hash_table_free(dict_sys->table_id_hash);
|
||||
|
||||
dict_ind_free();
|
||||
|
||||
mutex_free(&dict_sys->mutex);
|
||||
|
||||
rw_lock_free(&dict_operation_lock);
|
||||
memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
|
||||
|
||||
mutex_free(&dict_foreign_err_mutex);
|
||||
|
||||
mem_free(dict_sys);
|
||||
dict_sys = NULL;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
|
@ -321,6 +321,17 @@ fil_get_space_id_for_table(
|
|||
/*=======================*/
|
||||
const char* name); /*!< in: table name in the standard
|
||||
'databasename/tablename' format */
|
||||
/*******************************************************************//**
|
||||
Frees a space object from the tablespace memory cache. Closes the files in
|
||||
the chain but does not delete them. There must not be any pending i/o's or
|
||||
flushes on the files. */
|
||||
static
|
||||
ibool
|
||||
fil_space_free(
|
||||
/*===========*/
|
||||
/* out: TRUE if success */
|
||||
ulint id, /* in: space id */
|
||||
ibool own_mutex);/* in: TRUE if own system->mutex */
|
||||
/********************************************************************//**
|
||||
Reads data from a space to a buffer. Remember that the possible incomplete
|
||||
blocks at the end of file are ignored: they are not taken into account when
|
||||
|
@ -1144,7 +1155,7 @@ try_again:
|
|||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
fil_space_free(namesake_id);
|
||||
fil_space_free(namesake_id, FALSE);
|
||||
|
||||
goto try_again;
|
||||
}
|
||||
|
@ -1269,17 +1280,21 @@ Frees a space object from the tablespace memory cache. Closes the files in
|
|||
the chain but does not delete them. There must not be any pending i/o's or
|
||||
flushes on the files.
|
||||
@return TRUE if success */
|
||||
UNIV_INTERN
|
||||
static
|
||||
ibool
|
||||
fil_space_free(
|
||||
/*===========*/
|
||||
ulint id) /*!< in: space id */
|
||||
/* out: TRUE if success */
|
||||
ulint id, /* in: space id */
|
||||
ibool own_mutex) /* in: TRUE if own system->mutex */
|
||||
{
|
||||
fil_space_t* space;
|
||||
fil_space_t* namespace;
|
||||
fil_node_t* fil_node;
|
||||
|
||||
mutex_enter(&fil_system->mutex);
|
||||
if (!own_mutex) {
|
||||
mutex_enter(&fil_system->mutex);
|
||||
}
|
||||
|
||||
space = fil_space_get_by_id(id);
|
||||
|
||||
|
@ -1326,7 +1341,9 @@ fil_space_free(
|
|||
|
||||
ut_a(0 == UT_LIST_GET_LEN(space->chain));
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
if (!own_mutex) {
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
|
||||
rw_lock_free(&(space->latch));
|
||||
|
||||
|
@ -1586,6 +1603,8 @@ fil_close_all_files(void)
|
|||
space = UT_LIST_GET_FIRST(fil_system->space_list);
|
||||
|
||||
while (space != NULL) {
|
||||
fil_space_t* prev_space = space;
|
||||
|
||||
node = UT_LIST_GET_FIRST(space->chain);
|
||||
|
||||
while (node != NULL) {
|
||||
|
@ -1595,6 +1614,7 @@ fil_close_all_files(void)
|
|||
node = UT_LIST_GET_NEXT(chain, node);
|
||||
}
|
||||
space = UT_LIST_GET_NEXT(space_list, space);
|
||||
fil_space_free(prev_space->id, TRUE);
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
@ -2226,7 +2246,7 @@ try_again:
|
|||
#endif
|
||||
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
|
||||
|
||||
success = fil_space_free(id);
|
||||
success = fil_space_free(id, FALSE);
|
||||
|
||||
if (success) {
|
||||
success = os_file_delete(path);
|
||||
|
@ -4753,3 +4773,26 @@ fil_page_get_type(
|
|||
|
||||
return(mach_read_from_2(page + FIL_PAGE_TYPE));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Initializes the tablespace memory cache. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_close(void)
|
||||
/*===========*/
|
||||
{
|
||||
/* The mutex should already have been freed. */
|
||||
ut_ad(fil_system->mutex.magic_n == 0);
|
||||
|
||||
hash_table_free(fil_system->spaces);
|
||||
|
||||
hash_table_free(fil_system->name_hash);
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
|
||||
|
||||
mem_free(fil_system);
|
||||
|
||||
fil_system = NULL;
|
||||
}
|
||||
|
|
|
@ -389,6 +389,27 @@ ibuf_count_set(
|
|||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************//**
|
||||
Closes insert buffer and frees the data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_close(void)
|
||||
/*============*/
|
||||
{
|
||||
mutex_free(&ibuf_pessimistic_insert_mutex);
|
||||
memset(&ibuf_pessimistic_insert_mutex,
|
||||
0x0, sizeof(ibuf_pessimistic_insert_mutex));
|
||||
|
||||
mutex_free(&ibuf_mutex);
|
||||
memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex));
|
||||
|
||||
mutex_free(&ibuf_bitmap_mutex);
|
||||
memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex));
|
||||
|
||||
mem_free(ibuf);
|
||||
ibuf = NULL;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Updates the size information of the ibuf, assuming the segment size has not
|
||||
changed. */
|
||||
|
|
|
@ -41,6 +41,12 @@ void
|
|||
btr_search_sys_create(
|
||||
/*==================*/
|
||||
ulint hash_size); /*!< in: hash index hash table size */
|
||||
/*****************************************************************//**
|
||||
Frees the adaptive search system at a database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_search_sys_free(void);
|
||||
/*=====================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Disable the adaptive hash search system and empty the index. */
|
||||
|
|
|
@ -1151,6 +1151,13 @@ void
|
|||
dict_ind_init(void);
|
||||
/*===============*/
|
||||
|
||||
/**********************************************************************//**
|
||||
Closes the data dictionary module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_close(void);
|
||||
/*============*/
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "dict0dict.ic"
|
||||
#endif
|
||||
|
|
|
@ -224,15 +224,6 @@ fil_space_create(
|
|||
0 for uncompressed tablespaces */
|
||||
ulint purpose);/*!< in: FIL_TABLESPACE, or FIL_LOG if log */
|
||||
/*******************************************************************//**
|
||||
Frees a space object from a the tablespace memory cache. Closes the files in
|
||||
the chain but does not delete them.
|
||||
@return TRUE if success */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fil_space_free(
|
||||
/*===========*/
|
||||
ulint id); /*!< in: space id */
|
||||
/*******************************************************************//**
|
||||
Returns the size of the space in pages. The tablespace must be cached in the
|
||||
memory cache.
|
||||
@return space size, 0 if space not found */
|
||||
|
@ -278,6 +269,12 @@ fil_init(
|
|||
ulint hash_size, /*!< in: hash table size */
|
||||
ulint max_n_open); /*!< in: max number of open files */
|
||||
/*******************************************************************//**
|
||||
Initializes the tablespace memory cache. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_close(void);
|
||||
/*===========*/
|
||||
/*******************************************************************//**
|
||||
Opens all log files and system tablespace data files. They stay open until the
|
||||
database server shutdown. This should be called at a server startup after the
|
||||
space objects for the log and the system tablespace have been created. The
|
||||
|
|
|
@ -356,6 +356,12 @@ void
|
|||
ibuf_print(
|
||||
/*=======*/
|
||||
FILE* file); /*!< in: file where to print */
|
||||
/******************************************************************//**
|
||||
Closes insert buffer and frees the data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ibuf_close(void);
|
||||
/*============*/
|
||||
|
||||
#define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO
|
||||
#define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO
|
||||
|
|
|
@ -59,6 +59,12 @@ lock_sys_create(
|
|||
/*============*/
|
||||
ulint n_cells); /*!< in: number of slots in lock hash table */
|
||||
/*********************************************************************//**
|
||||
Closes the lock system at database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_sys_close(void);
|
||||
/*================*/
|
||||
/*********************************************************************//**
|
||||
Checks if some transaction has an implicit x-lock on a record in a clustered
|
||||
index.
|
||||
@return transaction which has the x-lock, or NULL */
|
||||
|
|
|
@ -572,6 +572,18 @@ UNIV_INTERN
|
|||
void
|
||||
log_refresh_stats(void);
|
||||
/*===================*/
|
||||
/**********************************************************
|
||||
Shutdown the log system but do not release all the memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_shutdown(void);
|
||||
/*==============*/
|
||||
/**********************************************************
|
||||
Free the log system data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_mem_free(void);
|
||||
/*==============*/
|
||||
|
||||
extern log_t* log_sys;
|
||||
|
||||
|
@ -584,7 +596,7 @@ extern log_t* log_sys;
|
|||
#define LOG_RECOVER 98887331
|
||||
|
||||
/* The counting of lsn's starts from this value: this must be non-zero */
|
||||
#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE))
|
||||
#define LOG_START_LSN ((ib_uint64_t) (16 * OS_FILE_LOG_BLOCK_SIZE))
|
||||
|
||||
#define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE)
|
||||
#define LOG_ARCHIVE_BUF_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE / 4)
|
||||
|
@ -721,9 +733,12 @@ struct log_group_struct{
|
|||
ulint lsn_offset; /*!< the offset of the above lsn */
|
||||
ulint n_pending_writes;/*!< number of currently pending flush
|
||||
writes for this log group */
|
||||
byte** file_header_bufs_ptr;/*!< unaligned buffers */
|
||||
byte** file_header_bufs;/*!< buffers for each file
|
||||
header in the group */
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/*-----------------------------*/
|
||||
byte** archive_file_header_bufs_ptr;/*!< unaligned buffers */
|
||||
byte** archive_file_header_bufs;/*!< buffers for each file
|
||||
header in the group */
|
||||
ulint archive_space_id;/*!< file space which
|
||||
|
@ -742,10 +757,12 @@ struct log_group_struct{
|
|||
completion function then sets the new
|
||||
value to ..._file_no */
|
||||
ulint next_archived_offset; /*!< like the preceding field */
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
/*-----------------------------*/
|
||||
ib_uint64_t scanned_lsn; /*!< used only in recovery: recovery scan
|
||||
succeeded up to this lsn in this log
|
||||
group */
|
||||
byte* checkpoint_buf_ptr;/*!< unaligned checkpoint header */
|
||||
byte* checkpoint_buf; /*!< checkpoint header is written from
|
||||
this buffer to the group */
|
||||
UT_LIST_NODE_T(log_group_t)
|
||||
|
@ -763,6 +780,7 @@ struct log_struct{
|
|||
#ifndef UNIV_HOTBACKUP
|
||||
mutex_t mutex; /*!< mutex protecting the log */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
byte* buf_ptr; /* unaligned log buffer */
|
||||
byte* buf; /*!< log buffer */
|
||||
ulint buf_size; /*!< log buffer size in bytes */
|
||||
ulint max_buf_free; /*!< recommended maximum value of
|
||||
|
@ -899,6 +917,7 @@ struct log_struct{
|
|||
should wait for this without owning
|
||||
the log mutex */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
byte* checkpoint_buf_ptr;/* unaligned checkpoint header */
|
||||
byte* checkpoint_buf; /*!< checkpoint header is read to this
|
||||
buffer */
|
||||
/* @} */
|
||||
|
|
|
@ -239,6 +239,18 @@ UNIV_INTERN
|
|||
void
|
||||
recv_sys_create(void);
|
||||
/*=================*/
|
||||
/**********************************************************//**
|
||||
Release recovery system mutexes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_close(void);
|
||||
/*================*/
|
||||
/********************************************************//**
|
||||
Frees the recovery system memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_mem_free(void);
|
||||
/*===================*/
|
||||
/********************************************************//**
|
||||
Inits the recovery system for a recovery operation. */
|
||||
UNIV_INTERN
|
||||
|
@ -246,6 +258,12 @@ void
|
|||
recv_sys_init(
|
||||
/*==========*/
|
||||
ulint available_memory); /*!< in: available memory in bytes */
|
||||
/********************************************************//**
|
||||
Reset the state of the recovery system variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_var_init(void);
|
||||
/*===================*/
|
||||
/*******************************************************************//**
|
||||
Empties the hash table of stored log records, applying them to appropriate
|
||||
pages. */
|
||||
|
|
|
@ -82,6 +82,13 @@ void
|
|||
mem_init(
|
||||
/*=====*/
|
||||
ulint size); /*!< in: common pool size in bytes */
|
||||
/******************************************************************//**
|
||||
Closes the memory system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_close(void);
|
||||
/*===========*/
|
||||
|
||||
/**************************************************************//**
|
||||
Use this macro instead of the corresponding function! Macro for memory
|
||||
heap creation. */
|
||||
|
|
|
@ -62,6 +62,13 @@ mem_pool_create(
|
|||
/*============*/
|
||||
ulint size); /*!< in: pool size in bytes */
|
||||
/********************************************************************//**
|
||||
Frees a memory pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_pool_free(
|
||||
/*==========*/
|
||||
mem_pool_t* pool); /*!< in, own: memory pool */
|
||||
/********************************************************************//**
|
||||
Allocates memory from a pool. NOTE: This low-level function should only be
|
||||
used in mem0mem.*!
|
||||
@return own: allocated memory buffer */
|
||||
|
|
|
@ -620,6 +620,13 @@ os_aio_init(
|
|||
ulint n_write_segs, /*<! in: number of writer threads */
|
||||
ulint n_slots_sync); /*<! in: number of slots in the sync aio
|
||||
array */
|
||||
/***********************************************************************
|
||||
Frees the asynchronous io system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
os_aio_free(void);
|
||||
/*=============*/
|
||||
|
||||
/*******************************************************************//**
|
||||
Requests an asynchronous i/o operation.
|
||||
@return TRUE if request was queued successfully, FALSE if fail */
|
||||
|
|
|
@ -583,6 +583,12 @@ pars_info_get_bound_id(
|
|||
pars_info_t* info, /*!< in: info struct */
|
||||
const char* name); /*!< in: bound id name to find */
|
||||
|
||||
/******************************************************************//**
|
||||
Release any resources used by the lexer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
pars_lexer_close(void);
|
||||
/*==================*/
|
||||
|
||||
/** Extra information supplied for pars_sql(). */
|
||||
struct pars_info_struct {
|
||||
|
|
|
@ -411,7 +411,7 @@ void
|
|||
srv_init(void);
|
||||
/*==========*/
|
||||
/*********************************************************************//**
|
||||
Frees the OS fast mutex created in srv_boot(). */
|
||||
Frees the data structures created in srv_init(). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
srv_free(void);
|
||||
|
|
|
@ -39,6 +39,12 @@ UNIV_INTERN
|
|||
void
|
||||
thr_local_init(void);
|
||||
/*================*/
|
||||
/****************************************************************//**
|
||||
Close the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_close(void);
|
||||
/*=================*/
|
||||
/*******************************************************************//**
|
||||
Creates a local storage struct for the calling new thread. */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -141,6 +141,13 @@ void
|
|||
trx_i_s_cache_init(
|
||||
/*===============*/
|
||||
trx_i_s_cache_t* cache); /*!< out: cache to init */
|
||||
/*******************************************************************//**
|
||||
Free the INFORMATION SCHEMA trx related cache. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_i_s_cache_free(
|
||||
/*===============*/
|
||||
trx_i_s_cache_t* cache); /*!< in/out: cache to free */
|
||||
|
||||
/*******************************************************************//**
|
||||
Issue a shared/read lock on the tables cache. */
|
||||
|
|
|
@ -71,6 +71,12 @@ void
|
|||
trx_purge_sys_create(void);
|
||||
/*======================*/
|
||||
/********************************************************************//**
|
||||
Frees the global purge system control structure. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_purge_sys_close(void);
|
||||
/*======================*/
|
||||
/************************************************************************
|
||||
Adds the update undo log as the first log in the history list. Removes the
|
||||
update undo log segment from the rseg slot if it is too big for reuse. */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -125,6 +125,13 @@ trx_rseg_create(
|
|||
ulint max_size, /*!< in: max size in pages */
|
||||
ulint* id, /*!< out: rseg id */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/***************************************************************************
|
||||
Free's an instance of the rollback segment in memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_rseg_mem_free(
|
||||
/*==============*/
|
||||
trx_rseg_t* rseg); /* in, own: instance to free */
|
||||
|
||||
|
||||
/* Number of undo log slots in a rollback segment file copy */
|
||||
|
|
|
@ -334,6 +334,12 @@ void
|
|||
trx_sys_file_format_tag_init(void);
|
||||
/*==============================*/
|
||||
/*****************************************************************//**
|
||||
Shutdown/Close the transaction system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_close(void);
|
||||
/*===============*/
|
||||
/*****************************************************************//**
|
||||
Get the name representation of the file format from its id.
|
||||
@return pointer to the name */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -333,6 +333,13 @@ trx_undo_parse_discard_latest(
|
|||
byte* end_ptr,/*!< in: buffer end */
|
||||
page_t* page, /*!< in: page or NULL */
|
||||
mtr_t* mtr); /*!< in: mtr or NULL */
|
||||
/************************************************************************
|
||||
Frees an undo log memory copy. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_undo_mem_free(
|
||||
/*==============*/
|
||||
trx_undo_t* undo); /* in: the undo object to be freed */
|
||||
|
||||
/* Types of an undo log segment */
|
||||
#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */
|
||||
|
|
|
@ -44,14 +44,12 @@ sess_t*
|
|||
sess_open(void);
|
||||
/*============*/
|
||||
/*********************************************************************//**
|
||||
Closes a session, freeing the memory occupied by it, if it is in a state
|
||||
where it should be closed.
|
||||
@return TRUE if closed */
|
||||
Closes a session, freeing the memory occupied by it. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
sess_try_close(
|
||||
/*===========*/
|
||||
sess_t* sess); /*!< in, own: session object */
|
||||
void
|
||||
sess_close(
|
||||
/*=======*/
|
||||
sess_t* sess); /* in, own: session object */
|
||||
|
||||
/* The session handle. All fields are protected by the kernel mutex */
|
||||
struct sess_struct{
|
||||
|
|
|
@ -577,6 +577,23 @@ lock_sys_create(
|
|||
ut_a(lock_latest_err_file);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Closes the lock system at database shutdown. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
lock_sys_close(void)
|
||||
/*================*/
|
||||
{
|
||||
if (lock_latest_err_file != NULL) {
|
||||
fclose(lock_latest_err_file);
|
||||
lock_latest_err_file = NULL;
|
||||
}
|
||||
|
||||
hash_table_free(lock_sys->rec_hash);
|
||||
mem_free(lock_sys);
|
||||
lock_sys = NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the size of a lock struct.
|
||||
@return size in bytes */
|
||||
|
|
126
log/log0log.c
126
log/log0log.c
|
@ -771,8 +771,6 @@ void
|
|||
log_init(void)
|
||||
/*==========*/
|
||||
{
|
||||
byte* buf;
|
||||
|
||||
log_sys = mem_alloc(sizeof(log_t));
|
||||
|
||||
mutex_create(&log_sys->mutex, SYNC_LOG);
|
||||
|
@ -787,8 +785,8 @@ log_init(void)
|
|||
ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE);
|
||||
ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE);
|
||||
|
||||
buf = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
log_sys->buf = ut_align(buf, OS_FILE_LOG_BLOCK_SIZE);
|
||||
log_sys->buf_ptr = mem_alloc(LOG_BUFFER_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
log_sys->buf = ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
log_sys->buf_size = LOG_BUFFER_SIZE;
|
||||
|
||||
|
@ -833,9 +831,9 @@ log_init(void)
|
|||
|
||||
rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
log_sys->checkpoint_buf
|
||||
= ut_align(mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
log_sys->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE);
|
||||
log_sys->checkpoint_buf = ut_align(log_sys->checkpoint_buf_ptr,
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
|
||||
/*----------------------------*/
|
||||
|
||||
|
@ -918,23 +916,33 @@ log_group_init(
|
|||
group->lsn_offset = LOG_FILE_HDR_SIZE;
|
||||
group->n_pending_writes = 0;
|
||||
|
||||
group->file_header_bufs_ptr = mem_alloc(sizeof(byte*) * n_files);
|
||||
group->file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
group->archive_file_header_bufs_ptr = mem_alloc(
|
||||
sizeof(byte*) * n_files);
|
||||
group->archive_file_header_bufs = mem_alloc(sizeof(byte*) * n_files);
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
for (i = 0; i < n_files; i++) {
|
||||
*(group->file_header_bufs + i) = ut_align(
|
||||
mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE),
|
||||
group->file_header_bufs_ptr[i] = mem_alloc(
|
||||
LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
group->file_header_bufs[i] = ut_align(
|
||||
group->file_header_bufs_ptr[i],
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
memset(*(group->file_header_bufs + i), '\0',
|
||||
LOG_FILE_HDR_SIZE);
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
*(group->archive_file_header_bufs + i) = ut_align(
|
||||
mem_alloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE),
|
||||
group->archive_file_header_bufs_ptr[i] = mem_alloc(
|
||||
LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
group->archive_file_header_bufs[i] = ut_align(
|
||||
group->archive_file_header_bufs_ptr[i],
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
memset(*(group->archive_file_header_bufs + i), '\0',
|
||||
LOG_FILE_HDR_SIZE);
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
@ -947,8 +955,9 @@ log_group_init(
|
|||
group->archived_offset = 0;
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
group->checkpoint_buf = ut_align(
|
||||
mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), OS_FILE_LOG_BLOCK_SIZE);
|
||||
group->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE);
|
||||
group->checkpoint_buf = ut_align(group->checkpoint_buf_ptr,
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
memset(group->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
|
||||
|
||||
|
@ -3364,4 +3373,95 @@ log_refresh_stats(void)
|
|||
log_sys->n_log_ios_old = log_sys->n_log_ios;
|
||||
log_sys->last_printout_time = time(NULL);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Closes a log group. */
|
||||
static
|
||||
void
|
||||
log_group_close(
|
||||
/*===========*/
|
||||
log_group_t* group) /* in,own: log group to close */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < group->n_files; i++) {
|
||||
mem_free(group->file_header_bufs_ptr[i]);
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
mem_free(group->archive_file_header_bufs_ptr[i]);
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
}
|
||||
|
||||
mem_free(group->file_header_bufs_ptr);
|
||||
mem_free(group->file_header_bufs);
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
mem_free(group->archive_file_header_bufs_ptr);
|
||||
mem_free(group->archive_file_header_bufs);
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
mem_free(group->checkpoint_buf_ptr);
|
||||
|
||||
mem_free(group);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Shutdown the log system but do not release all the memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_shutdown(void)
|
||||
/*==============*/
|
||||
{
|
||||
log_group_t* group;
|
||||
|
||||
group = UT_LIST_GET_FIRST(log_sys->log_groups);
|
||||
|
||||
while (UT_LIST_GET_LEN(log_sys->log_groups) > 0) {
|
||||
log_group_t* prev_group = group;
|
||||
|
||||
group = UT_LIST_GET_NEXT(log_groups, group);
|
||||
UT_LIST_REMOVE(log_groups, log_sys->log_groups, prev_group);
|
||||
|
||||
log_group_close(prev_group);
|
||||
}
|
||||
|
||||
mem_free(log_sys->buf_ptr);
|
||||
log_sys->buf_ptr = NULL;
|
||||
log_sys->buf = NULL;
|
||||
mem_free(log_sys->checkpoint_buf_ptr);
|
||||
log_sys->checkpoint_buf_ptr = NULL;
|
||||
log_sys->checkpoint_buf = NULL;
|
||||
|
||||
os_event_free(log_sys->no_flush_event);
|
||||
os_event_free(log_sys->one_flushed_event);
|
||||
|
||||
rw_lock_free(&log_sys->checkpoint_lock);
|
||||
|
||||
mutex_free(&log_sys->mutex);
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
rw_lock_free(&log_sys->archive_lock);
|
||||
os_event_create(log_sys->archiving_on);
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
recv_sys_debug_free();
|
||||
#endif
|
||||
|
||||
recv_sys_close();
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
Free the log system data structures. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
log_mem_free(void)
|
||||
/*==============*/
|
||||
{
|
||||
if (log_sys != NULL) {
|
||||
recv_sys_mem_free();
|
||||
mem_free(log_sys);
|
||||
|
||||
log_sys = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
139
log/log0recv.c
139
log/log0recv.c
|
@ -69,15 +69,15 @@ UNIV_INTERN recv_sys_t* recv_sys = NULL;
|
|||
/** TRUE when applying redo log records during crash recovery; FALSE
|
||||
otherwise. Note that this is FALSE while a background thread is
|
||||
rolling back incomplete transactions. */
|
||||
UNIV_INTERN ibool recv_recovery_on = FALSE;
|
||||
UNIV_INTERN ibool recv_recovery_on;
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** TRUE when applying redo log records from an archived log file */
|
||||
UNIV_INTERN ibool recv_recovery_from_backup_on = FALSE;
|
||||
UNIV_INTERN ibool recv_recovery_from_backup_on;
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** TRUE when recv_init_crash_recovery() has been called. */
|
||||
UNIV_INTERN ibool recv_needed_recovery = FALSE;
|
||||
UNIV_INTERN ibool recv_needed_recovery;
|
||||
# ifdef UNIV_DEBUG
|
||||
/** TRUE if writing to the redo log (mtr_commit) is forbidden.
|
||||
Protected by log_sys->mutex. */
|
||||
|
@ -87,7 +87,7 @@ UNIV_INTERN ibool recv_no_log_write = FALSE;
|
|||
/** TRUE if buf_page_is_corrupted() should check if the log sequence
|
||||
number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by
|
||||
recv_recovery_from_checkpoint_start_func(). */
|
||||
UNIV_INTERN ibool recv_lsn_checks_on = FALSE;
|
||||
UNIV_INTERN ibool recv_lsn_checks_on;
|
||||
|
||||
/** There are two conditions under which we scan the logs, the first
|
||||
is normal startup and the second is when we do a recovery from an
|
||||
|
@ -97,7 +97,7 @@ startup. If we find log entries that were written after the last checkpoint
|
|||
we know that the server was not cleanly shutdown. We must then initialize
|
||||
the crash recovery environment before attempting to store these entries in
|
||||
the log hash table. */
|
||||
static ibool recv_log_scan_is_startup_type = FALSE;
|
||||
static ibool recv_log_scan_is_startup_type;
|
||||
|
||||
/** If the following is TRUE, the buffer pool file pages must be invalidated
|
||||
after recovery and no ibuf operations are allowed; this becomes TRUE if
|
||||
|
@ -108,7 +108,7 @@ buffer pool before the pages have been recovered to the up-to-date state.
|
|||
|
||||
TRUE means that recovery is running and no operations on the log files
|
||||
are allowed yet: the variable name is misleading. */
|
||||
UNIV_INTERN ibool recv_no_ibuf_operations = FALSE;
|
||||
UNIV_INTERN ibool recv_no_ibuf_operations;
|
||||
/** TRUE when the redo log is being backed up */
|
||||
# define recv_is_making_a_backup FALSE
|
||||
/** TRUE when recovering from a backed up redo log file */
|
||||
|
@ -116,30 +116,30 @@ UNIV_INTERN ibool recv_no_ibuf_operations = FALSE;
|
|||
#else /* !UNIV_HOTBACKUP */
|
||||
# define recv_needed_recovery FALSE
|
||||
/** TRUE when the redo log is being backed up */
|
||||
UNIV_INTERN ibool recv_is_making_a_backup = FALSE;
|
||||
UNIV_INTERN ibool recv_is_making_a_backup = FALSE;
|
||||
/** TRUE when recovering from a backed up redo log file */
|
||||
UNIV_INTERN ibool recv_is_from_backup = FALSE;
|
||||
# define buf_pool_get_curr_size() (5 * 1024 * 1024)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/** The following counter is used to decide when to print info on
|
||||
log scan */
|
||||
static ulint recv_scan_print_counter = 0;
|
||||
static ulint recv_scan_print_counter;
|
||||
|
||||
/** The type of the previous parsed redo log record */
|
||||
static ulint recv_previous_parsed_rec_type = 999999;
|
||||
static ulint recv_previous_parsed_rec_type;
|
||||
/** The offset of the previous parsed redo log record */
|
||||
static ulint recv_previous_parsed_rec_offset = 0;
|
||||
static ulint recv_previous_parsed_rec_offset;
|
||||
/** The 'multi' flag of the previous parsed redo log record */
|
||||
static ulint recv_previous_parsed_rec_is_multi = 0;
|
||||
static ulint recv_previous_parsed_rec_is_multi;
|
||||
|
||||
/** Maximum page number encountered in the redo log */
|
||||
UNIV_INTERN ulint recv_max_parsed_page_no = 0;
|
||||
UNIV_INTERN ulint recv_max_parsed_page_no;
|
||||
|
||||
/** This many frames must be left free in the buffer pool when we scan
|
||||
the log and store the scanned log records in the buffer pool: we will
|
||||
use these free frames to read in pages when we start applying the
|
||||
log records to the database. */
|
||||
UNIV_INTERN ulint recv_n_pool_free_frames = 256;
|
||||
UNIV_INTERN ulint recv_n_pool_free_frames;
|
||||
|
||||
/** The maximum lsn we see for a page during the recovery process. If this
|
||||
is bigger than the lsn we are able to scan up to, that is an indication that
|
||||
|
@ -170,7 +170,8 @@ recv_sys_create(void)
|
|||
return;
|
||||
}
|
||||
|
||||
recv_sys = mem_alloc(sizeof(recv_sys_t));
|
||||
recv_sys = mem_alloc(sizeof(*recv_sys));
|
||||
memset(recv_sys, 0x0, sizeof(*recv_sys));
|
||||
|
||||
mutex_create(&recv_sys->mutex, SYNC_RECV);
|
||||
|
||||
|
@ -179,6 +180,106 @@ recv_sys_create(void)
|
|||
}
|
||||
|
||||
/********************************************************//**
|
||||
Release recovery system mutexes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_close(void)
|
||||
/*================*/
|
||||
{
|
||||
if (recv_sys != NULL) {
|
||||
if (recv_sys->addr_hash != NULL) {
|
||||
hash_table_free(recv_sys->addr_hash);
|
||||
}
|
||||
|
||||
if (recv_sys->heap != NULL) {
|
||||
mem_heap_free(recv_sys->heap);
|
||||
}
|
||||
|
||||
if (recv_sys->buf != NULL) {
|
||||
ut_free(recv_sys->buf);
|
||||
}
|
||||
|
||||
if (recv_sys->last_block_buf_start != NULL) {
|
||||
mem_free(recv_sys->last_block_buf_start);
|
||||
}
|
||||
|
||||
mutex_free(&recv_sys->mutex);
|
||||
|
||||
mem_free(recv_sys);
|
||||
recv_sys = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Frees the recovery system memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_mem_free(void)
|
||||
/*===================*/
|
||||
{
|
||||
if (recv_sys != NULL) {
|
||||
if (recv_sys->addr_hash != NULL) {
|
||||
hash_table_free(recv_sys->addr_hash);
|
||||
}
|
||||
|
||||
if (recv_sys->heap != NULL) {
|
||||
mem_heap_free(recv_sys->heap);
|
||||
}
|
||||
|
||||
if (recv_sys->buf != NULL) {
|
||||
ut_free(recv_sys->buf);
|
||||
}
|
||||
|
||||
if (recv_sys->last_block_buf_start != NULL) {
|
||||
mem_free(recv_sys->last_block_buf_start);
|
||||
}
|
||||
|
||||
mem_free(recv_sys);
|
||||
recv_sys = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Reset the state of the recovery system variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
recv_sys_var_init(void)
|
||||
/*===================*/
|
||||
{
|
||||
recv_lsn_checks_on = FALSE;
|
||||
|
||||
recv_n_pool_free_frames = 256;
|
||||
|
||||
recv_recovery_on = FALSE;
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
recv_recovery_from_backup_on = FALSE;
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
|
||||
recv_needed_recovery = FALSE;
|
||||
|
||||
recv_lsn_checks_on = FALSE;
|
||||
|
||||
recv_log_scan_is_startup_type = FALSE;
|
||||
|
||||
recv_no_ibuf_operations = FALSE;
|
||||
|
||||
recv_scan_print_counter = 0;
|
||||
|
||||
recv_previous_parsed_rec_type = 999999;
|
||||
|
||||
recv_previous_parsed_rec_offset = 0;
|
||||
|
||||
recv_previous_parsed_rec_is_multi = 0;
|
||||
|
||||
recv_max_parsed_page_no = 0;
|
||||
|
||||
recv_n_pool_free_frames = 256;
|
||||
|
||||
recv_max_page_lsn = 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Inits the recovery system for a recovery operation. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
@ -253,8 +354,8 @@ recv_sys_empty_hash(void)
|
|||
Frees the recovery system. */
|
||||
static
|
||||
void
|
||||
recv_sys_free(void)
|
||||
/*===============*/
|
||||
recv_sys_debug_free(void)
|
||||
/*=====================*/
|
||||
{
|
||||
mutex_enter(&(recv_sys->mutex));
|
||||
|
||||
|
@ -263,8 +364,10 @@ recv_sys_free(void)
|
|||
ut_free(recv_sys->buf);
|
||||
mem_free(recv_sys->last_block_buf_start);
|
||||
|
||||
recv_sys->addr_hash = NULL;
|
||||
recv_sys->buf = NULL;
|
||||
recv_sys->heap = NULL;
|
||||
recv_sys->addr_hash = NULL;
|
||||
recv_sys->last_block_buf_start = NULL;
|
||||
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
}
|
||||
|
@ -3149,7 +3252,7 @@ recv_recovery_from_checkpoint_finish(void)
|
|||
recv_recovery_on = FALSE;
|
||||
|
||||
#ifndef UNIV_LOG_DEBUG
|
||||
recv_sys_free();
|
||||
recv_sys_debug_free();
|
||||
#endif
|
||||
/* Roll back any recovered data dictionary transactions, so
|
||||
that the data dictionary tables will be free of any locks.
|
||||
|
|
|
@ -170,6 +170,17 @@ mem_init(
|
|||
|
||||
mem_comm_pool = mem_pool_create(size);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Closes the memory system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_close(void)
|
||||
/*===========*/
|
||||
{
|
||||
mem_pool_free(mem_comm_pool);
|
||||
mem_comm_pool = NULL;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_MEM_DEBUG
|
||||
|
|
|
@ -260,6 +260,18 @@ mem_pool_create(
|
|||
return(pool);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Frees a memory pool. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
mem_pool_free(
|
||||
/*==========*/
|
||||
mem_pool_t* pool) /*!< in, own: memory pool */
|
||||
{
|
||||
ut_free(pool->buf);
|
||||
ut_free(pool);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Fills the specified free list.
|
||||
@return TRUE if we were able to insert a block to the free list */
|
||||
|
|
57
os/os0file.c
57
os/os0file.c
|
@ -3029,6 +3029,34 @@ os_aio_array_create(
|
|||
return(array);
|
||||
}
|
||||
|
||||
/************************************************************************//**
|
||||
Frees an aio wait array. */
|
||||
static
|
||||
void
|
||||
os_aio_array_free(
|
||||
/*==============*/
|
||||
os_aio_array_t* array) /*!< in, own: array to free */
|
||||
{
|
||||
#ifdef WIN_ASYNC_IO
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < array->n_slots; i++) {
|
||||
os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i);
|
||||
os_event_free(slot->event);
|
||||
}
|
||||
#endif /* WIN_ASYNC_IO */
|
||||
|
||||
#ifdef __WIN__
|
||||
ut_free(array->native_events);
|
||||
#endif /* __WIN__ */
|
||||
os_mutex_free(array->mutex);
|
||||
os_event_free(array->not_full);
|
||||
os_event_free(array->is_empty);
|
||||
|
||||
ut_free(array->slots);
|
||||
ut_free(array);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Initializes the asynchronous io system. Creates one array each for ibuf
|
||||
and log i/o. Also creates one array each for read and write where each
|
||||
|
@ -3099,6 +3127,35 @@ os_aio_init(
|
|||
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Frees the asynchronous io system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
os_aio_free(void)
|
||||
/*=============*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
os_aio_array_free(os_aio_ibuf_array);
|
||||
os_aio_ibuf_array = NULL;
|
||||
os_aio_array_free(os_aio_log_array);
|
||||
os_aio_log_array = NULL;
|
||||
os_aio_array_free(os_aio_read_array);
|
||||
os_aio_read_array = NULL;
|
||||
os_aio_array_free(os_aio_write_array);
|
||||
os_aio_write_array = NULL;
|
||||
os_aio_array_free(os_aio_sync_array);
|
||||
os_aio_sync_array = NULL;
|
||||
|
||||
for (i = 0; i < os_aio_n_segments; i++) {
|
||||
os_event_free(os_aio_segment_wait_events[i]);
|
||||
}
|
||||
|
||||
ut_free(os_aio_segment_wait_events);
|
||||
os_aio_segment_wait_events = 0;
|
||||
os_aio_n_segments = 0;
|
||||
}
|
||||
|
||||
#ifdef WIN_ASYNC_IO
|
||||
/************************************************************************//**
|
||||
Wakes up all async i/o threads in the array in Windows async i/o at
|
||||
|
|
|
@ -86,6 +86,9 @@ os_sync_init(void)
|
|||
UT_LIST_INIT(os_event_list);
|
||||
UT_LIST_INIT(os_mutex_list);
|
||||
|
||||
os_sync_mutex = NULL;
|
||||
os_sync_mutex_inited = FALSE;
|
||||
|
||||
os_sync_mutex = os_mutex_create(NULL);
|
||||
|
||||
os_sync_mutex_inited = TRUE;
|
||||
|
@ -713,6 +716,7 @@ os_fast_mutex_free(
|
|||
os_mutex_enter(os_sync_mutex);
|
||||
}
|
||||
|
||||
ut_ad(os_fast_mutex_count > 0);
|
||||
os_fast_mutex_count--;
|
||||
|
||||
if (UNIV_LIKELY(os_sync_mutex_inited)) {
|
||||
|
|
|
@ -233,6 +233,7 @@ os_thread_exit(
|
|||
#ifdef __WIN__
|
||||
ExitThread((DWORD)exit_value);
|
||||
#else
|
||||
pthread_detach(pthread_self());
|
||||
pthread_exit(exit_value);
|
||||
#endif
|
||||
}
|
||||
|
|
13
pars/lexyy.c
13
pars/lexyy.c
|
@ -2778,3 +2778,16 @@ static void yyfree (void * ptr )
|
|||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Release any resources used by the lexer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
pars_lexer_close(void)
|
||||
/*==================*/
|
||||
{
|
||||
yylex_destroy();
|
||||
free(stringbuf);
|
||||
stringbuf = NULL;
|
||||
stringbuf_len_alloc = stringbuf_len = 0;
|
||||
}
|
||||
|
|
|
@ -661,3 +661,16 @@ In the state 'id', only two actions are possible (defined below). */
|
|||
}
|
||||
|
||||
%%
|
||||
|
||||
/**********************************************************************
|
||||
Release any resources used by the lexer. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
pars_lexer_close(void)
|
||||
/*==================*/
|
||||
{
|
||||
yylex_destroy();
|
||||
free(stringbuf);
|
||||
stringbuf = NULL;
|
||||
stringbuf_len_alloc = stringbuf_len = 0;
|
||||
}
|
||||
|
|
|
@ -518,6 +518,7 @@ que_graph_free_recursive(
|
|||
upd_node_t* upd;
|
||||
tab_node_t* cre_tab;
|
||||
ind_node_t* cre_ind;
|
||||
purge_node_t* purge;
|
||||
|
||||
if (node == NULL) {
|
||||
|
||||
|
@ -579,6 +580,13 @@ que_graph_free_recursive(
|
|||
mem_heap_free(ins->entry_sys_heap);
|
||||
|
||||
break;
|
||||
case QUE_NODE_PURGE:
|
||||
purge = node;
|
||||
|
||||
mem_heap_free(purge->heap);
|
||||
|
||||
break;
|
||||
|
||||
case QUE_NODE_UPDATE:
|
||||
|
||||
upd = node;
|
||||
|
|
|
@ -1006,13 +1006,26 @@ srv_init(void)
|
|||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Frees the OS fast mutex created in srv_init(). */
|
||||
Frees the data structures created in srv_init(). */
|
||||
UNIV_INTERN
|
||||
void
|
||||
srv_free(void)
|
||||
/*==========*/
|
||||
{
|
||||
os_fast_mutex_free(&srv_conc_mutex);
|
||||
mem_free(srv_conc_slots);
|
||||
srv_conc_slots = NULL;
|
||||
|
||||
mem_free(srv_sys->threads);
|
||||
mem_free(srv_sys);
|
||||
srv_sys = NULL;
|
||||
|
||||
mem_free(kernel_mutex_temp);
|
||||
kernel_mutex_temp = NULL;
|
||||
mem_free(srv_mysql_table);
|
||||
srv_mysql_table = NULL;
|
||||
|
||||
trx_i_s_cache_free(trx_i_s_cache);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
@ -1024,6 +1037,8 @@ srv_general_init(void)
|
|||
/*==================*/
|
||||
{
|
||||
ut_mem_init();
|
||||
/* Reset the system variables in the recovery module. */
|
||||
recv_sys_var_init();
|
||||
os_sync_init();
|
||||
sync_init();
|
||||
mem_init(srv_mem_pool_size);
|
||||
|
|
105
srv/srv0start.c
105
srv/srv0start.c
|
@ -103,6 +103,7 @@ Created 2/16/1996 Heikki Tuuri
|
|||
# include "row0row.h"
|
||||
# include "row0mysql.h"
|
||||
# include "btr0pcur.h"
|
||||
# include "thr0loc.h"
|
||||
# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
|
||||
/** Log sequence number immediately after startup */
|
||||
|
@ -495,6 +496,8 @@ io_handler_thread(
|
|||
mutex_exit(&ios_mutex);
|
||||
}
|
||||
|
||||
thr_local_free(os_thread_get_curr_id());
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
|
@ -531,32 +534,6 @@ srv_normalize_path_for_win(
|
|||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Adds a slash or a backslash to the end of a string if it is missing
|
||||
and the string is not empty.
|
||||
@return string which has the separator if the string is not empty */
|
||||
UNIV_INTERN
|
||||
char*
|
||||
srv_add_path_separator_if_needed(
|
||||
/*=============================*/
|
||||
char* str) /*!< in: null-terminated character string */
|
||||
{
|
||||
char* out_str;
|
||||
ulint len = ut_strlen(str);
|
||||
|
||||
if (len == 0 || str[len - 1] == SRV_PATH_SEPARATOR) {
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
out_str = ut_malloc(len + 2);
|
||||
memcpy(out_str, str, len);
|
||||
out_str[len] = SRV_PATH_SEPARATOR;
|
||||
out_str[len + 1] = 0;
|
||||
|
||||
return(out_str);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Calculates the low 32 bits when a file size which is given as a number
|
||||
|
@ -605,19 +582,24 @@ open_or_create_log_file(
|
|||
ulint size;
|
||||
ulint size_high;
|
||||
char name[10000];
|
||||
ulint dirnamelen;
|
||||
|
||||
UT_NOT_USED(create_new_db);
|
||||
|
||||
*log_file_created = FALSE;
|
||||
|
||||
srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
|
||||
srv_log_group_home_dirs[k] = srv_add_path_separator_if_needed(
|
||||
srv_log_group_home_dirs[k]);
|
||||
|
||||
ut_a(strlen(srv_log_group_home_dirs[k])
|
||||
< (sizeof name) - 10 - sizeof "ib_logfile");
|
||||
sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k],
|
||||
"ib_logfile", (ulong) i);
|
||||
dirnamelen = strlen(srv_log_group_home_dirs[k]);
|
||||
ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile");
|
||||
memcpy(name, srv_log_group_home_dirs[k], dirnamelen);
|
||||
|
||||
/* Add a path separator if needed. */
|
||||
if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
|
||||
name[dirnamelen++] = SRV_PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
|
||||
|
||||
files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL,
|
||||
OS_LOG_FILE, &ret);
|
||||
|
@ -780,14 +762,22 @@ open_or_create_data_files(
|
|||
*create_new_db = FALSE;
|
||||
|
||||
srv_normalize_path_for_win(srv_data_home);
|
||||
srv_data_home = srv_add_path_separator_if_needed(srv_data_home);
|
||||
|
||||
for (i = 0; i < srv_n_data_files; i++) {
|
||||
srv_normalize_path_for_win(srv_data_file_names[i]);
|
||||
ulint dirnamelen;
|
||||
|
||||
ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i])
|
||||
srv_normalize_path_for_win(srv_data_file_names[i]);
|
||||
dirnamelen = strlen(srv_data_home);
|
||||
|
||||
ut_a(dirnamelen + strlen(srv_data_file_names[i])
|
||||
< (sizeof name) - 1);
|
||||
sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]);
|
||||
memcpy(name, srv_data_home, dirnamelen);
|
||||
/* Add a path separator if needed. */
|
||||
if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
|
||||
name[dirnamelen++] = SRV_PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
strcpy(name + dirnamelen, srv_data_file_names[i]);
|
||||
|
||||
if (srv_data_file_is_raw_partition[i] == 0) {
|
||||
|
||||
|
@ -1009,7 +999,7 @@ skip_size_check:
|
|||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
/********************************************************************
|
||||
Starts InnoDB and creates a new database if database files
|
||||
are not found and the user wants.
|
||||
@return DB_SUCCESS or error code */
|
||||
|
@ -1120,7 +1110,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
|
||||
if (srv_start_has_been_called) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error:startup called second time"
|
||||
"InnoDB: Error: startup called second time"
|
||||
" during the process lifetime.\n"
|
||||
"InnoDB: In the MySQL Embedded Server Library"
|
||||
" you cannot call server_init()\n"
|
||||
|
@ -1959,8 +1949,10 @@ innobase_shutdown_for_mysql(void)
|
|||
/* All the threads have exited or are just exiting;
|
||||
NOTE that the threads may not have completed their
|
||||
exit yet. Should we use pthread_join() to make sure
|
||||
they have exited? Now we just sleep 0.1 seconds and
|
||||
hope that is enough! */
|
||||
they have exited? If we did, we would have to
|
||||
remove the pthread_detach() from
|
||||
os_thread_exit(). Now we just sleep 0.1
|
||||
seconds and hope that is enough! */
|
||||
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
||||
|
@ -1999,37 +1991,41 @@ innobase_shutdown_for_mysql(void)
|
|||
srv_misc_tmpfile = 0;
|
||||
}
|
||||
|
||||
/* This must be disabled before closing the buffer pool
|
||||
and closing the data dictionary. */
|
||||
btr_search_disable();
|
||||
|
||||
ibuf_close();
|
||||
log_shutdown();
|
||||
lock_sys_close();
|
||||
thr_local_close();
|
||||
trx_sys_file_format_close();
|
||||
trx_sys_close();
|
||||
|
||||
mutex_free(&srv_monitor_file_mutex);
|
||||
mutex_free(&srv_dict_tmpfile_mutex);
|
||||
mutex_free(&srv_misc_tmpfile_mutex);
|
||||
dict_close();
|
||||
btr_search_sys_free();
|
||||
|
||||
/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
|
||||
them */
|
||||
os_aio_free();
|
||||
sync_close();
|
||||
srv_free();
|
||||
fil_close();
|
||||
|
||||
/* 4. Free the os_conc_mutex and all os_events and os_mutexes */
|
||||
|
||||
srv_free();
|
||||
os_sync_free();
|
||||
|
||||
/* Check that all read views are closed except read view owned
|
||||
by a purge. */
|
||||
|
||||
if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: all read views were not closed"
|
||||
" before shutdown:\n"
|
||||
"InnoDB: %lu read views open \n",
|
||||
UT_LIST_GET_LEN(trx_sys->view_list) - 1);
|
||||
}
|
||||
|
||||
/* 5. Free all allocated memory and the os_fast_mutex created in
|
||||
ut0mem.c */
|
||||
/* 5. Free all allocated memory */
|
||||
|
||||
pars_lexer_close();
|
||||
log_mem_free();
|
||||
buf_pool_free();
|
||||
ut_free_all_mem();
|
||||
mem_close();
|
||||
|
||||
if (os_thread_count != 0
|
||||
|| os_event_count != 0
|
||||
|
@ -2060,6 +2056,7 @@ innobase_shutdown_for_mysql(void)
|
|||
}
|
||||
|
||||
srv_was_started = FALSE;
|
||||
srv_start_has_been_called = FALSE;
|
||||
|
||||
return((int) DB_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -227,24 +227,21 @@ sync_array_create(
|
|||
SYNC_ARRAY_MUTEX: determines the type
|
||||
of mutex protecting the data structure */
|
||||
{
|
||||
ulint sz;
|
||||
sync_array_t* arr;
|
||||
sync_cell_t* cell_array;
|
||||
sync_cell_t* cell;
|
||||
ulint i;
|
||||
|
||||
ut_a(n_cells > 0);
|
||||
|
||||
/* Allocate memory for the data structures */
|
||||
arr = ut_malloc(sizeof(sync_array_t));
|
||||
memset(arr, 0x0, sizeof(*arr));
|
||||
|
||||
cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells);
|
||||
sz = sizeof(sync_cell_t) * n_cells;
|
||||
arr->array = ut_malloc(sz);
|
||||
memset(arr->array, 0x0, sz);
|
||||
|
||||
arr->n_cells = n_cells;
|
||||
arr->n_reserved = 0;
|
||||
arr->array = cell_array;
|
||||
arr->protection = protection;
|
||||
arr->sg_count = 0;
|
||||
arr->res_count = 0;
|
||||
|
||||
/* Then create the mutex to protect the wait array complex */
|
||||
if (protection == SYNC_ARRAY_OS_MUTEX) {
|
||||
|
@ -255,13 +252,6 @@ sync_array_create(
|
|||
ut_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_cells; i++) {
|
||||
cell = sync_array_get_nth_cell(arr, i);
|
||||
cell->wait_object = NULL;
|
||||
cell->waiting = FALSE;
|
||||
cell->signal_count = 0;
|
||||
}
|
||||
|
||||
return(arr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1377,7 +1377,12 @@ sync_close(void)
|
|||
mutex_free(&mutex_list_mutex);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
mutex_free(&sync_thread_mutex);
|
||||
|
||||
/* Switch latching order checks on in sync0sync.c */
|
||||
sync_order_checks_on = FALSE;
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
sync_initialized = FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
|
|
|
@ -246,3 +246,34 @@ thr_local_init(void)
|
|||
|
||||
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Close the thread local storage module. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thr_local_close(void)
|
||||
/*=================*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_a(thr_local_hash != NULL);
|
||||
|
||||
/* Free the hash elements. We don't remove them from the table
|
||||
because we are going to destroy the table anyway. */
|
||||
for (i = 0; i < hash_get_n_cells(thr_local_hash); i++) {
|
||||
thr_local_t* local;
|
||||
|
||||
local = HASH_GET_FIRST(thr_local_hash, i);
|
||||
|
||||
while (local) {
|
||||
thr_local_t* prev_local = local;
|
||||
|
||||
local = HASH_GET_NEXT(hash, prev_local);
|
||||
ut_a(prev_local->magic_n == THR_LOCAL_MAGIC_N);
|
||||
mem_free(prev_local);
|
||||
}
|
||||
}
|
||||
|
||||
hash_table_free(thr_local_hash);
|
||||
thr_local_hash = NULL;
|
||||
}
|
||||
|
|
|
@ -237,6 +237,27 @@ table_cache_init(
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees a table cache. */
|
||||
static
|
||||
void
|
||||
table_cache_free(
|
||||
/*=============*/
|
||||
i_s_table_cache_t* table_cache) /*!< in/out: table cache */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
|
||||
|
||||
/* the memory is actually allocated in
|
||||
table_cache_create_empty_row() */
|
||||
if (table_cache->chunks[i].base) {
|
||||
mem_free(table_cache->chunks[i].base);
|
||||
table_cache->chunks[i].base = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Returns an empty row from a table cache. The row is allocated if no more
|
||||
empty rows are available. The number of used rows is incremented.
|
||||
|
@ -1251,6 +1272,22 @@ trx_i_s_cache_init(
|
|||
cache->is_truncated = FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Free the INFORMATION SCHEMA trx related cache. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_i_s_cache_free(
|
||||
/*===============*/
|
||||
trx_i_s_cache_t* cache) /*!< in, own: cache to free */
|
||||
{
|
||||
hash_table_free(cache->locks_hash);
|
||||
ha_storage_free(cache->storage);
|
||||
table_cache_free(&cache->innodb_trx);
|
||||
table_cache_free(&cache->innodb_locks);
|
||||
table_cache_free(&cache->innodb_lock_waits);
|
||||
memset(cache, 0, sizeof *cache);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Issue a shared/read lock on the tables cache. */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -249,6 +249,44 @@ trx_purge_sys_create(void)
|
|||
purge_sys->heap);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Frees the global purge system control structure. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_purge_sys_close(void)
|
||||
/*======================*/
|
||||
{
|
||||
ut_ad(!mutex_own(&kernel_mutex));
|
||||
|
||||
que_graph_free(purge_sys->query);
|
||||
|
||||
ut_a(purge_sys->sess->trx->is_purge);
|
||||
purge_sys->sess->trx->conc_state = TRX_NOT_STARTED;
|
||||
sess_close(purge_sys->sess);
|
||||
purge_sys->sess = NULL;
|
||||
|
||||
if (purge_sys->view != NULL) {
|
||||
/* Because acquiring the kernel mutex is a pre-condition
|
||||
of read_view_close(). We don't really need it here. */
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
read_view_close(purge_sys->view);
|
||||
purge_sys->view = NULL;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
trx_undo_arr_free(purge_sys->arr);
|
||||
|
||||
rw_lock_free(&purge_sys->latch);
|
||||
mutex_free(&purge_sys->mutex);
|
||||
|
||||
mem_heap_free(purge_sys->heap);
|
||||
mem_free(purge_sys);
|
||||
|
||||
purge_sys = NULL;
|
||||
}
|
||||
|
||||
/*================ UNDO LOG HISTORY LIST =============================*/
|
||||
|
||||
/********************************************************************//**
|
||||
|
|
|
@ -132,6 +132,49 @@ trx_rseg_header_create(
|
|||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Free's an instance of the rollback segment in memory. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_rseg_mem_free(
|
||||
/*==============*/
|
||||
trx_rseg_t* rseg) /* in, own: instance to free */
|
||||
{
|
||||
trx_undo_t* undo;
|
||||
|
||||
mutex_free(&rseg->mutex);
|
||||
|
||||
/* There can't be any active transactions. */
|
||||
ut_a(UT_LIST_GET_LEN(rseg->update_undo_list) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(rseg->insert_undo_list) == 0);
|
||||
|
||||
undo = UT_LIST_GET_FIRST(rseg->update_undo_cached);
|
||||
|
||||
while (undo != NULL) {
|
||||
trx_undo_t* prev_undo = undo;
|
||||
|
||||
undo = UT_LIST_GET_NEXT(undo_list, undo);
|
||||
UT_LIST_REMOVE(undo_list, rseg->update_undo_cached, prev_undo);
|
||||
|
||||
trx_undo_mem_free(prev_undo);
|
||||
}
|
||||
|
||||
undo = UT_LIST_GET_FIRST(rseg->insert_undo_cached);
|
||||
|
||||
while (undo != NULL) {
|
||||
trx_undo_t* prev_undo = undo;
|
||||
|
||||
undo = UT_LIST_GET_NEXT(undo_list, undo);
|
||||
UT_LIST_REMOVE(undo_list, rseg->insert_undo_cached, prev_undo);
|
||||
|
||||
trx_undo_mem_free(prev_undo);
|
||||
}
|
||||
|
||||
trx_sys_set_nth_rseg(trx_sys, rseg->id, NULL);
|
||||
|
||||
mem_free(rseg);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Creates and initializes a rollback segment object. The values for the
|
||||
fields are read from the header. The object is inserted to the rseg
|
||||
list of the trx system object and a pointer is inserted in the rseg
|
||||
|
|
|
@ -40,6 +40,7 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "trx0purge.h"
|
||||
#include "log0log.h"
|
||||
#include "os0file.h"
|
||||
#include "read0read.h"
|
||||
|
||||
/** The file format tag structure with id and name. */
|
||||
struct file_format_struct {
|
||||
|
@ -1533,3 +1534,80 @@ trx_sys_file_format_id_to_name(
|
|||
}
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************
|
||||
Shutdown/Close the transaction system. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_close(void)
|
||||
/*===============*/
|
||||
{
|
||||
trx_rseg_t* rseg;
|
||||
read_view_t* view;
|
||||
|
||||
ut_ad(trx_sys != NULL);
|
||||
|
||||
/* Check that all read views are closed except read view owned
|
||||
by a purge. */
|
||||
|
||||
if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: all read views were not closed"
|
||||
" before shutdown:\n"
|
||||
"InnoDB: %lu read views open \n",
|
||||
UT_LIST_GET_LEN(trx_sys->view_list) - 1);
|
||||
}
|
||||
|
||||
sess_close(trx_dummy_sess);
|
||||
trx_dummy_sess = NULL;
|
||||
|
||||
trx_purge_sys_close();
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
/* Free the double write data structures. */
|
||||
ut_a(trx_doublewrite != NULL);
|
||||
ut_free(trx_doublewrite->write_buf_unaligned);
|
||||
trx_doublewrite->write_buf_unaligned = NULL;
|
||||
|
||||
mem_free(trx_doublewrite->buf_block_arr);
|
||||
trx_doublewrite->buf_block_arr = NULL;
|
||||
|
||||
mutex_free(&trx_doublewrite->mutex);
|
||||
mem_free(trx_doublewrite);
|
||||
trx_doublewrite = NULL;
|
||||
|
||||
/* There can't be any active transactions. */
|
||||
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
|
||||
|
||||
while (rseg != NULL) {
|
||||
trx_rseg_t* prev_rseg = rseg;
|
||||
|
||||
rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg);
|
||||
UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg);
|
||||
|
||||
trx_rseg_mem_free(prev_rseg);
|
||||
}
|
||||
|
||||
view = UT_LIST_GET_FIRST(trx_sys->view_list);
|
||||
|
||||
while (view != NULL) {
|
||||
read_view_t* prev_view = view;
|
||||
|
||||
view = UT_LIST_GET_NEXT(view_list, prev_view);
|
||||
|
||||
/* Views are allocated from the trx_sys->global_read_view_heap.
|
||||
So, we simply remove the element here. */
|
||||
UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view);
|
||||
}
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
|
||||
|
||||
mem_free(trx_sys);
|
||||
|
||||
trx_sys = NULL;
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
|
|
@ -1522,7 +1522,7 @@ trx_undo_mem_init_for_reuse(
|
|||
|
||||
/********************************************************************//**
|
||||
Frees an undo log memory copy. */
|
||||
static
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_undo_mem_free(
|
||||
/*==============*/
|
||||
|
|
|
@ -31,14 +31,6 @@ Created 6/25/1996 Heikki Tuuri
|
|||
|
||||
#include "trx0trx.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Closes a session, freeing the memory occupied by it. */
|
||||
static
|
||||
void
|
||||
sess_close(
|
||||
/*=======*/
|
||||
sess_t* sess); /*!< in, own: session object */
|
||||
|
||||
/*********************************************************************//**
|
||||
Opens a session.
|
||||
@return own: session object */
|
||||
|
@ -64,35 +56,16 @@ sess_open(void)
|
|||
|
||||
/*********************************************************************//**
|
||||
Closes a session, freeing the memory occupied by it. */
|
||||
static
|
||||
UNIV_INTERN
|
||||
void
|
||||
sess_close(
|
||||
/*=======*/
|
||||
sess_t* sess) /*!< in, own: session object */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad(sess->trx == NULL);
|
||||
ut_ad(!mutex_own(&kernel_mutex));
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(sess->graphs) == 0);
|
||||
|
||||
trx_free_for_background(sess->trx);
|
||||
mem_free(sess);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Closes a session, freeing the memory occupied by it, if it is in a state
|
||||
where it should be closed.
|
||||
@return TRUE if closed */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
sess_try_close(
|
||||
/*===========*/
|
||||
sess_t* sess) /*!< in, own: session object */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (UT_LIST_GET_LEN(sess->graphs) == 0) {
|
||||
sess_close(sess);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
|
|
@ -433,6 +433,8 @@ ut_free_all_mem(void)
|
|||
" total allocated memory is %lu\n",
|
||||
(ulong) ut_total_allocated_memory);
|
||||
}
|
||||
|
||||
ut_mem_block_list_inited = FALSE;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
|
Loading…
Reference in a new issue