summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-06-18 12:17:37 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-06-18 14:16:01 +0300
commitbf3c862faa8efed4a662725ec27586cd69e9228e (patch)
tree85acdff0c73a376fa5cdd15a6d8f92bff3efe303
parent9159b8976f7dfe9c956608f23df42d49ba1fcbbc (diff)
downloadmariadb-git-bf3c862faa8efed4a662725ec27586cd69e9228e.tar.gz
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.
-rw-r--r--storage/innobase/CMakeLists.txt1
-rw-r--r--storage/innobase/btr/btr0cur.cc6
-rw-r--r--storage/innobase/btr/btr0sea.cc563
-rw-r--r--storage/innobase/buf/buf0buf.cc2
-rw-r--r--storage/innobase/ha/ha0ha.cc361
-rw-r--r--storage/innobase/ha/hash0hash.cc17
-rw-r--r--storage/innobase/include/btr0sea.h138
-rw-r--r--storage/innobase/include/btr0sea.ic44
-rw-r--r--storage/innobase/include/buf0buf.h2
-rw-r--r--storage/innobase/include/ha0ha.h119
-rw-r--r--storage/innobase/include/ha0ha.ic43
-rw-r--r--storage/innobase/include/hash0hash.h36
-rw-r--r--storage/innobase/include/hash0hash.ic3
-rw-r--r--storage/innobase/include/ut0new.h1
-rw-r--r--storage/innobase/row/row0sel.cc2
-rw-r--r--storage/innobase/srv/srv0srv.cc48
-rw-r--r--storage/innobase/srv/srv0start.cc3
17 files changed, 497 insertions, 892 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 0cef6770181..ae5185e315e 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -56,7 +56,6 @@ SET(INNOBASE_SOURCES
fsp/fsp0space.cc
fsp/fsp0sysspace.cc
fut/fut0lst.cc
- ha/ha0ha.cc
ha/ha0storage.cc
ha/hash0hash.cc
fts/fts0fts.cc
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index c99b737200d..9da9b90d246 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -3561,7 +3561,7 @@ fail_err:
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else {
- rw_lock_t* ahi_latch = btr_get_search_latch(index);
+ rw_lock_t* ahi_latch = btr_search_sys.get_latch(*index);
if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(
cursor, ahi_latch);
@@ -3772,7 +3772,7 @@ btr_cur_pessimistic_insert(
ut_ad(!(flags & BTR_CREATE_FLAG));
} else {
btr_search_update_hash_on_insert(
- cursor, btr_get_search_latch(index));
+ cursor, btr_search_sys.get_latch(*index));
}
#endif /* BTR_CUR_HASH_ADAPT */
if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) {
@@ -4274,7 +4274,7 @@ btr_cur_update_in_place(
#ifdef BTR_CUR_HASH_ADAPT
{
rw_lock_t* ahi_latch = block->index
- ? btr_get_search_latch(index) : NULL;
+ ? btr_search_sys.get_latch(*index) : NULL;
if (ahi_latch) {
/* TO DO: Can we skip this if none of the fields
index->search_info->curr_n_fields
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 2d1f9100f32..bdaea6244ea 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -41,7 +41,6 @@ Created 2/17/1996 Heikki Tuuri
#include "btr0btr.h"
#include "ha0ha.h"
#include "srv0mon.h"
-#include "sync0sync.h"
/** Is search system enabled.
Search system is protected by array of latches. */
@@ -57,25 +56,8 @@ ulint btr_search_n_succ = 0;
ulint btr_search_n_hash_fail = 0;
#endif /* UNIV_SEARCH_PERF_STAT */
-/** padding to prevent other memory update
-hotspots from residing on the same memory
-cache line as btr_search_latches */
-UNIV_INTERN byte btr_sea_pad1[CACHE_LINE_SIZE];
-
-/** The latches protecting the adaptive search system: this latches protects the
-(1) positions of records on those pages where a hash index has been built.
-NOTE: It does not protect values of non-ordering fields within a record from
-being updated in-place! We can use fact (1) to perform unique searches to
-indexes. We will allocate the latches from dynamic memory to get it to the
-same DRAM page as other hotspot semaphores */
-rw_lock_t** btr_search_latches;
-
-/** padding to prevent other memory update hotspots from residing on
-the same memory cache line */
-UNIV_INTERN byte btr_sea_pad2[CACHE_LINE_SIZE];
-
/** The adaptive hash index */
-btr_search_sys_t* btr_search_sys;
+btr_search_sys_t btr_search_sys;
/** If the number of records on the page divided by this parameter
would have been successfully accessed using a hash index, the index
@@ -187,104 +169,23 @@ probable that, when have reserved the btr search system latch and we need to
allocate a new node to the hash table, it will succeed. However, the check
will not guarantee success.
@param[in] index index handler */
-static
-void
-btr_search_check_free_space_in_heap(const dict_index_t* index)
+static void btr_search_check_free_space_in_heap(const dict_index_t *index)
{
- /* Note that we peek the value of heap->free_block without reserving
- the latch: this is ok, because we will not guarantee that there will
- be enough free space in the hash table. */
+ /* Note that we peek the value of heap->free_block without reserving
+ the latch: this is ok, because we will not guarantee that there will
+ be enough free space in the hash table. */
- buf_block_t* block = buf_block_alloc();
- rw_lock_t* latch = btr_get_search_latch(index);
- hash_table_t* table;
- mem_heap_t* heap;
+ buf_block_t *block= buf_block_alloc();
+ auto part= btr_search_sys.get_part(*index);
- rw_lock_x_lock(latch);
+ rw_lock_x_lock(&part->latch);
- if (!btr_search_enabled) {
- goto func_exit;
- }
-
- table = btr_get_search_table(index);
- heap = table->heap;
+ if (!btr_search_enabled || part->heap->free_block)
+ buf_block_free(block);
+ else
+ part->heap->free_block= block;
- if (heap->free_block == NULL) {
- heap->free_block = block;
- } else {
-func_exit:
- buf_block_free(block);
- }
-
- rw_lock_x_unlock(latch);
-}
-
-/** 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)
-{
- /* Search System is divided into n parts.
- Each part controls access to distinct set of hash buckets from
- hash table through its own latch. */
-
- /* Step-1: Allocate latches (1 per part). */
- btr_search_latches = reinterpret_cast<rw_lock_t**>(
- ut_malloc(sizeof(rw_lock_t*) * btr_ahi_parts, mem_key_ahi));
-
- for (ulint i = 0; i < btr_ahi_parts; ++i) {
-
- btr_search_latches[i] = reinterpret_cast<rw_lock_t*>(
- ut_malloc(sizeof(rw_lock_t), mem_key_ahi));
-
- rw_lock_create(btr_search_latch_key,
- btr_search_latches[i], SYNC_SEARCH_SYS);
- }
-
- /* Step-2: Allocate hash tablees. */
- btr_search_sys = reinterpret_cast<btr_search_sys_t*>(
- ut_malloc(sizeof(btr_search_sys_t), mem_key_ahi));
-
- btr_search_sys->hash_tables = NULL;
-
- if (btr_search_enabled) {
- btr_search_enable();
- }
-}
-
-/** Frees the adaptive search system at a database shutdown. */
-void btr_search_sys_free()
-{
- if (!btr_search_sys)
- {
- ut_ad(!btr_search_latches);
- return;
- }
-
- ut_ad(btr_search_sys);
- ut_ad(btr_search_latches);
-
- if (btr_search_sys->hash_tables)
- {
- for (ulint i= 0; i < btr_ahi_parts; ++i)
- {
- mem_heap_free(btr_search_sys->hash_tables[i]->heap);
- hash_table_free(btr_search_sys->hash_tables[i]);
- }
- ut_free(btr_search_sys->hash_tables);
- }
-
- ut_free(btr_search_sys);
- btr_search_sys= nullptr;
-
- /* Free all latches. */
- for (ulint i= 0; i < btr_ahi_parts; ++i)
- {
- rw_lock_free(btr_search_latches[i]);
- ut_free(btr_search_latches[i]);
- }
-
- ut_free(btr_search_latches);
- btr_search_latches= nullptr;
+ rw_lock_x_unlock(&part->latch);
}
/** Set index->ref_count = 0 on all indexes of a table.
@@ -351,12 +252,7 @@ void btr_search_disable()
buf_pool.clear_hash_index();
/* Clear the adaptive hash index. */
- for (ulint i = 0; i < btr_ahi_parts; ++i) {
- mem_heap_free(btr_search_sys->hash_tables[i]->heap);
- hash_table_free(btr_search_sys->hash_tables[i]);
- }
- ut_free(btr_search_sys->hash_tables);
- btr_search_sys->hash_tables = NULL;
+ btr_search_sys.clear();
btr_search_x_unlock_all();
}
@@ -377,27 +273,13 @@ void btr_search_enable(bool resize)
btr_search_x_lock_all();
ulint hash_size = buf_pool_get_curr_size() / sizeof(void *) / 64;
- if (btr_search_sys->hash_tables) {
+ if (btr_search_sys.parts[0].heap) {
ut_ad(btr_search_enabled);
btr_search_x_unlock_all();
return;
}
- btr_search_sys->hash_tables = reinterpret_cast<hash_table_t**>(
- ut_malloc(sizeof(hash_table_t*) * btr_ahi_parts, mem_key_ahi));
- for (ulint i = 0; i < btr_ahi_parts; ++i) {
- btr_search_sys->hash_tables[i] =
- hash_create(hash_size / btr_ahi_parts);
- btr_search_sys->hash_tables[i]->heap = mem_heap_create_typed(
- std::min<ulong>(4096,
- MEM_MAX_ALLOC_IN_BUF / 2
- - MEM_BLOCK_HEADER_SIZE
- - MEM_SPACE_NEEDED(0)),
- MEM_HEAP_FOR_BTR_SEARCH);
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- btr_search_sys->hash_tables[i]->adaptive = TRUE;
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- }
+ btr_search_sys.alloc(hash_size);
btr_search_enabled = true;
btr_search_x_unlock_all();
@@ -581,6 +463,221 @@ btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block)
return(false);
}
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+/** Maximum number of records in a page */
+constexpr ulint MAX_N_POINTERS = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
+__attribute__((nonnull))
+/**
+Insert an entry into the 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.
+@param table hash table
+@param heap memory heap
+@param fold folded value of the record
+@param block buffer block containing the record
+@param data the record
+@retval true on success
+@retval false if no more memory could be allocated */
+static bool ha_insert_for_fold(hash_table_t *table, mem_heap_t* heap,
+ ulint fold,
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ buf_block_t *block, /*!< buffer block of data */
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ const rec_t *data)
+{
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(block->frame == page_align(data));
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ ut_ad(btr_search_enabled);
+
+ ulint hash = hash_calc_hash(fold, table);
+ hash_cell_t *cell= hash_get_nth_cell(table, hash);
+
+ for (ha_node_t *prev= static_cast<ha_node_t*>(cell->node); prev;
+ prev= prev->next)
+ {
+ if (prev->fold == fold)
+ {
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ buf_block_t *prev_block= prev->block;
+ ut_a(prev_block->frame == page_align(prev->data));
+ ut_a(prev_block->n_pointers-- < MAX_N_POINTERS);
+ ut_a(block->n_pointers++ < MAX_N_POINTERS);
+
+ prev->block= block;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ prev->data= data;
+ return true;
+ }
+ }
+
+ /* We have to allocate a new chain node */
+ ha_node_t *node= static_cast<ha_node_t*>(mem_heap_alloc(heap, sizeof *node));
+
+ if (!node)
+ return false;
+
+ ha_node_set_data(node, block, data);
+
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(block->n_pointers++ < MAX_N_POINTERS);
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
+ node->fold= fold;
+ node->next= nullptr;
+
+ ha_node_t *prev= static_cast<ha_node_t*>(cell->node);
+ if (!prev)
+ cell->node= node;
+ else
+ {
+ while (prev->next)
+ prev= prev->next;
+ prev->next= node;
+ }
+ return true;
+}
+
+__attribute__((nonnull))
+/** Delete a record.
+@param table hash table
+@param heap memory heap
+@param del_node record to be deleted */
+static void ha_delete_hash_node(hash_table_t *table, mem_heap_t *heap,
+ ha_node_t *del_node)
+{
+ ut_ad(btr_search_enabled);
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(del_node->block->frame == page_align(del_node->data));
+ ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS);
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
+ const ulint fold= del_node->fold;
+
+ HASH_DELETE(ha_node_t, next, table, fold, del_node);
+
+ ha_node_t *top= static_cast<ha_node_t*>(mem_heap_get_top(heap, sizeof *top));
+
+ if (del_node != top)
+ {
+ /* Compact the heap of nodes by moving the top in the place of del_node. */
+ *del_node= *top;
+ hash_cell_t *cell= hash_get_nth_cell(table, table->calc_hash(top->fold));
+
+ /* Look for the pointer to the top node, to update it */
+ if (cell->node == top)
+ /* The top node is the first in the chain */
+ cell->node= del_node;
+ else
+ {
+ /* We have to look for the predecessor */
+ ha_node_t *node= static_cast<ha_node_t*>(cell->node);
+
+ while (top != HASH_GET_NEXT(next, node))
+ node= static_cast<ha_node_t*>(HASH_GET_NEXT(next, node));
+
+ /* Now we have the predecessor node */
+ node->next= del_node;
+ }
+ }
+
+ /* Free the occupied space */
+ mem_heap_free_top(heap, sizeof *top);
+}
+
+__attribute__((nonnull))
+/** Delete all pointers to a page.
+@param table hash table
+@param heap memory heap
+@param page record to be deleted */
+static void ha_remove_all_nodes_to_page(hash_table_t *table, mem_heap_t *heap,
+ ulint fold, const page_t *page)
+{
+ for (ha_node_t *node= ha_chain_get_first(table, fold); node; )
+ {
+ if (page_align(ha_node_get_data(node)) == page)
+ {
+ ha_delete_hash_node(table, heap, node);
+ /* The deletion may compact the heap of nodes and move other nodes! */
+ node= ha_chain_get_first(table, fold);
+ }
+ else
+ node= ha_chain_get_next(node);
+ }
+#ifdef UNIV_DEBUG
+ /* Check that all nodes really got deleted */
+ for (ha_node_t *node= ha_chain_get_first(table, fold); node;
+ node= ha_chain_get_next(node))
+ ut_ad(page_align(ha_node_get_data(node)) != page);
+#endif /* UNIV_DEBUG */
+}
+
+/** Delete a record if found.
+@param table hash table
+@param heap memory heap for the hash bucket chain
+@param fold folded value of the searched data
+@param data pointer to the record
+@return whether the record was found */
+static bool ha_search_and_delete_if_found(hash_table_t *table,
+ mem_heap_t *heap,
+ ulint fold, const rec_t *data)
+{
+ if (ha_node_t *node= ha_search_with_data(table, fold, data))
+ {
+ ha_delete_hash_node(table, heap, node);
+ return true;
+ }
+
+ return false;
+}
+
+__attribute__((nonnull))
+/** Looks for an element when we know the pointer to the data and
+updates the pointer to data if found.
+@param table hash table
+@param fold folded value of the searched data
+@param data pointer to the data
+@param new_data new pointer to the data
+@return whether the element was found */
+static bool ha_search_and_update_if_found(hash_table_t *table, ulint fold,
+ const rec_t *data,
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ /** block containing new_data */
+ buf_block_t *new_block,
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ const rec_t *new_data)
+{
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(new_block->frame == page_align(new_data));
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
+ if (!btr_search_enabled)
+ return false;
+
+ if (ha_node_t *node= ha_search_with_data(table, fold, data))
+ {
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+ ut_a(node->block->n_pointers-- < MAX_N_POINTERS);
+ ut_a(new_block->n_pointers++ < MAX_N_POINTERS);
+ node->block= new_block;
+#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ node->data= new_data;
+
+ return true;
+ }
+
+ return false;
+}
+
+#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+#else
+# define ha_insert_for_fold(t,h,f,b,d) ha_insert_for_fold(t,h,f,d)
+# define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \
+ ha_search_and_update_if_found(table,fold,data,new_data)
+#endif
+
/** Updates a hash node reference when it has been unsuccessfully used in a
search which could have succeeded with the used hash parameters. This can
happen because when building a hash index for a page, we do not check
@@ -615,8 +712,8 @@ btr_search_update_hash_ref(
ut_ad(block->page.id().space() == index->table->space_id);
ut_ad(index == cursor->index);
ut_ad(!dict_index_is_ibuf(index));
- rw_lock_t* const latch = btr_get_search_latch(index);
- rw_lock_x_lock(latch);
+ auto part = btr_search_sys.get_part(*index);
+ rw_lock_x_lock(&part->latch);
ut_ad(!block->index || block->index == index);
if (block->index
@@ -644,14 +741,13 @@ btr_search_update_hash_ref(
mem_heap_free(heap);
}
- ha_insert_for_fold(btr_get_search_table(index), fold,
- block, rec);
+ ha_insert_for_fold(&part->table, heap, fold, block, rec);
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
}
func_exit:
- rw_lock_x_unlock(latch);
+ rw_lock_x_unlock(&part->latch);
}
/** Checks if a guessed position for a tree cursor is right. Note that if
@@ -926,7 +1022,8 @@ btr_search_guess_on_hash(
}
ut_ad(!index->is_ibuf());
- ut_ad(!ahi_latch || ahi_latch == btr_get_search_latch(index));
+ ut_ad(!ahi_latch
+ || ahi_latch == &btr_search_sys.get_part(*index)->latch);
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
compile_time_assert(ulint{BTR_SEARCH_LEAF} == ulint{RW_S_LATCH});
@@ -959,11 +1056,11 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
- rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index);
+ auto part = btr_search_sys.get_part(*index);
const rec_t* rec;
- if (use_latch) {
- rw_lock_s_lock(use_latch);
+ if (!ahi_latch) {
+ rw_lock_s_lock(&part->latch);
if (!btr_search_enabled) {
goto fail;
@@ -974,12 +1071,12 @@ btr_search_guess_on_hash(
}
rec = static_cast<const rec_t*>(
- ha_search_and_get_data(btr_get_search_table(index), fold));
+ ha_search_and_get_data(&part->table, fold));
if (!rec) {
- if (use_latch) {
+ if (!ahi_latch) {
fail:
- rw_lock_s_unlock(use_latch);
+ rw_lock_s_unlock(&part->latch);
}
btr_search_failure(info, cursor);
@@ -988,7 +1085,7 @@ fail:
buf_block_t* block = buf_pool.block_from_ahi(rec);
- if (use_latch) {
+ if (!ahi_latch) {
rw_lock_t* hash_lock = buf_pool.hash_lock_get(
block->page.id());
rw_lock_s_lock(hash_lock);
@@ -1032,7 +1129,7 @@ got_no_latch:
buf_pool.stat.n_page_gets++;
- rw_lock_s_unlock(use_latch);
+ rw_lock_s_unlock(&part->latch);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
if (UNIV_UNLIKELY(fail)) {
@@ -1149,7 +1246,6 @@ void btr_search_drop_page_hash_index(buf_block_t* block)
ulint i;
mem_heap_t* heap;
rec_offs* offsets;
- rw_lock_t* latch;
retry:
/* This debug check uses a dirty read that could theoretically cause
@@ -1175,17 +1271,15 @@ retry:
const index_id_t index_id
= btr_page_get_index_id(block->frame);
- const ulint ahi_slot
- = ut_fold_ulint_pair(static_cast<ulint>(index_id),
- block->page.id().space())
- % btr_ahi_parts;
- latch = btr_search_latches[ahi_slot];
- rw_lock_s_lock(latch);
+ auto part = btr_search_sys.get_part(index_id,
+ block->page.id().space());
+
+ rw_lock_s_lock(&part->latch);
assert_block_ahi_valid(block);
if (!block->index || !btr_search_enabled) {
- rw_lock_s_unlock(latch);
+ rw_lock_s_unlock(&part->latch);
return;
}
@@ -1225,7 +1319,7 @@ retry:
/* NOTE: The AHI fields of block must not be accessed after
releasing search latch, as the index page might only be s-latched! */
- rw_lock_s_unlock(latch);
+ rw_lock_s_unlock(&part->latch);
ut_a(n_fields > 0 || n_bytes > 0);
@@ -1276,7 +1370,7 @@ next_rec:
mem_heap_free(heap);
}
- rw_lock_x_lock(latch);
+ rw_lock_x_lock(&part->latch);
if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
@@ -1292,17 +1386,15 @@ next_rec:
/* Someone else has meanwhile built a new hash index on the
page, with different parameters */
- rw_lock_x_unlock(latch);
+ rw_lock_x_unlock(&part->latch);
ut_free(folds);
goto retry;
}
for (i = 0; i < n_cached; i++) {
-
- ha_remove_all_nodes_to_page(
- btr_search_sys->hash_tables[ahi_slot],
- folds[i], page);
+ ha_remove_all_nodes_to_page(&part->table, part->heap,
+ folds[i], page);
}
switch (index->search_info->ref_count--) {
@@ -1321,7 +1413,7 @@ next_rec:
cleanup:
assert_block_ahi_valid(block);
- rw_lock_x_unlock(latch);
+ rw_lock_x_unlock(&part->latch);
ut_free(folds);
}
@@ -1397,7 +1489,6 @@ btr_search_build_page_hash_index(
ulint n_recs;
ulint* folds;
const rec_t** recs;
- ulint i;
mem_heap_t* heap = NULL;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_;
@@ -1410,7 +1501,7 @@ btr_search_build_page_hash_index(
}
rec_offs_init(offsets_);
- ut_ad(ahi_latch == btr_get_search_latch(index));
+ ut_ad(ahi_latch == &btr_search_sys.get_part(*index)->latch);
ut_ad(index);
ut_ad(block->page.id().space() == index->table->space_id);
ut_ad(!dict_index_is_ibuf(index));
@@ -1534,20 +1625,12 @@ btr_search_build_page_hash_index(
btr_search_check_free_space_in_heap(index);
- hash_table_t* table = btr_get_search_table(index);
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto exit_func;
}
- table = btr_get_search_table(index);
- if (block->index && ((block->curr_n_fields != n_fields)
- || (block->curr_n_bytes != n_bytes)
- || (block->curr_left_side != left_side))) {
- goto exit_func;
- }
-
/* This counter is decremented every time we drop page
hash index entries and is incremented here. Since we can
rebuild hash index for a page that is already hashed, we
@@ -1556,6 +1639,10 @@ btr_search_build_page_hash_index(
if (!block->index) {
assert_block_ahi_empty(block);
index->search_info->ref_count++;
+ } else if (block->curr_n_fields != n_fields
+ || block->curr_n_bytes != n_bytes
+ || block->curr_left_side != left_side) {
+ goto exit_func;
}
block->n_hash_helps = 0;
@@ -1565,9 +1652,13 @@ btr_search_build_page_hash_index(
block->curr_left_side = left_side;
block->index = index;
- for (i = 0; i < n_cached; i++) {
-
- ha_insert_for_fold(table, folds[i], block, recs[i]);
+ {
+ auto part = btr_search_sys.get_part(*index);
+ for (ulint i = 0; i < n_cached; i++) {
+ ha_insert_for_fold(&part->table, part->heap,
+ folds[i], block, recs[i]);
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
+ }
}
MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);
@@ -1589,8 +1680,8 @@ exit_func:
void
btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor)
{
- rw_lock_t* ahi_latch = btr_get_search_latch(cursor->index);
-
+ rw_lock_t* ahi_latch = &btr_search_sys.get_part(*cursor->index)
+ ->latch;
ut_ad(!rw_lock_own_flagged(ahi_latch,
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
@@ -1659,7 +1750,9 @@ btr_search_move_or_delete_hash_entries(
assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block);
- rw_lock_t* ahi_latch = index ? btr_get_search_latch(index) : NULL;
+ rw_lock_t* ahi_latch = index
+ ? &btr_search_sys.get_part(*index)->latch
+ : nullptr;
if (new_block->index) {
btr_search_drop_page_hash_index(block);
@@ -1745,27 +1838,25 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor)
mem_heap_free(heap);
}
- rw_lock_t* ahi_latch = btr_get_search_latch(index);
+ auto part = btr_search_sys.get_part(*index);
- rw_lock_x_lock(ahi_latch);
+ rw_lock_x_lock(&part->latch);
assert_block_ahi_valid(block);
- if (btr_search_enabled) {
- hash_table_t* table = btr_get_search_table(index);
- if (block->index) {
- ut_a(block->index == index);
-
- if (ha_search_and_delete_if_found(table, fold, rec)) {
- MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVED);
- } else {
- MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND);
- }
+ if (block->index && btr_search_enabled) {
+ ut_a(block->index == index);
- assert_block_ahi_valid(block);
+ if (ha_search_and_delete_if_found(&part->table, part->heap,
+ fold, rec)) {
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVED);
+ } else {
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND);
}
+
+ assert_block_ahi_valid(block);
}
- rw_lock_x_unlock(ahi_latch);
+ rw_lock_x_unlock(&part->latch);
}
/** Updates the page hash index when a single record is inserted on a page.
@@ -1776,12 +1867,11 @@ void btr_search_update_hash_on_delete(btr_cur_t* cursor)
void
btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
{
- hash_table_t* table;
buf_block_t* block;
dict_index_t* index;
rec_t* rec;
- ut_ad(ahi_latch == btr_get_search_latch(cursor->index));
+ ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
#ifdef MYSQL_INDEX_DISABLE_AHI
@@ -1820,10 +1910,9 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
&& (cursor->n_bytes == block->curr_n_bytes)
&& !block->curr_left_side) {
- table = btr_get_search_table(index);
-
if (ha_search_and_update_if_found(
- table, cursor->fold, rec, block,
+ &btr_search_sys.get_part(*cursor->index)->table,
+ cursor->fold, rec, block,
page_rec_get_next(rec))) {
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED);
}
@@ -1847,7 +1936,7 @@ func_exit:
void
btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
{
- hash_table_t* table;
+ btr_search_sys_t::partition* part;
buf_block_t* block;
dict_index_t* index;
const rec_t* rec;
@@ -1863,7 +1952,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
- ut_ad(ahi_latch == btr_get_search_latch(cursor->index));
+ ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
@@ -1932,8 +2021,10 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
goto function_exit;
}
- table = btr_get_search_table(index);
- ha_insert_for_fold(table, ins_fold, block, ins_rec);
+ part = btr_search_sys.get_part(*index);
+ ha_insert_for_fold(&part->table, part->heap,
+ ins_fold, block, ins_rec);
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
}
goto check_next_rec;
@@ -1948,14 +2039,17 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
if (!btr_search_enabled || !block->index) {
goto function_exit;
}
- table = btr_get_search_table(index);
+ part = btr_search_sys.get_part(*index);
}
if (!left_side) {
- ha_insert_for_fold(table, fold, block, rec);
+ ha_insert_for_fold(&part->table, part->heap,
+ fold, block, rec);
} else {
- ha_insert_for_fold(table, ins_fold, block, ins_rec);
+ ha_insert_for_fold(&part->table, part->heap,
+ ins_fold, block, ins_rec);
}
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
}
check_next_rec:
@@ -1969,10 +2063,12 @@ check_next_rec:
if (!btr_search_enabled || !block->index) {
goto function_exit;
}
- table = btr_get_search_table(index);
+ part = btr_search_sys.get_part(*index);
}
- ha_insert_for_fold(table, ins_fold, block, ins_rec);
+ ha_insert_for_fold(&part->table, part->heap,
+ ins_fold, block, ins_rec);
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
}
goto function_exit;
@@ -1986,14 +2082,17 @@ check_next_rec:
if (!btr_search_enabled || !block->index) {
goto function_exit;
}
- table = btr_get_search_table(index);
+ part = btr_search_sys.get_part(*index);
}
if (!left_side) {
- ha_insert_for_fold(table, ins_fold, block, ins_rec);
+ ha_insert_for_fold(&part->table, part->heap,
+ ins_fold, block, ins_rec);
} else {
- ha_insert_for_fold(table, next_fold, block, next_rec);
+ ha_insert_for_fold(&part->table, part->heap,
+ next_fold, block, next_rec);
}
+ MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
}
function_exit:
@@ -2007,6 +2106,31 @@ function_exit:
}
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+__attribute__((nonnull))
+/** @return whether a range of the cells is valid */
+static bool ha_validate(const hash_table_t *table,
+ ulint start_index, ulint end_index)
+{
+ ut_a(start_index <= end_index);
+ ut_a(end_index < table->n_cells);
+
+ bool ok= true;
+
+ for (ulint i= start_index; i <= end_index; i++)
+ {
+ for (auto node= static_cast<const ha_node_t*>(table->array[i].node); node;
+ node= node->next)
+ {
+ if (table->calc_hash(node->fold) != i) {
+ ib::error() << "Hash table node fold value " << node->fold
+ << " does not match the cell number " << i;
+ ok= false;
+ }
+ }
+ }
+
+ return ok;
+}
/** Validates the search system for given hash table.
@param[in] hash_table_id hash table to validate
@@ -2037,8 +2161,9 @@ btr_search_hash_table_validate(ulint hash_table_id)
mutex_enter(&buf_pool.mutex);
- cell_count = hash_get_n_cells(
- btr_search_sys->hash_tables[hash_table_id]);
+ auto &part = btr_search_sys.parts[hash_table_id];
+
+ cell_count = hash_get_n_cells(&part.table);
for (i = 0; i < cell_count; i++) {
/* We release search latches every once in a while to
@@ -2059,8 +2184,7 @@ btr_search_hash_table_validate(ulint hash_table_id)
mutex_enter(&buf_pool.mutex);
- ulint curr_cell_count = hash_get_n_cells(
- btr_search_sys->hash_tables[hash_table_id]);
+ ulint curr_cell_count = hash_get_n_cells(&part.table);
if (cell_count != curr_cell_count) {
@@ -2072,8 +2196,7 @@ btr_search_hash_table_validate(ulint hash_table_id)
}
}
- node = (ha_node_t*) hash_get_nth_cell(
- btr_search_sys->hash_tables[hash_table_id], i)->node;
+ node = (ha_node_t*) hash_get_nth_cell(&part.table, i)->node;
for (; node != NULL; node = node->next) {
const buf_block_t* block
@@ -2169,8 +2292,7 @@ state_ok:
mutex_enter(&buf_pool.mutex);
- ulint curr_cell_count = hash_get_n_cells(
- btr_search_sys->hash_tables[hash_table_id]);
+ ulint curr_cell_count = hash_get_n_cells(&part.table);
if (cell_count != curr_cell_count) {
@@ -2184,8 +2306,7 @@ state_ok:
ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1);
- if (!ha_validate(btr_search_sys->hash_tables[hash_table_id],
- i, end_index)) {
+ if (!ha_validate(&part.table, i, end_index)) {
ok = FALSE;
}
}
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 1eb28db37a2..84e8bb0e1c6 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1552,7 +1552,7 @@ bool buf_pool_t::create()
chunk_t::map_ref= chunk_t::map_reg;
buf_LRU_old_ratio_update(100 * 3 / 8, false);
- btr_search_sys_create(srv_buf_pool_curr_size / sizeof(void*) / 64);
+ btr_search_sys_create();
ut_ad(is_initialised());
return false;
}
diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc
deleted file mode 100644
index f0b5fb672cd..00000000000
--- a/storage/innobase/ha/ha0ha.cc
+++ /dev/null
@@ -1,361 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2020, MariaDB Corporation.
-
-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, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/********************************************************************//**
-@file ha/ha0ha.cc
-The hash table with external chains
-
-Created 8/22/1994 Heikki Tuuri
-*************************************************************************/
-
-#include "ha0ha.h"
-
-#ifdef UNIV_DEBUG
-# include "buf0buf.h"
-#endif /* UNIV_DEBUG */
-#include "btr0sea.h"
-#include "page0page.h"
-
-#ifdef BTR_CUR_HASH_ADAPT
-# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
-/** Maximum number of records in a page */
-static const ulint MAX_N_POINTERS
- = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES;
-# endif /* 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. If btr_search_enabled is set to FALSE, we will only allow
-updating existing nodes, but no new node is allowed to be added.
-@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 */
-{
- hash_cell_t* cell;
- ha_node_t* node;
- ha_node_t* prev_node;
- ulint hash;
-
- ut_ad(data);
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(table->heap->type & MEM_HEAP_BTR_SEARCH);
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- ut_a(block->frame == page_align(data));
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- ut_ad(btr_search_enabled);
-
- hash = hash_calc_hash(fold, table);
-
- cell = hash_get_nth_cell(table, hash);
-
- prev_node = static_cast<ha_node_t*>(cell->node);
-
- while (prev_node != NULL) {
- if (prev_node->fold == fold) {
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- if (table->adaptive) {
- buf_block_t* prev_block = prev_node->block;
- ut_a(prev_block->frame
- == page_align(prev_node->data));
- ut_a(prev_block->n_pointers-- < MAX_N_POINTERS);
- ut_a(block->n_pointers++ < MAX_N_POINTERS);
- }
-
- prev_node->block = block;
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- prev_node->data = data;
-
- return(TRUE);
- }
-
- prev_node = prev_node->next;
- }
-
- /* We have to allocate a new chain node */
- node = static_cast<ha_node_t*>(
- mem_heap_alloc(table->heap, sizeof(ha_node_t)));
-
- if (node == NULL) {
- /* It was a btr search type memory heap and at the moment
- no more memory could be allocated: return */
- return(FALSE);
- }
-
- ha_node_set_data(node, block, data);
-
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- if (table->adaptive) {
- ut_a(block->n_pointers++ < MAX_N_POINTERS);
- }
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-
- node->fold = fold;
-
- node->next = NULL;
-
- prev_node = static_cast<ha_node_t*>(cell->node);
-
- if (prev_node == NULL) {
-
- cell->node = node;
-
- return(TRUE);
- }
-
- while (prev_node->next != NULL) {
-
- prev_node = prev_node->next;
- }
-
- prev_node->next = node;
-
- return(TRUE);
-}
-
-#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)
-{
- ulint i;
- for (i = 0; i < btr_ahi_parts; ++i) {
- if (btr_search_sys->hash_tables[i] == table) {
- break;
- }
- }
-
- ut_ad(i < btr_ahi_parts);
- ut_ad(rw_lock_own(btr_search_latches[i], RW_LOCK_X));
-}
-#endif /* UNIV_DEBUG */
-
-/***********************************************************//**
-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 */
-{
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_d(ha_btr_search_latch_x_locked(table));
- ut_ad(btr_search_enabled);
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- ut_a(table->adaptive);
- ut_a(del_node->block->frame == page_align(del_node->data));
- ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS);
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-
- ha_node_t* node;
-
- const ulint fold = del_node->fold;
-
- HASH_DELETE(ha_node_t, next, table, fold, del_node);
-
- ha_node_t* top_node = (ha_node_t*) mem_heap_get_top(table->heap,
- sizeof(ha_node_t));
-
- /* If the node to remove is not the top node in the heap, compact the
- heap of nodes by moving the top node in the place of del_node. */
-
- if (del_node != top_node) {
- /* Copy the top node in place of del_node */
-
- *del_node = *top_node;
-
- hash_cell_t* cell = hash_get_nth_cell(
- table, hash_calc_hash(top_node->fold, table));
-
- /* Look for the pointer to the top node, to update it */
-
- if (cell->node == top_node) {
- /* The top node is the first in the chain */
- cell->node = del_node;
- } else {
- /* We have to look for the predecessor */
- node = static_cast<ha_node_t*>(cell->node);
-
- while (top_node != HASH_GET_NEXT(next, node)) {
- node = static_cast<ha_node_t*>(
- HASH_GET_NEXT(next, node));
- }
-
- /* Now we have the predecessor node */
- node->next = del_node;
- }
- }
-
- /* Free the space occupied by the top node */
-
- mem_heap_free_top(table->heap, sizeof(ha_node_t));
-}
-
-/*********************************************************//**
-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 */
-{
- ha_node_t* node;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- ut_a(new_block->frame == page_align(new_data));
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-
- ut_d(ha_btr_search_latch_x_locked(table));
-
- if (!btr_search_enabled) {
- return(FALSE);
- }
-
- node = ha_search_with_data(table, fold, data);
-
- if (node) {
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- if (table->adaptive) {
- ut_a(node->block->n_pointers-- < MAX_N_POINTERS);
- ut_a(new_block->n_pointers++ < MAX_N_POINTERS);
- }
-
- node->block = new_block;
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
- node->data = new_data;
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*****************************************************************//**
-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 */
-{
- ha_node_t* node;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(btr_search_enabled);
- ut_d(ha_btr_search_latch_x_locked(table));
-
- node = ha_chain_get_first(table, fold);
-
- while (node) {
- if (page_align(ha_node_get_data(node)) == page) {
-
- /* Remove the hash node */
-
- ha_delete_hash_node(table, node);
-
- /* Start again from the first node in the chain
- because the deletion may compact the heap of
- nodes and move other nodes! */
-
- node = ha_chain_get_first(table, fold);
- } else {
- node = ha_chain_get_next(node);
- }
- }
-#ifdef UNIV_DEBUG
- /* Check that all nodes really got deleted */
-
- node = ha_chain_get_first(table, fold);
-
- while (node) {
- ut_a(page_align(ha_node_get_data(node)) != page);
-
- node = ha_chain_get_next(node);
- }
-#endif /* UNIV_DEBUG */
-}
-
-#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 */
-{
- ibool ok = TRUE;
- ulint i;
-
- ut_ad(table);
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_a(start_index <= end_index);
- ut_a(start_index < hash_get_n_cells(table));
- 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);
-
- for (node = static_cast<ha_node_t*>(cell->node);
- node != 0;
- node = node->next) {
-
- if (hash_calc_hash(node->fold, table) != i) {
- ib::error() << "Hash table node fold value "
- << node->fold << " does not match the"
- " cell number " << i << ".";
-
- ok = FALSE;
- }
- }
- }
-
- return(ok);
-}
-#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
-#endif /* BTR_CUR_HASH_ADAPT */
diff --git a/storage/innobase/ha/hash0hash.cc b/storage/innobase/ha/hash0hash.cc
index 6a8c84a349d..37e5bc4dea7 100644
--- a/storage/innobase/ha/hash0hash.cc
+++ b/storage/innobase/ha/hash0hash.cc
@@ -28,20 +28,23 @@ Created 5/20/1997 Heikki Tuuri
#include "mem0mem.h"
#include "sync0sync.h"
+/** Create the hash table.
+@param n the lower bound of n_cells */
+void hash_table_t::create(ulint n)
+{
+ n_cells= ut_find_prime(n);
+ array= static_cast<hash_cell_t*>(ut_zalloc_nokey(n_cells * sizeof *array));
+}
+
/**
Create a hash table.
@param n the minimum number of hash array elements
@return created table (with n_cells being a prime, at least n) */
hash_table_t *hash_create(ulint n)
{
- ulint prime= ut_find_prime(n);
-
hash_table_t *table= static_cast<hash_table_t*>
(ut_zalloc_nokey(sizeof *table));
- table->array= static_cast<hash_cell_t*>(ut_zalloc_nokey(sizeof(hash_cell_t) *
- prime));
- table->n_cells= prime;
- ut_d(table->magic_n= HASH_TABLE_MAGIC_N);
+ table->create(n);
return table;
}
@@ -52,8 +55,6 @@ hash_table_free(
/*============*/
hash_table_t* table) /*!< in, own: hash table */
{
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
-
ut_free(table->array);
ut_free(table);
}
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<ulong>(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<partition*>(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",
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index d56985a0a2e..77a043acccc 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -3823,7 +3823,7 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(dict_index_is_clust(index));
ut_ad(!prebuilt->templ_contains_blob);
- rw_lock_t* ahi_latch = btr_get_search_latch(index);
+ rw_lock_t* ahi_latch = btr_search_sys.get_latch(*index);
rw_lock_s_lock(ahi_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index ab0bf1164ee..84f91048068 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -965,29 +965,16 @@ srv_printf_innodb_monitor(
ibuf_print(file);
#ifdef BTR_CUR_HASH_ADAPT
- btr_search_x_lock_all();
for (ulint i = 0; i < btr_ahi_parts && btr_search_enabled; ++i) {
- const hash_table_t* table = btr_search_sys->hash_tables[i];
-
- ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
- ut_ad(table->heap->type == MEM_HEAP_FOR_BTR_SEARCH);
-
- const mem_heap_t* heap = table->heap;
- /* The heap may change during the following call,
- so the data displayed may be garbage. We intentionally
- avoid acquiring btr_search_latches[] so that the
- diagnostic output will not stop here even in case another
- thread hangs while holding btr_search_latches[].
-
- This should be safe from crashes, because
- table->heap will be pointing to the same object
- for the full lifetime of the server. Even during
- btr_search_disable() the heap will stay valid. */
+ const auto part= &btr_search_sys.parts[i];
+ rw_lock_s_lock(&part->latch);
+ ut_ad(part->heap->type == MEM_HEAP_FOR_BTR_SEARCH);
fprintf(file, "Hash table size " ULINTPF
", node heap has " ULINTPF " buffer(s)\n",
- table->n_cells, heap->base.count - !heap->free_block);
+ part->table.n_cells,
+ part->heap->base.count - !part->heap->free_block);
+ rw_lock_s_unlock(&part->latch);
}
- btr_search_x_unlock_all();
fprintf(file,
"%.2f hash searches/s, %.2f non-hash searches/s\n",
@@ -1126,22 +1113,15 @@ srv_export_innodb_status(void)
#ifdef BTR_CUR_HASH_ADAPT
ulint mem_adaptive_hash = 0;
for (ulong i = 0; i < btr_ahi_parts; i++) {
- rw_lock_s_lock(btr_search_latches[i]);
- if (!btr_search_sys->hash_tables) {
-next:
- rw_lock_s_unlock(btr_search_latches[i]);
- continue;
- }
-
- hash_table_t* ht = btr_search_sys->hash_tables[i];
+ const auto part= &btr_search_sys.parts[i];
+ rw_lock_s_lock(&part->latch);
+ if (part->heap) {
+ ut_ad(part->heap->type == MEM_HEAP_FOR_BTR_SEARCH);
- ut_ad(ht);
- ut_ad(ht->heap);
- ut_ad(ht->heap->type == MEM_HEAP_FOR_BTR_SEARCH);
-
- mem_adaptive_hash += mem_heap_get_size(ht->heap)
- + ht->n_cells * sizeof(hash_cell_t);
- goto next;
+ mem_adaptive_hash += mem_heap_get_size(part->heap)
+ + part->table.n_cells * sizeof(hash_cell_t);
+ }
+ rw_lock_s_unlock(&part->latch);
}
export_vars.innodb_mem_adaptive_hash = mem_adaptive_hash;
#endif
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 3fe78bc1909..5dbf01c6b49 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2127,9 +2127,6 @@ void innodb_shutdown()
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
ut_ad(lock_sys.is_initialised() || !srv_was_started);
ut_ad(log_sys.is_initialised() || !srv_was_started);
-#ifdef BTR_CUR_HASH_ADAPT
- ut_ad(btr_search_sys || !srv_was_started);
-#endif /* BTR_CUR_HASH_ADAPT */
ut_ad(ibuf.index || !srv_was_started);
dict_stats_deinit();