List:Commits« Previous MessageNext Message »
From:Satya B Date:November 30 2009 11:32am
Subject:bzr commit into mysql-5.1-bugteam branch (satya.bn:3221) Bug#45992
Bug#46656
View as plain text  
#At file:///home/satya/WORK/mysql/mysql-5.1-bugteam/ based on revid:satya.bn@stripped

 3221 Satya B	2009-11-30
      Applying InnoDB Plugin 1.0.6 snapshot,part 1. Fixes BUG#45992 and BUG#46656
      
      Detailed revision comments:
      
      r6130 | marko | 2009-11-02 11:42:56 +0200 (Mon, 02 Nov 2009) | 9 lines
      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

    modified:
      storage/innodb_plugin/ChangeLog
      storage/innodb_plugin/btr/btr0sea.c
      storage/innodb_plugin/buf/buf0buf.c
      storage/innodb_plugin/dict/dict0dict.c
      storage/innodb_plugin/fil/fil0fil.c
      storage/innodb_plugin/ibuf/ibuf0ibuf.c
      storage/innodb_plugin/include/btr0sea.h
      storage/innodb_plugin/include/dict0dict.h
      storage/innodb_plugin/include/fil0fil.h
      storage/innodb_plugin/include/ibuf0ibuf.h
      storage/innodb_plugin/include/lock0lock.h
      storage/innodb_plugin/include/log0log.h
      storage/innodb_plugin/include/log0recv.h
      storage/innodb_plugin/include/mem0mem.h
      storage/innodb_plugin/include/mem0pool.h
      storage/innodb_plugin/include/os0file.h
      storage/innodb_plugin/include/pars0pars.h
      storage/innodb_plugin/include/srv0srv.h
      storage/innodb_plugin/include/thr0loc.h
      storage/innodb_plugin/include/trx0i_s.h
      storage/innodb_plugin/include/trx0purge.h
      storage/innodb_plugin/include/trx0rseg.h
      storage/innodb_plugin/include/trx0sys.h
      storage/innodb_plugin/include/trx0undo.h
      storage/innodb_plugin/include/usr0sess.h
      storage/innodb_plugin/lock/lock0lock.c
      storage/innodb_plugin/log/log0log.c
      storage/innodb_plugin/log/log0recv.c
      storage/innodb_plugin/mem/mem0dbg.c
      storage/innodb_plugin/mem/mem0pool.c
      storage/innodb_plugin/os/os0file.c
      storage/innodb_plugin/os/os0sync.c
      storage/innodb_plugin/os/os0thread.c
      storage/innodb_plugin/pars/lexyy.c
      storage/innodb_plugin/pars/pars0lex.l
      storage/innodb_plugin/que/que0que.c
      storage/innodb_plugin/srv/srv0srv.c
      storage/innodb_plugin/srv/srv0start.c
      storage/innodb_plugin/sync/sync0arr.c
      storage/innodb_plugin/sync/sync0sync.c
      storage/innodb_plugin/thr/thr0loc.c
      storage/innodb_plugin/trx/trx0i_s.c
      storage/innodb_plugin/trx/trx0purge.c
      storage/innodb_plugin/trx/trx0rseg.c
      storage/innodb_plugin/trx/trx0sys.c
      storage/innodb_plugin/trx/trx0undo.c
      storage/innodb_plugin/usr/usr0sess.c
      storage/innodb_plugin/ut/ut0mem.c
=== modified file 'storage/innodb_plugin/ChangeLog'
--- a/storage/innodb_plugin/ChangeLog	2009-11-03 10:34:03 +0000
+++ b/storage/innodb_plugin/ChangeLog	2009-11-30 11:32:05 +0000
@@ -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,

