diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
--- a/storage/innobase/btr/btr0sea.c 2010-11-03 07:01:13.000000000 +0900
+++ b/storage/innobase/btr/btr0sea.c 2010-12-03 15:45:47.503988924 +0900
-@@ -1185,6 +1185,132 @@
+@@ -1185,6 +1185,179 @@
mem_free(folds);
}
+/*=====================================*/
+ dict_index_t* index) /* in: record descriptor */
+{
-+ buf_page_t* bpage;
++
+ hash_table_t* table;
+ buf_block_t* block;
+ ulint n_fields;
+ ulint i, j;
+ mem_heap_t* heap = NULL;
+ ulint* offsets;
++ ibool released_search_latch;
+
-+ rw_lock_x_lock(&btr_search_latch);
-+ buf_pool_mutex_enter_all();
++ rw_lock_s_lock(&btr_search_latch);
+
+ table = btr_search_sys->hash_index;
+
+
+ buf_pool = buf_pool_from_array(j);
+
-+ bpage = UT_LIST_GET_LAST(buf_pool->LRU);
++ do {
++ buf_chunk_t* chunks = buf_pool->chunks;
++ buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
++
++ released_search_latch = FALSE;
++
++ while (--chunk >= chunks) {
++ block = chunk->blocks;
++ i = chunk->size;
++
++retry:
++ for (; i--; block++) {
++ if (buf_block_get_state(block)
++ != BUF_BLOCK_FILE_PAGE
++ || block->index != index
++ || !block->is_hashed) {
++ continue;
++ }
++
++ page = block->frame;
++
++ /* from btr_search_drop_page_hash_index() */
++ n_fields = block->curr_n_fields;
++ n_bytes = block->curr_n_bytes;
++
+
-+ while (bpage != NULL) {
-+ block = (buf_block_t*) bpage;
-+ if (block->index == index && block->is_hashed) {
-+ page = block->frame;
++ /* keeping latch order */
++ rw_lock_s_unlock(&btr_search_latch);
++ released_search_latch = TRUE;
++ rw_lock_x_lock(&block->lock);
+
-+ /* from btr_search_drop_page_hash_index() */
-+ n_fields = block->curr_n_fields;
-+ n_bytes = block->curr_n_bytes;
+
-+ ut_a(n_fields + n_bytes > 0);
++ ut_a(n_fields + n_bytes > 0);
+
-+ n_recs = page_get_n_recs(page);
++ n_recs = page_get_n_recs(page);
+
-+ /* Calculate and cache fold values into an array for fast deletion
-+ from the hash index */
++ /* Calculate and cache fold values into an array for fast deletion
++ from the hash index */
+
-+ folds = mem_alloc(n_recs * sizeof(ulint));
++ folds = mem_alloc(n_recs * sizeof(ulint));
+
-+ n_cached = 0;
++ n_cached = 0;
+
-+ rec = page_get_infimum_rec(page);
-+ rec = page_rec_get_next_low(rec, page_is_comp(page));
++ rec = page_get_infimum_rec(page);
++ rec = page_rec_get_next_low(rec, page_is_comp(page));
+
-+ index_id = btr_page_get_index_id(page);
++ index_id = btr_page_get_index_id(page);
+
-+ ut_a(index_id == index->id);
++ ut_a(index_id == index->id);
+
-+ prev_fold = 0;
++ prev_fold = 0;
+
-+ offsets = NULL;
++ offsets = NULL;
+
-+ while (!page_rec_is_supremum(rec)) {
-+ offsets = rec_get_offsets(rec, index, offsets,
-+ n_fields + (n_bytes > 0), &heap);
-+ ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
-+ fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
++ while (!page_rec_is_supremum(rec)) {
++ offsets = rec_get_offsets(rec, index, offsets,
++ n_fields + (n_bytes > 0), &heap);
++ ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
++ fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
+
-+ if (fold == prev_fold && prev_fold != 0) {
++ if (fold == prev_fold && prev_fold != 0) {
+
-+ goto next_rec;
-+ }
++ goto next_rec;
++ }
+
-+ /* Remove all hash nodes pointing to this page from the
-+ hash chain */
++ /* Remove all hash nodes pointing to this page from the
++ hash chain */
+
-+ folds[n_cached] = fold;
-+ n_cached++;
++ folds[n_cached] = fold;
++ n_cached++;
+next_rec:
-+ rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
-+ prev_fold = fold;
-+ }
++ rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
++ prev_fold = fold;
++ }
+
-+ for (i = 0; i < n_cached; i++) {
++ if (UNIV_LIKELY_NULL(heap)) {
++ mem_heap_empty(heap);
++ }
+
-+ ha_remove_all_nodes_to_page(table, folds[i], page);
-+ }
++ rw_lock_x_lock(&btr_search_latch);
+
-+ ut_a(index->search_info->ref_count > 0);
-+ index->search_info->ref_count--;
++ if (UNIV_UNLIKELY(!block->is_hashed)) {
++ goto cleanup;
++ }
+
-+ block->is_hashed = FALSE;
-+ block->index = NULL;
-+
++ ut_a(block->index == index);
++
++ if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
++ || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
++ rw_lock_x_unlock(&btr_search_latch);
++ rw_lock_x_unlock(&block->lock);
++
++ mem_free(folds);
++
++ rw_lock_s_lock(&btr_search_latch);
++ goto retry;
++ }
++
++ for (i = 0; i < n_cached; i++) {
++
++ ha_remove_all_nodes_to_page(table, folds[i], page);
++ }
++
++ ut_a(index->search_info->ref_count > 0);
++ index->search_info->ref_count--;
++
++ block->is_hashed = FALSE;
++ block->index = NULL;
++
++cleanup:
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-+ if (UNIV_UNLIKELY(block->n_pointers)) {
-+ /* Corruption */
-+ ut_print_timestamp(stderr);
-+ fprintf(stderr,
-+" InnoDB: Corruption of adaptive hash index. After dropping\n"
-+"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n",
-+ index->name, (ulong) block->n_pointers);
-+ }
++ if (UNIV_UNLIKELY(block->n_pointers)) {
++ /* Corruption */
++ ut_print_timestamp(stderr);
++ fprintf(stderr,
++"InnoDB: The adaptive hash index is corrupted. After dropping\n"
++"InnoDB: the hash index to a page of %s, %lu hash nodes still remain.\n",
++ index->name, (ulong) block->n_pointers);
++ }
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
++ rw_lock_x_unlock(&btr_search_latch);
++ rw_lock_x_unlock(&block->lock);
+
-+ mem_free(folds);
-+ }
++ mem_free(folds);
+
-+ bpage = UT_LIST_GET_PREV(LRU, bpage);
-+ }
++ rw_lock_s_lock(&btr_search_latch);
++ }
++ }
++ } while (released_search_latch);
+ }
+
-+ buf_pool_mutex_exit_all();
-+ rw_lock_x_unlock(&btr_search_latch);
++ rw_lock_s_unlock(&btr_search_latch);
+
+ if (UNIV_LIKELY_NULL(heap)) {
+ mem_heap_free(heap);
/********************************************************************//**
Drops a page hash index when a page is freed from a fseg to the file system.
Drops possible hash index if the page happens to be in the buffer pool. */
+diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
+--- a/storage/innobase/buf/buf0buf.c 2011-02-01 18:00:03.000000000 +0900
++++ b/storage/innobase/buf/buf0buf.c 2011-02-01 18:01:59.000000000 +0900
+@@ -294,14 +294,14 @@
+ # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
+ #endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
+
+-/** A chunk of buffers. The buffer pool is allocated in chunks. */
+-struct buf_chunk_struct{
+- ulint mem_size; /*!< allocated size of the chunk */
+- ulint size; /*!< size of frames[] and blocks[] */
+- void* mem; /*!< pointer to the memory area which
+- was allocated for the frames */
+- buf_block_t* blocks; /*!< array of buffer control blocks */
+-};
++/** A chunk of buffers. The buffer pool is allocated in chunks. (moved to buf0buf.h)*/
++//struct buf_chunk_struct{
++// ulint mem_size; /*!< allocated size of the chunk */
++// ulint size; /*!< size of frames[] and blocks[] */
++// void* mem; /*!< pointer to the memory area which
++// was allocated for the frames */
++// buf_block_t* blocks; /*!< array of buffer control blocks */
++//};
+ #endif /* !UNIV_HOTBACKUP */
+
+ /********************************************************************//**
diff -ruN a/storage/innobase/dict/dict0boot.c b/storage/innobase/dict/dict0boot.c
--- a/storage/innobase/dict/dict0boot.c 2010-11-03 07:01:13.000000000 +0900
+++ b/storage/innobase/dict/dict0boot.c 2010-12-03 15:45:47.503988924 +0900
diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
--- a/storage/innobase/dict/dict0dict.c 2010-11-03 07:01:13.000000000 +0900
+++ b/storage/innobase/dict/dict0dict.c 2010-12-03 15:45:47.525953769 +0900
-@@ -625,6 +625,8 @@
+@@ -627,6 +627,8 @@
table = dict_table_get_on_id_low(table_id);
mutex_exit(&(dict_sys->mutex));
return(table);
-@@ -743,6 +745,8 @@
+@@ -745,6 +747,8 @@
table->n_mysql_handles_opened++;
}
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
-@@ -1256,6 +1260,64 @@
+@@ -1260,6 +1264,64 @@
dict_mem_table_free(table);
}
/****************************************************************//**
If the given column name is reserved for InnoDB system columns, return
TRUE.
-@@ -1719,6 +1781,11 @@
+@@ -1723,6 +1785,11 @@
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(mutex_own(&(dict_sys->mutex)));
diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
--- a/storage/innobase/handler/ha_innodb.cc 2010-12-03 15:43:57.294986852 +0900
+++ b/storage/innobase/handler/ha_innodb.cc 2010-12-03 15:45:47.534959966 +0900
-@@ -655,6 +655,8 @@
+@@ -656,6 +656,8 @@
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
{"dblwr_writes",
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
{"have_atomic_builtins",
(char*) &export_vars.innodb_have_atomic_builtins, SHOW_BOOL},
{"log_waits",
-@@ -11543,6 +11545,11 @@
+@@ -11536,6 +11538,11 @@
"Number of extra user rollback segments which are used in a round-robin fashion.",
NULL, NULL, 127, 0, 127, 0);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
-@@ -11611,6 +11618,7 @@
+@@ -11603,6 +11610,7 @@
+ MYSQL_SYSVAR(read_ahead),
MYSQL_SYSVAR(adaptive_flushing_method),
- MYSQL_SYSVAR(enable_unsafe_group_commit),
MYSQL_SYSVAR(extra_rsegments),
+ MYSQL_SYSVAR(dict_size_limit),
MYSQL_SYSVAR(use_sys_malloc),
/********************************************************************//**
Drops a page hash index when a page is freed from a fseg to the file system.
Drops possible hash index if the page happens to be in the buffer pool. */
+diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
+--- a/storage/innobase/include/buf0buf.h 2011-02-01 18:00:03.000000000 +0900
++++ b/storage/innobase/include/buf0buf.h 2011-02-01 18:03:29.000000000 +0900
+@@ -1553,6 +1553,15 @@
+ #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
+ /* @} */
+
++/** A chunk of buffers. The buffer pool is allocated in chunks. */
++struct buf_chunk_struct{
++ ulint mem_size; /*!< allocated size of the chunk */
++ ulint size; /*!< size of frames[] and blocks[] */
++ void* mem; /*!< pointer to the memory area which
++ was allocated for the frames */
++ buf_block_t* blocks; /*!< array of buffer control blocks */
++};
++
+ /** @brief The buffer pool statistics structure. */
+ struct buf_pool_stat_struct{
+ ulint n_page_gets; /*!< number of page gets performed;
diff -ruN a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
--- a/storage/innobase/include/dict0dict.h 2010-11-03 07:01:13.000000000 +0900
+++ b/storage/innobase/include/dict0dict.h 2010-12-03 15:45:47.558024515 +0900
/*-------------------------------------------*/
extern ulint srv_n_rows_inserted;
-@@ -700,6 +700,7 @@
+@@ -708,6 +708,7 @@
ulint innodb_data_writes; /*!< I/O write requests */
ulint innodb_data_written; /*!< Data bytes written */
ulint innodb_data_reads; /*!< I/O read requests */
diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
--- a/storage/innobase/srv/srv0srv.c 2010-12-03 15:43:57.301024390 +0900
+++ b/storage/innobase/srv/srv0srv.c 2010-12-03 15:45:47.565023830 +0900
-@@ -414,6 +414,7 @@
+@@ -416,6 +416,7 @@
UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
UNIV_INTERN ulint srv_extra_rsegments = 127; /* extra rseg for users */
/*-------------------------------------------*/
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
-@@ -2192,6 +2193,7 @@
+@@ -2226,6 +2227,7 @@
export_vars.innodb_data_reads = os_n_file_reads;
export_vars.innodb_data_writes = os_n_file_writes;
export_vars.innodb_data_written = srv_data_written;