diff options
Diffstat (limited to 'storage/innobase/ha')
-rw-r--r-- | storage/innobase/ha/ha0ha.cc (renamed from storage/innobase/ha/ha0ha.c) | 163 | ||||
-rw-r--r-- | storage/innobase/ha/ha0storage.cc (renamed from storage/innobase/ha/ha0storage.c) | 12 | ||||
-rw-r--r-- | storage/innobase/ha/hash0hash.c | 184 | ||||
-rw-r--r-- | storage/innobase/ha/hash0hash.cc | 403 |
4 files changed, 527 insertions, 235 deletions
diff --git a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.cc index 594a10dc431..dd99e3afae5 100644 --- a/storage/innobase/ha/ha0ha.c +++ b/storage/innobase/ha/ha0ha.cc @@ -11,13 +11,13 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ /********************************************************************//** -@file ha/ha0ha.c +@file ha/ha0ha.cc The hash table with external chains Created 8/22/1994 Heikki Tuuri @@ -31,7 +31,9 @@ Created 8/22/1994 Heikki Tuuri #ifdef UNIV_DEBUG # include "buf0buf.h" #endif /* UNIV_DEBUG */ -#include "btr0sea.h" +#ifndef UNIV_HOTBACKUP +# include "btr0sea.h" +#endif /* !UNIV_HOTBACKUP */ #include "page0page.h" /*************************************************************//** @@ -44,43 +46,56 @@ ha_create_func( /*===========*/ ulint n, /*!< in: number of array cells */ #ifdef UNIV_SYNC_DEBUG - ulint mutex_level, /*!< in: level of the mutexes in the latching - order: this is used in the debug version */ + ulint sync_level, /*!< in: level of the mutexes or rw_locks + in the latching order: this is used in the + debug version */ #endif /* UNIV_SYNC_DEBUG */ - ulint n_mutexes) /*!< in: number of mutexes to protect the - hash table: must be a power of 2, or 0 */ + ulint n_sync_obj, /*!< in: number of mutexes or rw_locks + to protect the hash table: must be a + power of 2, or 0 */ + ulint type) /*!< in: type of datastructure for which + the memory heap is going to be used e.g.: + MEM_HEAP_FOR_BTR_SEARCH or + MEM_HEAP_FOR_PAGE_HASH */ { hash_table_t* table; #ifndef UNIV_HOTBACKUP ulint i; #endif /* !UNIV_HOTBACKUP */ - ut_ad(ut_is_2pow(n_mutexes)); + ut_a(type == MEM_HEAP_FOR_BTR_SEARCH + || type == MEM_HEAP_FOR_PAGE_HASH); + + ut_ad(ut_is_2pow(n_sync_obj)); table = hash_create(n); -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -# ifndef UNIV_HOTBACKUP - table->adaptive = TRUE; -# endif /* !UNIV_HOTBACKUP */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ /* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail, but in practise it never should in this case, hence the asserts. */ - if (n_mutexes == 0) { - table->heap = mem_heap_create_in_btr_search( - ut_min(4096, MEM_MAX_ALLOC_IN_BUF)); + if (n_sync_obj == 0) { + table->heap = mem_heap_create_typed( + ut_min(4096, MEM_MAX_ALLOC_IN_BUF), type); ut_a(table->heap); return(table); } #ifndef UNIV_HOTBACKUP - hash_create_mutexes(table, n_mutexes, mutex_level); + if (type == MEM_HEAP_FOR_PAGE_HASH) { + /* We create a hash table protected by rw_locks for + buf_pool->page_hash. */ + hash_create_sync_obj(table, HASH_TABLE_SYNC_RW_LOCK, + n_sync_obj, sync_level); + } else { + hash_create_sync_obj(table, HASH_TABLE_SYNC_MUTEX, + n_sync_obj, sync_level); + } - table->heaps = mem_alloc(n_mutexes * sizeof(void*)); + table->heaps = static_cast<mem_heap_t**>( + mem_alloc(n_sync_obj * sizeof(void*))); - for (i = 0; i < n_mutexes; i++) { - table->heaps[i] = mem_heap_create_in_btr_search(4096); + for (i = 0; i < n_sync_obj; i++) { + table->heaps[i] = mem_heap_create_typed(4096, type); ut_a(table->heaps[i]); } #endif /* !UNIV_HOTBACKUP */ @@ -89,6 +104,65 @@ ha_create_func( } /*************************************************************//** +Empties a hash table and frees the memory heaps. */ +UNIV_INTERN +void +ha_clear( +/*=====*/ + hash_table_t* table) /*!< in, own: hash table */ +{ + ulint i; + ulint n; + + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); +#ifdef UNIV_SYNC_DEBUG + ut_ad(!table->adaptive + || rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE)); +#endif /* UNIV_SYNC_DEBUG */ + +#ifndef UNIV_HOTBACKUP + /* Free the memory heaps. */ + n = table->n_sync_obj; + + for (i = 0; i < n; i++) { + mem_heap_free(table->heaps[i]); + } + + if (table->heaps) { + mem_free(table->heaps); + } + + switch (table->type) { + case HASH_TABLE_SYNC_MUTEX: + mem_free(table->sync_obj.mutexes); + table->sync_obj.mutexes = NULL; + break; + + case HASH_TABLE_SYNC_RW_LOCK: + mem_free(table->sync_obj.rw_locks); + table->sync_obj.rw_locks = NULL; + break; + + case HASH_TABLE_SYNC_NONE: + /* do nothing */ + break; + } + + table->n_sync_obj = 0; + table->type = HASH_TABLE_SYNC_NONE; + +#endif /* !UNIV_HOTBACKUP */ + + /* Clear the hash table. */ + n = hash_get_n_cells(table); + + for (i = 0; i < n; i++) { + hash_get_nth_cell(table, i)->node = NULL; + } +} + +/*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node is inserted. If btr_search_enabled is set to FALSE, we will only allow @@ -106,7 +180,7 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* block, /*!< in: buffer block containing the data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - rec_t* data) /*!< in: data, must not be NULL */ + const rec_t* data) /*!< in: data, must not be NULL */ { hash_cell_t* cell; ha_node_t* node; @@ -119,17 +193,14 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ut_a(block->frame == page_align(data)); #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -#ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); -#endif /* UNIV_SYNC_DEBUG */ - ASSERT_HASH_MUTEX_OWN(table, fold); + hash_assert_can_modify(table, fold); ut_ad(btr_search_enabled); hash = hash_calc_hash(fold, table); cell = hash_get_nth_cell(table, hash); - prev_node = cell->node; + prev_node = static_cast<ha_node_t*>(cell->node); while (prev_node != NULL) { if (prev_node->fold == fold) { @@ -147,7 +218,7 @@ ha_insert_for_fold_func( prev_node->block = block; #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - prev_node->data = data; + prev_node->data = (rec_t*) data; return(TRUE); } @@ -157,7 +228,8 @@ ha_insert_for_fold_func( /* We have to allocate a new chain node */ - node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)); + node = static_cast<ha_node_t*>( + mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t))); if (node == NULL) { /* It was a btr search type memory heap and at the moment @@ -168,7 +240,7 @@ ha_insert_for_fold_func( return(FALSE); } - ha_node_set_data(node, block, data); + ha_node_set_data(node, block, (rec_t*) data); #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG # ifndef UNIV_HOTBACKUP @@ -182,7 +254,7 @@ ha_insert_for_fold_func( node->next = NULL; - prev_node = cell->node; + prev_node = static_cast<ha_node_t*>(cell->node); if (prev_node == NULL) { @@ -231,9 +303,10 @@ ha_delete_hash_node( /*********************************************************//** Looks for an element when we know the pointer to the data, and updates -the pointer to data, if found. */ +the pointer to data, if found. +@return TRUE if found */ UNIV_INTERN -void +ibool ha_search_and_update_if_found_func( /*===============================*/ hash_table_t* table, /*!< in/out: hash table */ @@ -248,7 +321,7 @@ ha_search_and_update_if_found_func( ut_ad(table); ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ASSERT_HASH_MUTEX_OWN(table, fold); + hash_assert_can_modify(table, fold); #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ut_a(new_block->frame == page_align(new_data)); #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ @@ -257,7 +330,7 @@ ha_search_and_update_if_found_func( #endif /* UNIV_SYNC_DEBUG */ if (!btr_search_enabled) { - return; + return(FALSE); } node = ha_search_with_data(table, fold, data); @@ -275,7 +348,11 @@ ha_search_and_update_if_found_func( node->block = new_block; #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ node->data = new_data; + + return(TRUE); } + + return(FALSE); } #ifndef UNIV_HOTBACKUP @@ -294,10 +371,7 @@ ha_remove_all_nodes_to_page( ut_ad(table); ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ASSERT_HASH_MUTEX_OWN(table, fold); -#ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); -#endif /* UNIV_SYNC_DEBUG */ + hash_assert_can_modify(table, fold); ut_ad(btr_search_enabled); node = ha_chain_get_first(table, fold); @@ -343,8 +417,6 @@ ha_validate( ulint start_index, /*!< in: start index */ ulint end_index) /*!< in: end index */ { - hash_cell_t* cell; - ha_node_t* node; ibool ok = TRUE; ulint i; @@ -355,12 +427,15 @@ ha_validate( ut_a(end_index < hash_get_n_cells(table)); for (i = start_index; i <= end_index; i++) { + ha_node_t* node; + hash_cell_t* cell; cell = hash_get_nth_cell(table, i); - node = cell->node; + for (node = static_cast<ha_node_t*>(cell->node); + node != 0; + node = node->next) { - while (node) { if (hash_calc_hash(node->fold, table) != i) { ut_print_timestamp(stderr); fprintf(stderr, @@ -371,8 +446,6 @@ ha_validate( ok = FALSE; } - - node = node->next; } } diff --git a/storage/innobase/ha/ha0storage.c b/storage/innobase/ha/ha0storage.cc index 698e34f1166..6820591f316 100644 --- a/storage/innobase/ha/ha0storage.c +++ b/storage/innobase/ha/ha0storage.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,13 +11,13 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ /**************************************************//** -@file ha/ha0storage.c +@file ha/ha0storage.cc Hash storage. Provides a data structure that stores chunks of data in its own storage, avoiding duplicates. @@ -51,7 +51,7 @@ ha_storage_get( /* avoid repetitive calls to ut_fold_binary() in the HASH_SEARCH macro */ - fold = ut_fold_binary(data, data_len); + fold = ut_fold_binary(static_cast<const byte*>(data), data_len); #define IS_FOUND \ node->data_len == data_len && memcmp(node->data, data, data_len) == 0 @@ -128,7 +128,7 @@ ha_storage_put_memlim( /* avoid repetitive calls to ut_fold_binary() in the HASH_INSERT macro */ - fold = ut_fold_binary(data, data_len); + fold = ut_fold_binary(static_cast<const byte*>(data), data_len); HASH_INSERT( ha_storage_node_t, /* type used in the hash chain */ diff --git a/storage/innobase/ha/hash0hash.c b/storage/innobase/ha/hash0hash.c deleted file mode 100644 index 9589da00454..00000000000 --- a/storage/innobase/ha/hash0hash.c +++ /dev/null @@ -1,184 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA - -*****************************************************************************/ - -/**************************************************//** -@file ha/hash0hash.c -The simple hash table utility - -Created 5/20/1997 Heikki Tuuri -*******************************************************/ - -#include "hash0hash.h" -#ifdef UNIV_NONINL -#include "hash0hash.ic" -#endif - -#include "mem0mem.h" - -#ifndef UNIV_HOTBACKUP - -# ifdef UNIV_PFS_MUTEX -UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key; -# endif /* UNIV_PFS_MUTEX */ - -/************************************************************//** -Reserves the mutex for a fold value in a hash table. */ -UNIV_INTERN -void -hash_mutex_enter( -/*=============*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - mutex_enter(hash_get_mutex(table, fold)); -} - -/************************************************************//** -Releases the mutex for a fold value in a hash table. */ -UNIV_INTERN -void -hash_mutex_exit( -/*============*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: fold */ -{ - mutex_exit(hash_get_mutex(table, fold)); -} - -/************************************************************//** -Reserves all the mutexes of a hash table, in an ascending order. */ -UNIV_INTERN -void -hash_mutex_enter_all( -/*=================*/ - hash_table_t* table) /*!< in: hash table */ -{ - ulint i; - - for (i = 0; i < table->n_mutexes; i++) { - - mutex_enter(table->mutexes + i); - } -} - -/************************************************************//** -Releases all the mutexes of a hash table. */ -UNIV_INTERN -void -hash_mutex_exit_all( -/*================*/ - hash_table_t* table) /*!< in: hash table */ -{ - ulint i; - - for (i = 0; i < table->n_mutexes; i++) { - - mutex_exit(table->mutexes + i); - } -} -#endif /* !UNIV_HOTBACKUP */ - -/*************************************************************//** -Creates a hash table with >= n array cells. The actual number of cells is -chosen to be a prime number slightly bigger than n. -@return own: created table */ -UNIV_INTERN -hash_table_t* -hash_create( -/*========*/ - ulint n) /*!< in: number of array cells */ -{ - hash_cell_t* array; - ulint prime; - hash_table_t* table; - - prime = ut_find_prime(n); - - table = mem_alloc(sizeof(hash_table_t)); - - array = ut_malloc(sizeof(hash_cell_t) * prime); - - table->array = array; - table->n_cells = prime; -#ifndef UNIV_HOTBACKUP -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - table->adaptive = FALSE; -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - table->n_mutexes = 0; - table->mutexes = NULL; - table->heaps = NULL; -#endif /* !UNIV_HOTBACKUP */ - table->heap = NULL; - ut_d(table->magic_n = HASH_TABLE_MAGIC_N); - - /* Initialize the cell array */ - hash_table_clear(table); - - return(table); -} - -/*************************************************************//** -Frees a hash table. */ -UNIV_INTERN -void -hash_table_free( -/*============*/ - hash_table_t* table) /*!< in, own: hash table */ -{ - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); -#ifndef UNIV_HOTBACKUP - ut_a(table->mutexes == NULL); -#endif /* !UNIV_HOTBACKUP */ - - ut_free(table->array); - mem_free(table); -} - -#ifndef UNIV_HOTBACKUP -/*************************************************************//** -Creates a mutex array to protect a hash table. */ -UNIV_INTERN -void -hash_create_mutexes_func( -/*=====================*/ - hash_table_t* table, /*!< in: hash table */ -#ifdef UNIV_SYNC_DEBUG - ulint sync_level, /*!< in: latching order level of the - mutexes: used in the debug version */ -#endif /* UNIV_SYNC_DEBUG */ - ulint n_mutexes) /*!< in: number of mutexes, must be a - power of 2 */ -{ - ulint i; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); - ut_a(n_mutexes > 0); - ut_a(ut_is_2pow(n_mutexes)); - - table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t)); - - for (i = 0; i < n_mutexes; i++) { - mutex_create(hash_table_mutex_key, - table->mutexes + i, sync_level); - } - - table->n_mutexes = n_mutexes; -} -#endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/ha/hash0hash.cc b/storage/innobase/ha/hash0hash.cc new file mode 100644 index 00000000000..99128a676d5 --- /dev/null +++ b/storage/innobase/ha/hash0hash.cc @@ -0,0 +1,403 @@ +/***************************************************************************** + +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file ha/hash0hash.cc +The simple hash table utility + +Created 5/20/1997 Heikki Tuuri +*******************************************************/ + +#include "hash0hash.h" +#ifdef UNIV_NONINL +#include "hash0hash.ic" +#endif + +#include "mem0mem.h" + +#ifndef UNIV_HOTBACKUP + +# ifdef UNIV_PFS_MUTEX +UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key; +# endif /* UNIV_PFS_MUTEX */ + +# ifdef UNIV_PFS_RWLOCK +UNIV_INTERN mysql_pfs_key_t hash_table_rw_lock_key; +# endif /* UNIV_PFS_RWLOCK */ +/************************************************************//** +Reserves the mutex for a fold value in a hash table. */ +UNIV_INTERN +void +hash_mutex_enter( +/*=============*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + mutex_enter(hash_get_mutex(table, fold)); +} + +/************************************************************//** +Releases the mutex for a fold value in a hash table. */ +UNIV_INTERN +void +hash_mutex_exit( +/*============*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + mutex_exit(hash_get_mutex(table, fold)); +} + +/************************************************************//** +Reserves all the mutexes of a hash table, in an ascending order. */ +UNIV_INTERN +void +hash_mutex_enter_all( +/*=================*/ + hash_table_t* table) /*!< in: hash table */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + for (i = 0; i < table->n_sync_obj; i++) { + + mutex_enter(table->sync_obj.mutexes + i); + } +} + +/************************************************************//** +Releases all the mutexes of a hash table. */ +UNIV_INTERN +void +hash_mutex_exit_all( +/*================*/ + hash_table_t* table) /*!< in: hash table */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + for (i = 0; i < table->n_sync_obj; i++) { + + mutex_exit(table->sync_obj.mutexes + i); + } +} + +/************************************************************//** +Releases all but the passed in mutex of a hash table. */ +UNIV_INTERN +void +hash_mutex_exit_all_but( +/*====================*/ + hash_table_t* table, /*!< in: hash table */ + mutex_t* keep_mutex) /*!< in: mutex to keep */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_MUTEX); + for (i = 0; i < table->n_sync_obj; i++) { + + mutex_t* mutex = table->sync_obj.mutexes + i; + if (UNIV_LIKELY(keep_mutex != mutex)) { + mutex_exit(mutex); + } + } + + ut_ad(mutex_own(keep_mutex)); +} + +/************************************************************//** +s-lock a lock for a fold value in a hash table. */ +UNIV_INTERN +void +hash_lock_s( +/*========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + + rw_lock_t* lock = hash_get_lock(table, fold); + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(lock); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_s_lock(lock); +} + +/************************************************************//** +x-lock a lock for a fold value in a hash table. */ +UNIV_INTERN +void +hash_lock_x( +/*========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + + rw_lock_t* lock = hash_get_lock(table, fold); + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(lock); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_x_lock(lock); +} + +/************************************************************//** +unlock an s-lock for a fold value in a hash table. */ +UNIV_INTERN +void +hash_unlock_s( +/*==========*/ + + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + + rw_lock_t* lock = hash_get_lock(table, fold); + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(lock); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(lock, RW_LOCK_SHARED)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_s_unlock(lock); +} + +/************************************************************//** +unlock x-lock for a fold value in a hash table. */ +UNIV_INTERN +void +hash_unlock_x( +/*==========*/ + hash_table_t* table, /*!< in: hash table */ + ulint fold) /*!< in: fold */ +{ + rw_lock_t* lock = hash_get_lock(table, fold); + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + ut_ad(lock); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_x_unlock(lock); +} + +/************************************************************//** +Reserves all the locks of a hash table, in an ascending order. */ +UNIV_INTERN +void +hash_lock_x_all( +/*============*/ + hash_table_t* table) /*!< in: hash table */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + for (i = 0; i < table->n_sync_obj; i++) { + + rw_lock_t* lock = table->sync_obj.rw_locks + i; +#ifdef UNIV_SYNC_DEBUG + ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_x_lock(lock); + } +} + +/************************************************************//** +Releases all the locks of a hash table, in an ascending order. */ +UNIV_INTERN +void +hash_unlock_x_all( +/*==============*/ + hash_table_t* table) /*!< in: hash table */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + for (i = 0; i < table->n_sync_obj; i++) { + + rw_lock_t* lock = table->sync_obj.rw_locks + i; +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + rw_lock_x_unlock(lock); + } +} + +/************************************************************//** +Releases all but passed in lock of a hash table, */ +UNIV_INTERN +void +hash_unlock_x_all_but( +/*==================*/ + hash_table_t* table, /*!< in: hash table */ + rw_lock_t* keep_lock) /*!< in: lock to keep */ +{ + ulint i; + + ut_ad(table->type == HASH_TABLE_SYNC_RW_LOCK); + for (i = 0; i < table->n_sync_obj; i++) { + + rw_lock_t* lock = table->sync_obj.rw_locks + i; +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + if (UNIV_LIKELY(keep_lock != lock)) { + rw_lock_x_unlock(lock); + } + } +} + +#endif /* !UNIV_HOTBACKUP */ + +/*************************************************************//** +Creates a hash table with >= n array cells. The actual number of cells is +chosen to be a prime number slightly bigger than n. +@return own: created table */ +UNIV_INTERN +hash_table_t* +hash_create( +/*========*/ + ulint n) /*!< in: number of array cells */ +{ + hash_cell_t* array; + ulint prime; + hash_table_t* table; + + prime = ut_find_prime(n); + + table = static_cast<hash_table_t*>(mem_alloc(sizeof(hash_table_t))); + + array = static_cast<hash_cell_t*>( + ut_malloc(sizeof(hash_cell_t) * prime)); + + /* The default type of hash_table is HASH_TABLE_SYNC_NONE i.e.: + the caller is responsible for access control to the table. */ + table->type = HASH_TABLE_SYNC_NONE; + table->array = array; + table->n_cells = prime; +#ifndef UNIV_HOTBACKUP +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + table->adaptive = FALSE; +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + table->n_sync_obj = 0; + table->sync_obj.mutexes = NULL; + table->heaps = NULL; +#endif /* !UNIV_HOTBACKUP */ + table->heap = NULL; + ut_d(table->magic_n = HASH_TABLE_MAGIC_N); + + /* Initialize the cell array */ + hash_table_clear(table); + + return(table); +} + +/*************************************************************//** +Frees a hash table. */ +UNIV_INTERN +void +hash_table_free( +/*============*/ + hash_table_t* table) /*!< in, own: hash table */ +{ + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + + ut_free(table->array); + mem_free(table); +} + +#ifndef UNIV_HOTBACKUP +/*************************************************************//** +Creates a sync object array to protect a hash table. +::sync_obj can be mutexes or rw_locks depening on the type of +hash table. */ +UNIV_INTERN +void +hash_create_sync_obj_func( +/*======================*/ + hash_table_t* table, /*!< in: hash table */ + enum hash_table_sync_t type, /*!< in: HASH_TABLE_SYNC_MUTEX + or HASH_TABLE_SYNC_RW_LOCK */ +#ifdef UNIV_SYNC_DEBUG + ulint sync_level,/*!< in: latching order level + of the mutexes: used in the + debug version */ +#endif /* UNIV_SYNC_DEBUG */ + ulint n_sync_obj)/*!< in: number of sync objects, + must be a power of 2 */ +{ + ulint i; + + ut_ad(table); + ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); + ut_a(n_sync_obj > 0); + ut_a(ut_is_2pow(n_sync_obj)); + + table->type = type; + + switch (type) { + case HASH_TABLE_SYNC_MUTEX: + table->sync_obj.mutexes = static_cast<mutex_t*>( + mem_alloc(n_sync_obj * sizeof(mutex_t))); + + for (i = 0; i < n_sync_obj; i++) { + mutex_create(hash_table_mutex_key, + table->sync_obj.mutexes + i, sync_level); + } + + break; + + case HASH_TABLE_SYNC_RW_LOCK: + table->sync_obj.rw_locks = static_cast<rw_lock_t*>( + mem_alloc(n_sync_obj * sizeof(rw_lock_t))); + + for (i = 0; i < n_sync_obj; i++) { + rw_lock_create(hash_table_rw_lock_key, + table->sync_obj.rw_locks + i, sync_level); + } + + break; + + case HASH_TABLE_SYNC_NONE: + ut_error; + } + + table->n_sync_obj = n_sync_obj; +} +#endif /* !UNIV_HOTBACKUP */ |