=== modified file 'storage/innodb_plugin/btr/btr0sea.c'
--- a/storage/innodb_plugin/btr/btr0sea.c	2009-10-08 11:28:37 +0000
+++ b/storage/innodb_plugin/btr/btr0sea.c	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/buf/buf0buf.c'
--- a/storage/innodb_plugin/buf/buf0buf.c	2009-11-03 10:26:07 +0000
+++ b/storage/innodb_plugin/buf/buf0buf.c	2009-11-30 11:32:05 +0000
@@ -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;
 }
 
 /********************************************************************//**

=== modified file 'storage/innodb_plugin/dict/dict0dict.c'
--- a/storage/innodb_plugin/dict/dict0dict.c	2009-10-09 12:52:18 +0000
+++ b/storage/innodb_plugin/dict/dict0dict.c	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/fil/fil0fil.c'
--- a/storage/innodb_plugin/fil/fil0fil.c	2009-11-03 10:24:21 +0000
+++ b/storage/innodb_plugin/fil/fil0fil.c	2009-11-30 11:32:05 +0000
@@ -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
 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;
+}

=== modified file 'storage/innodb_plugin/ibuf/ibuf0ibuf.c'
--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c	2009-11-30 11:32:05 +0000
@@ -390,6 +390,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. */
 static

=== modified file 'storage/innodb_plugin/include/btr0sea.h'
--- a/storage/innodb_plugin/include/btr0sea.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/btr0sea.h	2009-11-30 11:32:05 +0000
@@ -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. */

=== modified file 'storage/innodb_plugin/include/dict0dict.h'
--- a/storage/innodb_plugin/include/dict0dict.h	2009-10-08 11:28:37 +0000
+++ b/storage/innodb_plugin/include/dict0dict.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/fil0fil.h'
--- a/storage/innodb_plugin/include/fil0fil.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/fil0fil.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/ibuf0ibuf.h'
--- a/storage/innodb_plugin/include/ibuf0ibuf.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/ibuf0ibuf.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/lock0lock.h'
--- a/storage/innodb_plugin/include/lock0lock.h	2009-10-08 12:18:19 +0000
+++ b/storage/innodb_plugin/include/lock0lock.h	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/include/log0log.h'
--- a/storage/innodb_plugin/include/log0log.h	2009-10-08 12:18:19 +0000
+++ b/storage/innodb_plugin/include/log0log.h	2009-11-30 11:32:05 +0000
@@ -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 */
 	/* @} */

=== modified file 'storage/innodb_plugin/include/log0recv.h'
--- a/storage/innodb_plugin/include/log0recv.h	2009-10-09 14:13:15 +0000
+++ b/storage/innodb_plugin/include/log0recv.h	2009-11-30 11:32:05 +0000
@@ -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. */

=== modified file 'storage/innodb_plugin/include/mem0mem.h'
--- a/storage/innodb_plugin/include/mem0mem.h	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/include/mem0mem.h	2009-11-30 11:32:05 +0000
@@ -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. */

=== modified file 'storage/innodb_plugin/include/mem0pool.h'
--- a/storage/innodb_plugin/include/mem0pool.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/mem0pool.h	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/include/os0file.h'
--- a/storage/innodb_plugin/include/os0file.h	2009-11-03 09:59:06 +0000
+++ b/storage/innodb_plugin/include/os0file.h	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/include/pars0pars.h'
--- a/storage/innodb_plugin/include/pars0pars.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/pars0pars.h	2009-11-30 11:32:05 +0000
@@ -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 {

=== modified file 'storage/innodb_plugin/include/srv0srv.h'
--- a/storage/innodb_plugin/include/srv0srv.h	2009-10-08 11:28:37 +0000
+++ b/storage/innodb_plugin/include/srv0srv.h	2009-11-30 11:32:05 +0000
@@ -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);

=== modified file 'storage/innodb_plugin/include/thr0loc.h'
--- a/storage/innodb_plugin/include/thr0loc.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/thr0loc.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/trx0i_s.h'
--- a/storage/innodb_plugin/include/trx0i_s.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/trx0i_s.h	2009-11-30 11:32:05 +0000
@@ -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. */

