From bf3c862faa8efed4a662725ec27586cd69e9228e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Jun 2020 12:17:37 +0300 Subject: MDEV-22871: Clean up btr_search_sys btr_search_sys::parts[]: A single structure for the partitions of the adaptive hash index. Replaces the 3 separate arrays: btr_search_latches[], btr_search_sys->hash_tables, btr_search_sys->hash_tables[i]->heap. hash_table_t::heap, hash_table_t::adaptive: Remove. ha0ha.cc: Remove. Move all code to btr0sea.cc. --- storage/innobase/include/btr0sea.h | 138 ++++++++++++++++++++++++++-------- storage/innobase/include/btr0sea.ic | 44 ++--------- storage/innobase/include/buf0buf.h | 2 +- storage/innobase/include/ha0ha.h | 119 ----------------------------- storage/innobase/include/ha0ha.ic | 43 ----------- storage/innobase/include/hash0hash.h | 36 ++++----- storage/innobase/include/hash0hash.ic | 3 - storage/innobase/include/ut0new.h | 1 - 8 files changed, 127 insertions(+), 259 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index a406676c6ed..e3de4926a57 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -30,13 +30,10 @@ Created 2/17/1996 Heikki Tuuri #include "dict0dict.h" #ifdef BTR_CUR_HASH_ADAPT #include "ha0ha.h" +#include "sync0sync.h" -/** Creates and initializes the adaptive search system at a database start. -@param[in] hash_size hash table size. */ -void btr_search_sys_create(ulint hash_size); - -/** Frees the adaptive search system at a database shutdown. */ -void btr_search_sys_free(); +#define btr_search_sys_create() btr_search_sys.create() +#define btr_search_sys_free() btr_search_sys.free() /** Disable the adaptive hash search system and empty the index. */ void btr_search_disable(); @@ -162,19 +159,8 @@ static inline bool btr_search_own_any(); /** Unlock all search latches from shared mode. */ static inline void btr_search_s_unlock_all(); -/** Get the latch based on index attributes. -A latch is selected from an array of latches using pair of index-id, space-id. -@param[in] index index handler -@return latch */ -static inline rw_lock_t* btr_get_search_latch(const dict_index_t* index); - -/** Get the hash-table based on index attributes. -A table is selected from an array of tables using pair of index-id, space-id. -@param[in] index index handler -@return hash table */ -static inline hash_table_t* btr_get_search_table(const dict_index_t* index); #else /* BTR_CUR_HASH_ADAPT */ -# define btr_search_sys_create(size) +# define btr_search_sys_create() # define btr_search_sys_free() # define btr_search_drop_page_hash_index(block) # define btr_search_s_lock_all(index) @@ -259,31 +245,119 @@ struct btr_search_t{ }; #ifdef BTR_CUR_HASH_ADAPT +/** The hash index system */ +struct btr_search_sys_t +{ + /** Partition of the hash table */ + struct partition + { + /** latches protecting hash_table */ + rw_lock_t latch; + /** mapping of dtuple_fold() to rec_t* in buf_block_t::frame */ + hash_table_t table; + /** memory heap for table */ + mem_heap_t *heap; + + char pad[(CPU_LEVEL1_DCACHE_LINESIZE - sizeof(rw_lock_t) - + sizeof(hash_table_t) - sizeof(mem_heap_t)) & + (CPU_LEVEL1_DCACHE_LINESIZE - 1)]; + + void init() + { + memset((void*) this, 0, sizeof *this); + rw_lock_create(btr_search_latch_key, &latch, SYNC_SEARCH_SYS); + } + + void alloc(ulint hash_size) + { + table.create(hash_size); + heap= mem_heap_create_typed(std::min(4096, + MEM_MAX_ALLOC_IN_BUF / 2 + - MEM_BLOCK_HEADER_SIZE + - MEM_SPACE_NEEDED(0)), + MEM_HEAP_FOR_BTR_SEARCH); + } + + void clear() + { + mem_heap_free(heap); + heap= nullptr; + ut_free(table.array); + } + + void free() + { + rw_lock_free(&latch); + if (heap) + clear(); + } + }; + + /** Partitions of the adaptive hash index */ + partition *parts; + + /** Get an adaptive hash index partition */ + partition *get_part(index_id_t id, ulint space_id) const + { + return parts + ut_fold_ulint_pair(ulint(id), space_id) % btr_ahi_parts; + } + + /** Get an adaptive hash index partition */ + partition *get_part(const dict_index_t &index) const + { + ut_ad(index.table->space->id == index.table->space_id); + return get_part(ulint(index.id), index.table->space_id); + } + + /** Get the search latch for the adaptive hash index partition */ + rw_lock_t *get_latch(const dict_index_t &index) const + { return &get_part(index)->latch; } + + /** Create and initialize at startup */ + void create() + { + parts= static_cast(ut_malloc(btr_ahi_parts * sizeof *parts, + mem_key_ahi)); + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].init(); + if (btr_search_enabled) + btr_search_enable(); + } + + void alloc(ulint hash_size) + { + hash_size/= btr_ahi_parts; + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].alloc(hash_size); + } + + /** Clear when disabling the adaptive hash index */ + void clear() { for (ulong i= 0; i < btr_ahi_parts; ++i) parts[i].clear(); } + + /** Free at shutdown */ + void free() + { + if (parts) + for (ulong i= 0; i < btr_ahi_parts; ++i) + parts[i].free(); + } +}; + +/** The adaptive hash index */ +extern btr_search_sys_t btr_search_sys; + /** @return number of leaf pages pointed to by the adaptive hash index */ inline ulint dict_index_t::n_ahi_pages() const { if (!btr_search_enabled) return 0; - rw_lock_t *latch = btr_get_search_latch(this); + rw_lock_t *latch = &btr_search_sys.get_part(*this)->latch; rw_lock_s_lock(latch); ulint ref_count= search_info->ref_count; rw_lock_s_unlock(latch); return ref_count; } -/** The hash index system */ -struct btr_search_sys_t{ - hash_table_t** hash_tables; /*!< the adaptive hash tables, - mapping dtuple_fold values - to rec_t pointers on index pages */ -}; - -/** Latches protecting access to adaptive hash index. */ -extern rw_lock_t** btr_search_latches; - -/** The adaptive hash index */ -extern btr_search_sys_t* btr_search_sys; - #ifdef UNIV_SEARCH_PERF_STAT /** Number of successful adaptive hash index lookups */ extern ulint btr_search_n_succ; diff --git a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic index 9db0084ce59..40eb5d86ead 100644 --- a/storage/innobase/include/btr0sea.ic +++ b/storage/innobase/include/btr0sea.ic @@ -88,7 +88,7 @@ btr_search_info_update( static inline void btr_search_x_lock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_lock(btr_search_latches[i]); + rw_lock_x_lock(&btr_search_sys.parts[i].latch); } } @@ -96,7 +96,7 @@ static inline void btr_search_x_lock_all() static inline void btr_search_x_unlock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_x_unlock(btr_search_latches[i]); + rw_lock_x_unlock(&btr_search_sys.parts[i].latch); } } @@ -104,7 +104,7 @@ static inline void btr_search_x_unlock_all() static inline void btr_search_s_lock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_lock(btr_search_latches[i]); + rw_lock_s_lock(&btr_search_sys.parts[i].latch); } } @@ -112,7 +112,7 @@ static inline void btr_search_s_lock_all() static inline void btr_search_s_unlock_all() { for (ulint i = 0; i < btr_ahi_parts; ++i) { - rw_lock_s_unlock(btr_search_latches[i]); + rw_lock_s_unlock(&btr_search_sys.parts[i].latch); } } @@ -124,7 +124,7 @@ static inline void btr_search_s_unlock_all() static inline bool btr_search_own_all(ulint mode) { for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (!rw_lock_own(btr_search_latches[i], mode)) { + if (!rw_lock_own(&btr_search_sys.parts[i].latch, mode)) { return(false); } } @@ -138,7 +138,7 @@ static inline bool btr_search_own_all(ulint mode) static inline bool btr_search_own_any(ulint mode) { for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (rw_lock_own(btr_search_latches[i], mode)) { + if (rw_lock_own(&btr_search_sys.parts[i].latch, mode)) { return(true); } } @@ -149,7 +149,7 @@ static inline bool btr_search_own_any(ulint mode) static inline bool btr_search_own_any() { for (ulint i = btr_ahi_parts; i--; ) { - if (rw_lock_own_flagged(btr_search_latches[i], + if (rw_lock_own_flagged(&btr_search_sys.parts[i].latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)) { return true; } @@ -157,34 +157,4 @@ static inline bool btr_search_own_any() return false; } #endif /* UNIV_DEBUG */ - -/** Get the adaptive hash search index latch for a b-tree. -@param[in] index b-tree index -@return latch */ -static inline rw_lock_t* btr_get_search_latch(const dict_index_t* index) -{ - ut_ad(index != NULL); - ut_ad(!index->table->space - || index->table->space->id == index->table->space_id); - - ulint ifold = ut_fold_ulint_pair(ulint(index->id), - index->table->space_id); - - return(btr_search_latches[ifold % btr_ahi_parts]); -} - -/** Get the hash-table based on index attributes. -A table is selected from an array of tables using pair of index-id, space-id. -@param[in] index index handler -@return hash table */ -static inline hash_table_t* btr_get_search_table(const dict_index_t* index) -{ - ut_ad(index != NULL); - ut_ad(index->table->space->id == index->table->space_id); - - ulint ifold = ut_fold_ulint_pair(ulint(index->id), - index->table->space_id); - - return(btr_search_sys->hash_tables[ifold % btr_ahi_parts]); -} #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 71d06db01e9..6758e427c74 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1131,7 +1131,7 @@ struct buf_block_t{ assigning block->index = NULL (and block->n_pointers = 0) is allowed whenever btr_search_own_all(RW_LOCK_X). - Another exception is that ha_insert_for_fold_func() may + Another exception is that ha_insert_for_fold() may decrement n_pointers without holding the appropriate latch in btr_search_latches[]. Thus, n_pointers must be protected by atomic memory access. diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 3b3e511c9f5..561c322521e 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -43,125 +43,6 @@ ha_search_and_get_data( /*===================*/ hash_table_t* table, /*!< in: hash table */ ulint fold); /*!< in: folded value of the searched data */ -/*********************************************************//** -Looks for an element when we know the pointer to the data and updates -the pointer to data if found. -@return TRUE if found */ -ibool -ha_search_and_update_if_found_func( -/*===============================*/ - hash_table_t* table, /*!< in/out: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data, /*!< in: pointer to the data */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* new_block,/*!< in: block containing new_data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* new_data);/*!< in: new pointer to the data */ - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** Looks for an element when we know the pointer to the data and -updates the pointer to data if found. -@param table in/out: hash table -@param fold in: folded value of the searched data -@param data in: pointer to the data -@param new_block in: block containing new_data -@param new_data in: new pointer to the data */ -# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ - ha_search_and_update_if_found_func(table,fold,data,new_block,new_data) -#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -/** Looks for an element when we know the pointer to the data and -updates the pointer to data if found. -@param table in/out: hash table -@param fold in: folded value of the searched data -@param data in: pointer to the data -@param new_block ignored: block containing new_data -@param new_data in: new pointer to the data */ -# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ - ha_search_and_update_if_found_func(table,fold,data,new_data) -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -#endif /* BTR_CUR_HASH_ADAPT */ - -#ifdef BTR_CUR_HASH_ADAPT -/*************************************************************//** -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. -@return TRUE if succeed, FALSE if no more memory could be allocated */ -ibool -ha_insert_for_fold_func( -/*====================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of data; if a node with - the same fold value already exists, it is - updated to point to the same data, and no new - node is created! */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - buf_block_t* block, /*!< in: buffer block containing the data */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - const rec_t* data); /*!< in: data, must not be NULL */ - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/** -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. -@return TRUE if succeed, FALSE if no more memory could be allocated -@param t in: hash table -@param f in: folded value of data -@param b in: buffer block containing the data -@param d in: data, must not be NULL */ -# define ha_insert_for_fold(t,f,b,d) do { \ - ha_insert_for_fold_func(t,f,b,d); \ - MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \ -} while(0) -#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -/** -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. -@return TRUE if succeed, FALSE if no more memory could be allocated -@param t in: hash table -@param f in: folded value of data -@param b ignored: buffer block containing the data -@param d in: data, must not be NULL */ -# define ha_insert_for_fold(t,f,b,d) do { \ - ha_insert_for_fold_func(t,f,d); \ - MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); \ -} while (0) -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - -/*********************************************************//** -Looks for an element when we know the pointer to the data and deletes -it from the hash table if found. -@return TRUE if found */ -UNIV_INLINE -ibool -ha_search_and_delete_if_found( -/*==========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data); /*!< in: pointer to the data */ - -/*****************************************************************//** -Removes from the chain determined by fold all nodes whose data pointer -points to the page given. */ -void -ha_remove_all_nodes_to_page( -/*========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: fold value */ - const page_t* page); /*!< in: buffer page */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG -/*************************************************************//** -Validates a given range of the cells in hash table. -@return TRUE if ok */ -ibool -ha_validate( -/*========*/ - hash_table_t* table, /*!< in: hash table */ - ulint start_index, /*!< in: start index */ - ulint end_index); /*!< in: end index */ -#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ /** The hash table external chain node */ struct ha_node_t { diff --git a/storage/innobase/include/ha0ha.ic b/storage/innobase/include/ha0ha.ic index 57f21c02324..e358b1070eb 100644 --- a/storage/innobase/include/ha0ha.ic +++ b/storage/innobase/include/ha0ha.ic @@ -25,8 +25,6 @@ Created 8/18/1994 Heikki Tuuri *************************************************************************/ #ifdef BTR_CUR_HASH_ADAPT -#include "ut0rnd.h" -#include "mem0mem.h" #include "btr0types.h" /******************************************************************//** @@ -154,45 +152,4 @@ ha_search_with_data( return(NULL); } -/***********************************************************//** -Deletes a hash node. */ -void -ha_delete_hash_node( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ha_node_t* del_node); /*!< in: node to be deleted */ - -#ifdef UNIV_DEBUG -/** Verify if latch corresponding to the hash table is x-latched -@param table hash table */ -void ha_btr_search_latch_x_locked(const hash_table_t* table); -#endif /* UNIV_DEBUG */ - -/*********************************************************//** -Looks for an element when we know the pointer to the data, and deletes -it from the hash table, if found. -@return TRUE if found */ -UNIV_INLINE -ibool -ha_search_and_delete_if_found( -/*==========================*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold, /*!< in: folded value of the searched data */ - const rec_t* data) /*!< in: pointer to the data */ -{ - ha_node_t* node; - - ut_d(ha_btr_search_latch_x_locked(table)); - ut_ad(btr_search_enabled); - - node = ha_search_with_data(table, fold, data); - - if (node) { - ha_delete_hash_node(table, node); - - return(TRUE); - } - - return(FALSE); -} #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 29e242a540d..8d84e6e976c 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -24,11 +24,8 @@ The simple hash table utility Created 5/20/1997 Heikki Tuuri *******************************************************/ -#ifndef hash0hash_h -#define hash0hash_h - -#include "mem0mem.h" -#include "sync0rw.h" +#pragma once +#include "ut0rnd.h" struct hash_table_t; struct hash_cell_t{ @@ -259,26 +256,19 @@ do {\ }\ } while (0) -/* The hash table structure */ -struct hash_table_t { -#ifdef BTR_CUR_HASH_ADAPT -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - ibool adaptive;/* TRUE if this is the hash - table of the adaptive hash - index */ -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ -#endif /* BTR_CUR_HASH_ADAPT */ - ulint n_cells;/* number of cells in the hash table */ - hash_cell_t* array; /*!< pointer to cell array */ - mem_heap_t* heap; -#ifdef UNIV_DEBUG - ulint magic_n; -# define HASH_TABLE_MAGIC_N 76561114 -#endif /* UNIV_DEBUG */ +/** Hash table with singly-linkde overflow lists */ +struct hash_table_t +{ + /** number of elements in array (a prime number) */ + ulint n_cells; + /** the hash array */ + hash_cell_t *array; + + /** Create the hash table. + @param n the lower bound of n_cells */ + void create(ulint n); ulint calc_hash(ulint fold) const { return ut_hash_ulint(fold, n_cells); } }; #include "hash0hash.ic" - -#endif diff --git a/storage/innobase/include/hash0hash.ic b/storage/innobase/include/hash0hash.ic index 63661b041fd..e6ca3b15bd0 100644 --- a/storage/innobase/include/hash0hash.ic +++ b/storage/innobase/include/hash0hash.ic @@ -35,7 +35,6 @@ hash_get_nth_cell( ulint n) /*!< in: cell index */ { ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); ut_ad(n < table->n_cells); return(table->array + n); @@ -50,7 +49,6 @@ hash_table_clear( hash_table_t* table) /*!< in/out: hash table */ { ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); memset(table->array, 0x0, table->n_cells * sizeof(*table->array)); } @@ -65,6 +63,5 @@ hash_get_n_cells( hash_table_t* table) /*!< in: table */ { ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); return(table->n_cells); } diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 5137c8f3ae1..87249062a83 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -859,7 +859,6 @@ constexpr const char* const auto_event_names[] = "fts0tlex", "gis0sea", "ha_innodb", - "ha0ha", "handler0alter", "hash0hash", "i_s", -- cgit v1.2.1