=== modified file 'storage/innodb_plugin/include/trx0purge.h'
--- a/storage/innodb_plugin/include/trx0purge.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/trx0purge.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/trx0rseg.h'
--- a/storage/innodb_plugin/include/trx0rseg.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/trx0rseg.h	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/include/trx0sys.h'
--- a/storage/innodb_plugin/include/trx0sys.h	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/include/trx0sys.h	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/include/trx0undo.h'
--- a/storage/innodb_plugin/include/trx0undo.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/trx0undo.h	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/include/usr0sess.h'
--- a/storage/innodb_plugin/include/usr0sess.h	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/include/usr0sess.h	2009-11-30 11:32:05 +0000
@@ -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{

=== modified file 'storage/innodb_plugin/lock/lock0lock.c'
--- a/storage/innodb_plugin/lock/lock0lock.c	2009-10-09 14:13:15 +0000
+++ b/storage/innodb_plugin/lock/lock0lock.c	2009-11-30 11:32:05 +0000
@@ -578,6 +578,23 @@ lock_sys_create(
 }
 
 /*********************************************************************//**
+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 */
 UNIV_INTERN

=== modified file 'storage/innodb_plugin/log/log0log.c'
--- a/storage/innodb_plugin/log/log0log.c	2009-10-09 14:13:15 +0000
+++ b/storage/innodb_plugin/log/log0log.c	2009-11-30 11:32:05 +0000
@@ -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 */

=== modified file 'storage/innodb_plugin/log/log0recv.c'
--- a/storage/innodb_plugin/log/log0recv.c	2009-10-09 14:13:15 +0000
+++ b/storage/innodb_plugin/log/log0recv.c	2009-11-30 11:32:05 +0000
@@ -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 = FA
 /** 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 wer
 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 r
 
 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_operation
 #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(voi
 	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.

=== modified file 'storage/innodb_plugin/mem/mem0dbg.c'
--- a/storage/innodb_plugin/mem/mem0dbg.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/mem/mem0dbg.c	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/mem/mem0pool.c'
--- a/storage/innodb_plugin/mem/mem0pool.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/mem/mem0pool.c	2009-11-30 11:32:05 +0000
@@ -261,6 +261,18 @@ mem_pool_create(
 }
 
 /********************************************************************//**
+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 */
 static

=== modified file 'storage/innodb_plugin/os/os0file.c'
--- a/storage/innodb_plugin/os/os0file.c	2009-11-03 09:59:31 +0000
+++ b/storage/innodb_plugin/os/os0file.c	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/os/os0sync.c'
--- a/storage/innodb_plugin/os/os0sync.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/os/os0sync.c	2009-11-30 11:32:05 +0000
@@ -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)) {

=== modified file 'storage/innodb_plugin/os/os0thread.c'
--- a/storage/innodb_plugin/os/os0thread.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/os/os0thread.c	2009-11-30 11:32:05 +0000
@@ -233,6 +233,7 @@ os_thread_exit(
 #ifdef __WIN__
 	ExitThread((DWORD)exit_value);
 #else
+	pthread_detach(pthread_self());
 	pthread_exit(exit_value);
 #endif
 }

=== modified file 'storage/innodb_plugin/pars/lexyy.c'
--- a/storage/innodb_plugin/pars/lexyy.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/pars/lexyy.c	2009-11-30 11:32:05 +0000
@@ -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;
+}

=== modified file 'storage/innodb_plugin/pars/pars0lex.l'
--- a/storage/innodb_plugin/pars/pars0lex.l	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/pars/pars0lex.l	2009-11-30 11:32:05 +0000
@@ -661,3 +661,16 @@ In the state 'id', only two actions are 
 }
 
 %%
+
+/**********************************************************************
+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;
+}

=== modified file 'storage/innodb_plugin/que/que0que.c'
--- a/storage/innodb_plugin/que/que0que.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/que/que0que.c	2009-11-30 11:32:05 +0000
@@ -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;

=== modified file 'storage/innodb_plugin/srv/srv0srv.c'
--- a/storage/innodb_plugin/srv/srv0srv.c	2009-10-09 12:19:13 +0000
+++ b/storage/innodb_plugin/srv/srv0srv.c	2009-11-30 11:32:05 +0000
@@ -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);

=== modified file 'storage/innodb_plugin/srv/srv0start.c'
--- a/storage/innodb_plugin/srv/srv0start.c	2009-11-03 10:23:22 +0000
+++ b/storage/innodb_plugin/srv/srv0start.c	2009-11-30 11:32:05 +0000
@@ -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++) {
+		ulint	dirnamelen;
+
 		srv_normalize_path_for_win(srv_data_file_names[i]);
+		dirnamelen = strlen(srv_data_home);
 
-		ut_a(strlen(srv_data_home) + strlen(srv_data_file_names[i])
+		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);
 }

=== modified file 'storage/innodb_plugin/sync/sync0arr.c'
--- a/storage/innodb_plugin/sync/sync0arr.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/sync/sync0arr.c	2009-11-30 11:32:05 +0000
@@ -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);
 }
 

=== modified file 'storage/innodb_plugin/sync/sync0sync.c'
--- a/storage/innodb_plugin/sync/sync0sync.c	2009-10-12 12:00:56 +0000
+++ b/storage/innodb_plugin/sync/sync0sync.c	2009-11-30 11:32:05 +0000
@@ -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;	
 }
 
 /*******************************************************************//**

=== modified file 'storage/innodb_plugin/thr/thr0loc.c'
--- a/storage/innodb_plugin/thr/thr0loc.c	2009-10-08 10:00:49 +0000
+++ b/storage/innodb_plugin/thr/thr0loc.c	2009-11-30 11:32:05 +0000
@@ -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;
+}

=== modified file 'storage/innodb_plugin/trx/trx0i_s.c'
--- a/storage/innodb_plugin/trx/trx0i_s.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/trx/trx0i_s.c	2009-11-30 11:32:05 +0000
@@ -238,6 +238,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.
 If the memory limit is hit then NULL is returned and nothing is
@@ -1252,6 +1273,22 @@ trx_i_s_cache_init(
 }
 
 /*******************************************************************//**
+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
 void

=== modified file 'storage/innodb_plugin/trx/trx0purge.c'
--- a/storage/innodb_plugin/trx/trx0purge.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/trx/trx0purge.c	2009-11-30 11:32:05 +0000
@@ -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 =============================*/
 
 /********************************************************************//**

=== modified file 'storage/innodb_plugin/trx/trx0rseg.c'
--- a/storage/innodb_plugin/trx/trx0rseg.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/trx/trx0rseg.c	2009-11-30 11:32:05 +0000
@@ -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

=== modified file 'storage/innodb_plugin/trx/trx0sys.c'
--- a/storage/innodb_plugin/trx/trx0sys.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/trx/trx0sys.c	2009-11-30 11:32:05 +0000
@@ -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);
+}

=== modified file 'storage/innodb_plugin/trx/trx0undo.c'
--- a/storage/innodb_plugin/trx/trx0undo.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/trx/trx0undo.c	2009-11-30 11:32:05 +0000
@@ -1522,7 +1522,7 @@ trx_undo_mem_init_for_reuse(
 
 /********************************************************************//**
 Frees an undo log memory copy. */
-static
+UNIV_INTERN
 void
 trx_undo_mem_free(
 /*==============*/

=== modified file 'storage/innodb_plugin/usr/usr0sess.c'
--- a/storage/innodb_plugin/usr/usr0sess.c	2009-05-27 09:45:59 +0000
+++ b/storage/innodb_plugin/usr/usr0sess.c	2009-11-30 11:32:05 +0000
@@ -32,14 +32,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 */
 UNIV_INTERN
@@ -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);
-
-	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));
+	ut_ad(!mutex_own(&kernel_mutex));
 
-	if (UT_LIST_GET_LEN(sess->graphs) == 0) {
-		sess_close(sess);
+	ut_a(UT_LIST_GET_LEN(sess->graphs) == 0);
 
-		return(TRUE);
-	}
-
-	return(FALSE);
+	trx_free_for_background(sess->trx);
+	mem_free(sess);
 }

=== modified file 'storage/innodb_plugin/ut/ut0mem.c'
--- a/storage/innodb_plugin/ut/ut0mem.c	2009-07-30 12:42:56 +0000
+++ b/storage/innodb_plugin/ut/ut0mem.c	2009-11-30 11:32:05 +0000
@@ -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 */
 


Attachment: [text/bzr-bundle] bzr/satya.bn@sun.com-20091130113205-qcewe64fh8191c52.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (satya.bn:3221) Bug#45992Bug#46656Satya B30 Nov