Commit 0664d633 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-14952 Avoid repeated calls to btr_get_search_latch()

btr_cur_search_to_nth_level(), btr_search_guess_on_hash(),
btr_pcur_open_with_no_init_func(), row_sel_open_pcur():
Replace the parameter has_search_latch with the ahi_latch
(passed as NULL if the caller does not hold the latch).

btr_search_update_hash_node_on_insert(),
btr_search_update_hash_on_insert(),
btr_search_build_page_hash_index(): Add the parameter ahi_latch.

btr_search_x_lock(), btr_search_x_unlock(),
btr_search_s_lock(), btr_search_s_unlock(): Remove.
parent 4beb699a
......@@ -919,8 +919,7 @@ search tuple should be performed in the B-tree. InnoDB does an insert
immediately after the cursor. Thus, the cursor may end up on a user record,
or on a page infimum record. */
dberr_t
btr_cur_search_to_nth_level(
/*========================*/
btr_cur_search_to_nth_level_func(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
......@@ -935,17 +934,16 @@ btr_cur_search_to_nth_level(
cursor->left_block is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch
is != 0, we maybe do not have a latch set
on the cursor page, we assume
the caller uses his search latch
to protect the record! */
NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch
protects the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */
ulint has_search_latch,
/*!< in: info on the latch mode the
caller currently has on search system:
RW_S_LATCH, or 0 */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: currently held btr_search_latch
(in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in: mtr */
......@@ -1123,7 +1121,7 @@ btr_cur_search_to_nth_level(
&& mode != PAGE_CUR_LE_OR_EXTENDS
# endif /* PAGE_CUR_LE_OR_EXTENDS */
&& !dict_index_is_spatial(index)
/* If !has_search_latch, we do a dirty read of
/* If !ahi_latch, we do a dirty read of
btr_search_enabled below, and btr_search_guess_on_hash()
will have to check it again. */
&& btr_search_enabled
......@@ -1131,7 +1129,7 @@ btr_cur_search_to_nth_level(
&& !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)
&& btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor,
has_search_latch, mtr)) {
ahi_latch, mtr)) {
/* Search using the hash index succeeded */
......@@ -1152,10 +1150,12 @@ btr_cur_search_to_nth_level(
/* If the hash search did not succeed, do binary search down the
tree */
if (has_search_latch) {
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
/* Release possible search latch to obey latching order */
btr_search_s_unlock(index);
rw_lock_s_unlock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
/* Store the position of the tree latch we push to mtr so that we
know how to release it when we have latched leaf node(s) */
......@@ -2222,15 +2222,17 @@ btr_cur_search_to_nth_level(
ut_free(prev_tree_savepoints);
}
if (has_search_latch) {
btr_search_s_lock(index);
}
if (mbr_adj) {
/* remember that we will need to adjust parent MBR */
cursor->rtr_info->mbr_adj = true;
}
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
rw_lock_s_lock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
DBUG_RETURN(err);
}
......@@ -3300,10 +3302,14 @@ btr_cur_optimistic_insert(
ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW);
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(cursor);
} else {
btr_search_update_hash_on_insert(cursor);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(
cursor, ahi_latch);
} else {
btr_search_update_hash_on_insert(cursor, ahi_latch);
}
}
#endif /* BTR_CUR_HASH_ADAPT */
......@@ -3509,7 +3515,8 @@ btr_cur_pessimistic_insert(
ut_ad((flags & ~BTR_KEEP_IBUF_BITMAP)
== BTR_NO_LOCKING_FLAG);
} else {
btr_search_update_hash_on_insert(cursor);
btr_search_update_hash_on_insert(
cursor, btr_get_search_latch(index));
}
#endif /* BTR_CUR_HASH_ADAPT */
if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) {
......
......@@ -353,7 +353,11 @@ btr_pcur_restore_position_func(
}
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
cursor, 0, file, line, mtr);
cursor,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
/* Restore the old search mode */
cursor->search_mode = old_mode;
......
......@@ -48,7 +48,7 @@ Search system is protected by array of latches. */
char btr_search_enabled = true;
/** Number of adaptive hash index partition. */
ulong btr_ahi_parts = 8;
ulong btr_ahi_parts;
#ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */
......@@ -177,23 +177,6 @@ btr_search_get_n_fields(
return(btr_search_get_n_fields(cursor->n_fields, cursor->n_bytes));
}
/********************************************************************//**
Builds a hash index on a page with the given parameters. If the page already
has a hash index with different parameters, the old hash index is removed.
If index is non-NULL, this function checks if n_fields and n_bytes are
sensible values, and does not build a hash index if not. */
static
void
btr_search_build_page_hash_index(
/*=============================*/
dict_index_t* index, /*!< in: index for which to build, or NULL if
not known */
buf_block_t* block, /*!< in: index page, s- or x-latched */
ulint n_fields,/*!< in: hash this many full fields */
ulint n_bytes,/*!< in: hash this many bytes from the next
field */
ibool left_side);/*!< in: hash for searches from left side? */
/** This function should be called before reserving any btr search mutex, if
the intended operation might add nodes to the search system hash table.
Because of the latching order, once we have reserved the btr search system
......@@ -224,8 +207,9 @@ btr_search_check_free_space_in_heap(dict_index_t* index)
if (heap->free_block == NULL) {
buf_block_t* block = buf_block_alloc(NULL);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
btr_search_x_lock(index);
rw_lock_x_lock(ahi_latch);
if (btr_search_enabled
&& heap->free_block == NULL) {
......@@ -234,7 +218,7 @@ btr_search_check_free_space_in_heap(dict_index_t* index)
buf_block_free(block);
}
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
}
}
......@@ -457,12 +441,10 @@ btr_search_info_get_ref_count(
ut_ad(info);
ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_S));
ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_X));
btr_search_s_lock(index);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch);
ret = info->ref_count;
btr_search_s_unlock(index);
rw_lock_s_unlock(ahi_latch);
return(ret);
}
......@@ -723,61 +705,6 @@ btr_search_update_hash_ref(
}
}
/** Updates the search info.
@param[in,out] info search info
@param[in] cursor cursor which was just positioned */
void
btr_search_info_update_slow(
btr_search_t* info,
btr_cur_t* cursor)
{
buf_block_t* block;
ibool build_index;
ut_ad(!rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_S));
ut_ad(!rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X));
block = btr_cur_get_block(cursor);
/* NOTE that the following two function calls do NOT protect
info or block->n_fields etc. with any semaphore, to save CPU time!
We cannot assume the fields are consistent when we return from
those functions! */
btr_search_info_update_hash(info, cursor);
build_index = btr_search_update_block_hash_info(info, block, cursor);
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index);
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_hash_fail++;
#endif /* UNIV_SEARCH_PERF_STAT */
btr_search_x_lock(cursor->index);
btr_search_update_hash_ref(info, block, cursor);
btr_search_x_unlock(cursor->index);
}
if (build_index) {
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
btr_search_build_page_hash_index(cursor->index, block,
block->n_fields,
block->n_bytes,
block->left_side);
}
}
/** Checks if a guessed position for a tree cursor is right. Note that if
mode is PAGE_CUR_LE, which is used in inserts, and the function returns
TRUE, then cursor->up_match and cursor->low_match both have sensible values.
......@@ -947,12 +874,11 @@ both have sensible values.
we assume the caller uses his search latch
to protect the record!
@param[out] cursor tree cursor
@param[in] has_search_latch
latch mode the caller currently has on
search system: RW_S/X_LATCH or 0
@param[in] ahi_latch the adaptive hash index latch being held,
or NULL
@param[in] mtr mini transaction
@return TRUE if succeeded */
ibool
@return whether the search succeeded */
bool
btr_search_guess_on_hash(
dict_index_t* index,
btr_search_t* info,
......@@ -960,7 +886,7 @@ btr_search_guess_on_hash(
ulint mode,
ulint latch_mode,
btr_cur_t* cursor,
ulint has_search_latch,
rw_lock_t* ahi_latch,
mtr_t* mtr)
{
const rec_t* rec;
......@@ -970,6 +896,8 @@ btr_search_guess_on_hash(
btr_cur_t cursor2;
btr_pcur_t pcur;
#endif
ut_ad(!ahi_latch || rw_lock_own(ahi_latch, RW_LOCK_S)
|| rw_lock_own(ahi_latch, RW_LOCK_X));
if (!btr_search_enabled) {
return(FALSE);
......@@ -977,6 +905,7 @@ btr_search_guess_on_hash(
ut_ad(index && info && tuple && cursor && mtr);
ut_ad(!dict_index_is_ibuf(index));
ut_ad(!ahi_latch || ahi_latch == btr_get_search_latch(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
......@@ -1009,16 +938,16 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
if (!has_search_latch) {
btr_search_s_lock(index);
rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index);
if (!btr_search_enabled) {
btr_search_s_unlock(index);
btr_search_failure(info, cursor);
if (use_latch) {
rw_lock_s_lock(use_latch);
return(FALSE);
if (!btr_search_enabled) {
goto fail;
}
} else {
ut_ad(btr_search_enabled);
}
ut_ad(rw_lock_own(btr_get_search_latch(index), RW_LOCK_S));
......@@ -1027,9 +956,9 @@ btr_search_guess_on_hash(
btr_get_search_table(index), fold);
if (rec == NULL) {
if (!has_search_latch) {
btr_search_s_unlock(index);
if (use_latch) {
fail:
rw_lock_s_unlock(use_latch);
}
btr_search_failure(info, cursor);
......@@ -1039,22 +968,15 @@ btr_search_guess_on_hash(
buf_block_t* block = buf_block_from_ahi(rec);
if (!has_search_latch) {
if (use_latch) {
if (!buf_page_get_known_nowait(
latch_mode, block, BUF_MAKE_YOUNG,
__FILE__, __LINE__, mtr)) {
if (!has_search_latch) {
btr_search_s_unlock(index);
}
btr_search_failure(info, cursor);
return(FALSE);
goto fail;
}
btr_search_s_unlock(index);
rw_lock_s_unlock(use_latch);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
}
......@@ -1063,7 +985,7 @@ btr_search_guess_on_hash(
ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH);
if (!has_search_latch) {
if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr);
}
......@@ -1085,11 +1007,9 @@ btr_search_guess_on_hash(
record to determine if our guess for the cursor position is
right. */
if (index_id != btr_page_get_index_id(block->frame)
|| !btr_search_check_guess(cursor,
has_search_latch,
tuple, mode)) {
|| !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) {
if (!has_search_latch) {
if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr);
}
......@@ -1110,7 +1030,7 @@ btr_search_guess_on_hash(
info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */
ut_ad(!has_search_latch);
ut_ad(!ahi_latch);
btr_leaf_page_release(block, latch_mode, mtr);
......@@ -1143,7 +1063,7 @@ btr_search_guess_on_hash(
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++;
#endif
if (!has_search_latch && buf_page_peek_if_too_old(&block->page)) {
if (!ahi_latch && buf_page_peek_if_too_old(&block->page)) {
buf_page_make_young(&block->page);
}
......@@ -1191,6 +1111,8 @@ btr_search_drop_page_hash_index(buf_block_t* block)
/* This debug check uses a dirty read that could theoretically cause
false positives while buf_pool_clear_hash_index() is executing. */
assert_block_ahi_valid(block);
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
if (index == NULL) {
return;
......@@ -1214,9 +1136,6 @@ btr_search_drop_page_hash_index(buf_block_t* block)
% btr_ahi_parts;
latch = btr_search_latches[ahi_slot];
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
rw_lock_s_lock(latch);
assert_block_ahi_valid(block);
......@@ -1419,6 +1338,7 @@ If index is non-NULL, this function checks if n_fields and n_bytes are
sensible, and does not build a hash index if not.
@param[in,out] index index for which to build.
@param[in,out] block index page, s-/x- latched.
@param[in,out] ahi_latch the adaptive search latch
@param[in] n_fields hash this many full fields
@param[in] n_bytes hash this many bytes of the next field
@param[in] left_side hash for searches from left side */
......@@ -1427,12 +1347,11 @@ void
btr_search_build_page_hash_index(
dict_index_t* index,
buf_block_t* block,
rw_lock_t* ahi_latch,
ulint n_fields,
ulint n_bytes,
ibool left_side)
{
hash_table_t* table;
page_t* page;
const rec_t* rec;
const rec_t* next_rec;
ulint fold;
......@@ -1454,6 +1373,7 @@ btr_search_build_page_hash_index(
}
rec_offs_init(offsets_);
ut_ad(ahi_latch == btr_get_search_latch(index));
ut_ad(index);
ut_ad(block->page.id.space() == index->space);
ut_a(!dict_index_is_ibuf(index));
......@@ -1463,20 +1383,17 @@ btr_search_build_page_hash_index(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S)
|| rw_lock_own(&(block->lock), RW_LOCK_X));
btr_search_s_lock(index);
rw_lock_s_lock(ahi_latch);
table = btr_get_search_table(index);
page = buf_block_get_frame(block);
const bool rebuild = block->index
&& (block->curr_n_fields != n_fields
|| block->curr_n_bytes != n_bytes
|| block->curr_left_side != left_side);
if (block->index && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
btr_search_s_unlock(index);
rw_lock_s_unlock(ahi_latch);
if (rebuild) {
btr_search_drop_page_hash_index(block);
} else {
btr_search_s_unlock(index);
}
/* Check that the values for hash index build are sensible */
......@@ -1491,6 +1408,7 @@ btr_search_build_page_hash_index(
return;
}
page_t* page = buf_block_get_frame(block);
n_recs = page_get_n_recs(page);
if (n_recs == 0) {
......@@ -1573,7 +1491,8 @@ btr_search_build_page_hash_index(
btr_search_check_free_space_in_heap(index);
btr_search_x_lock(index);
hash_table_t* table = btr_get_search_table(index);
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto exit_func;
......@@ -1611,7 +1530,7 @@ btr_search_build_page_hash_index(
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
exit_func:
assert_block_ahi_valid(block);
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
ut_free(folds);
ut_free(recs);
......@@ -1620,6 +1539,60 @@ btr_search_build_page_hash_index(
}
}
/** Updates the search info.
@param[in,out] info search info
@param[in,out] cursor cursor which was just positioned */
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);
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_S));
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_X));
buf_block_t* block = btr_cur_get_block(cursor);
/* NOTE that the following two function calls do NOT protect
info or block->n_fields etc. with any semaphore, to save CPU time!
We cannot assume the fields are consistent when we return from
those functions! */
btr_search_info_update_hash(info, cursor);
bool build_index = btr_search_update_block_hash_info(
info, block, cursor);
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index);
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_hash_fail++;
#endif /* UNIV_SEARCH_PERF_STAT */
rw_lock_x_lock(ahi_latch);
btr_search_update_hash_ref(info, block, cursor);
rw_lock_x_unlock(ahi_latch);
}
if (build_index) {
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
btr_search_build_page_hash_index(cursor->index, block,
ahi_latch,
block->n_fields,
block->n_bytes,
block->left_side);
}
}
/** Move or delete hash entries for moved records, usually in a page split.
If new_block is already hashed, then any hash index for block is dropped.
If new_block is not hashed, and block is hashed, then a new hash index is
......@@ -1638,19 +1611,27 @@ btr_search_move_or_delete_hash_entries(
return;
}
dict_index_t* index = block->index;
if (!index) {
index = new_block->index;
} else {
ut_ad(!new_block->index || index == new_block->index);
}
assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block);
rw_lock_t* ahi_latch = index ? btr_get_search_latch(index) : NULL;
if (new_block->index) {
btr_search_drop_page_hash_index(block);
return;
}
dict_index_t* index = block->index;
if (!index) {
return;
}
btr_search_s_lock(index);
rw_lock_s_lock(ahi_latch);
if (block->index) {
ulint n_fields = block->curr_n_fields;
......@@ -1661,19 +1642,20 @@ btr_search_move_or_delete_hash_entries(
new_block->n_bytes = block->curr_n_bytes;
new_block->left_side = left_side;
btr_search_s_unlock(index);
rw_lock_s_unlock(ahi_latch);
ut_a(n_fields > 0 || n_bytes > 0);
btr_search_build_page_hash_index(
index, new_block, n_fields, n_bytes, left_side);
index, new_block, ahi_latch,
n_fields, n_bytes, left_side);
ut_ad(n_fields == block->curr_n_fields);
ut_ad(n_bytes == block->curr_n_bytes);
ut_ad(left_side == block->curr_left_side);
return;
}
btr_search_s_unlock(index);
rw_lock_s_unlock(ahi_latch);
}
/** Updates the page hash index when a single record is deleted from a page.
......@@ -1728,7 +1710,9 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
mem_heap_free(heap);
}
btr_search_x_lock(index);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_x_lock(ahi_latch);
assert_block_ahi_valid(block);
if (block->index) {
......@@ -1744,21 +1728,25 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
assert_block_ahi_valid(block);
}
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
}
/** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the place to insert
using btr_cur_search_, and the new record has been
inserted next to the cursor. */
inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */
void
btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
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(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
#ifdef MYSQL_INDEX_DISABLE_AHI
if (cursor->index->disable_ahi) return;
#endif
......@@ -1781,8 +1769,7 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
ut_a(cursor->index == index);
ut_a(!dict_index_is_ibuf(index));
btr_search_x_lock(index);
rw_lock_x_lock(ahi_latch);
if (!block->index) {
......@@ -1806,11 +1793,11 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
func_exit:
assert_block_ahi_valid(block);
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
} else {
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
btr_search_update_hash_on_insert(cursor);
btr_search_update_hash_on_insert(cursor, ahi_latch);
}
}
......@@ -1818,9 +1805,10 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
@param[in,out] cursor cursor which was positioned to the
place to insert using btr_cur_search_...,
and the new record has been inserted next
to the cursor */
to the cursor
@param[in] ahi_latch the adaptive hash index latch */
void
btr_search_update_hash_on_insert(btr_cur_t* cursor)
btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
{
hash_table_t* table;
buf_block_t* block;
......@@ -1834,13 +1822,16 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
ulint n_fields;
ulint n_bytes;
ibool left_side;
ibool locked = FALSE;
bool locked = false;
mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
rec_offs_init(offsets_);
ut_ad(ahi_latch == btr_get_search_latch(cursor->index));
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));
#ifdef MYSQL_INDEX_DISABLE_AHI
if (cursor->index->disable_ahi) return;
#endif
......@@ -1899,10 +1890,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else {
if (left_side) {
btr_search_x_lock(index);
locked = TRUE;
locked = true;
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto function_exit;
......@@ -1917,10 +1906,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
if (fold != ins_fold) {
if (!locked) {
btr_search_x_lock(index);
locked = TRUE;
locked = true;
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto function_exit;
......@@ -1938,11 +1925,9 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
if (page_rec_is_supremum(next_rec)) {
if (!left_side) {
if (!locked) {
btr_search_x_lock(index);
locked = TRUE;
locked = true;
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto function_exit;
......@@ -1958,10 +1943,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
if (ins_fold != next_fold) {
if (!locked) {
btr_search_x_lock(index);
locked = TRUE;
locked = true;
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) {
goto function_exit;
......@@ -1980,8 +1963,9 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
mem_heap_free(heap);
}
if (locked) {
btr_search_x_unlock(index);
rw_lock_x_unlock(ahi_latch);
}
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_X));
}
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
......
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, 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
......@@ -177,8 +177,7 @@ Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
dberr_t
btr_cur_search_to_nth_level(
/*========================*/
btr_cur_search_to_nth_level_func(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
......@@ -197,23 +196,29 @@ btr_cur_search_to_nth_level(
cursor->left_block is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch
is != 0, we maybe do not have a latch set
on the cursor page, we assume
the caller uses his search latch
to protect the record! */
NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch
protects the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */
ulint has_search_latch,
/*!< in: latch mode the caller
currently has on search system:
RW_S_LATCH, or 0 */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: currently held btr_search_latch
(in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in/out: mini-transaction */
ib_uint64_t autoinc = 0);
/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
#ifdef BTR_CUR_HASH_ADAPT
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,a,fi,li,mtr)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,fi,li,mtr)
#endif /* BTR_CUR_HASH_ADAPT */
/*****************************************************************//**
Opens a cursor at either end of an index.
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, 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
......@@ -136,20 +136,25 @@ btr_pcur_open_with_no_init_func(
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then
we maybe do not acquire a latch on the cursor
page, but assume that the caller uses his
btr search latch to protect the record! */
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ulint has_search_latch,
/*!< in: latch mode the caller
currently has on search system:
RW_S_LATCH, or 0 */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
#ifdef BTR_CUR_HASH_ADAPT
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,ahi,__FILE__,__LINE__,m)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,__FILE__,__LINE__,m)
#endif /* BTR_CUR_HASH_ADAPT */
/*****************************************************************//**
Opens a persistent cursor at either end of an index. */
......
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2017, MariaDB Corporation.
Copyright (c) 2015, 2018, 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
......@@ -454,9 +454,12 @@ btr_pcur_open_low(
ut_ad(!dict_index_is_spatial(index));
err = btr_cur_search_to_nth_level(
index, level, tuple, mode, latch_mode,
btr_cursor, 0, file, line, mtr, autoinc);
err = btr_cur_search_to_nth_level_func(
index, level, tuple, mode, latch_mode, btr_cursor,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr, autoinc);
if (err != DB_SUCCESS) {
ib::warn() << " Error code: " << err
......@@ -491,15 +494,15 @@ btr_pcur_open_with_no_init_func(
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then
we maybe do not acquire a latch on the cursor
page, but assume that the caller uses his
btr search latch to protect the record! */
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ulint has_search_latch,
/*!< in: latch mode the caller
currently has on search system:
RW_S_LATCH, or 0 */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
......@@ -514,9 +517,12 @@ btr_pcur_open_with_no_init_func(
btr_cursor = btr_pcur_get_btr_cur(cursor);
err = btr_cur_search_to_nth_level(
err = btr_cur_search_to_nth_level_func(
index, 0, tuple, mode, latch_mode, btr_cursor,
has_search_latch, file, line, mtr);
#ifdef BTR_CUR_HASH_ADAPT
ahi_latch,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, 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
......@@ -91,12 +91,11 @@ both have sensible values.
we assume the caller uses his search latch
to protect the record!
@param[out] cursor tree cursor
@param[in] has_search_latch
latch mode the caller currently has on
search system: RW_S/X_LATCH or 0
@param[in] ahi_latch the adaptive hash index latch being held,
or NULL
@param[in] mtr mini transaction
@return TRUE if succeeded */
ibool
@return whether the search succeeded */
bool
btr_search_guess_on_hash(
dict_index_t* index,
btr_search_t* info,
......@@ -104,7 +103,7 @@ btr_search_guess_on_hash(
ulint mode,
ulint latch_mode,
btr_cur_t* cursor,
ulint has_search_latch,
rw_lock_t* ahi_latch,
mtr_t* mtr);
/** Move or delete hash entries for moved records, usually in a page split.
......@@ -140,17 +139,19 @@ btr_search_drop_page_hash_when_freed(
/** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the place to insert
using btr_cur_search_, and the new record has been
inserted next to the cursor. */
inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */
void
btr_search_update_hash_node_on_insert(btr_cur_t* cursor);
btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch);
/** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the
@param[in,out] cursor cursor which was positioned to the
place to insert using btr_cur_search_...,
and the new record has been inserted next
to the cursor */
to the cursor
@param[in] ahi_latch the adaptive hash index latch */
void
btr_search_update_hash_on_insert(btr_cur_t* cursor);
btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch);
/** Updates the page hash index when a single record is deleted from a page.
@param[in] cursor cursor which was positioned on the record to delete
......@@ -163,18 +164,6 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor);
bool
btr_search_validate();
/** X-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_lock(const dict_index_t* index);
/** X-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_unlock(const dict_index_t* index);
/** Lock all search latches in exclusive mode. */
UNIV_INLINE
void
......@@ -185,18 +174,6 @@ UNIV_INLINE
void
btr_search_x_unlock_all();
/** S-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_lock(const dict_index_t* index);
/** S-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_unlock(const dict_index_t* index);
/** Lock all search latches in shared mode. */
UNIV_INLINE
void
......@@ -243,15 +220,11 @@ btr_get_search_table(const dict_index_t* index);
#else /* BTR_CUR_HASH_ADAPT */
# define btr_search_sys_create(size)
# define btr_search_drop_page_hash_index(block)
# define btr_search_s_lock(index)
# define btr_search_s_unlock(index)
# define btr_search_s_lock_all(index)
# define btr_search_s_unlock_all(index)
# define btr_search_x_lock(index)
# define btr_search_x_unlock(index)
# define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block)
# define btr_search_update_hash_on_insert(cursor)
# define btr_search_update_hash_on_insert(cursor, ahi_latch)
# define btr_search_update_hash_on_delete(cursor)
# define btr_search_sys_resize(hash_size)
#endif /* BTR_CUR_HASH_ADAPT */
......
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 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
......@@ -45,13 +46,11 @@ btr_search_info_create(mem_heap_t* heap)
}
#ifdef BTR_CUR_HASH_ADAPT
/*********************************************************************//**
Updates the search info. */
/** Updates the search info.
@param[in,out] info search info
@param[in,out] cursor cursor which was just positioned */
void
btr_search_info_update_slow(
/*========================*/
btr_search_t* info, /*!< in/out: search info */
btr_cur_t* cursor);/*!< in: cursor which was just positioned */
btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor);
/*********************************************************************//**
Updates the search info. */
......@@ -87,24 +86,6 @@ btr_search_info_update(
btr_search_info_update_slow(info, cursor);
}
/** X-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_lock(const dict_index_t* index)
{
rw_lock_x_lock(btr_get_search_latch(index));
}
/** X-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_unlock(const dict_index_t* index)
{
rw_lock_x_unlock(btr_get_search_latch(index));
}
/** Lock all search latches in exclusive mode. */
UNIV_INLINE
void
......@@ -125,24 +106,6 @@ btr_search_x_unlock_all()
}
}
/** S-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_lock(const dict_index_t* index)
{
rw_lock_s_lock(btr_get_search_latch(index));
}
/** S-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_unlock(const dict_index_t* index)
{
rw_lock_s_unlock(btr_get_search_latch(index));
}
/** Lock all search latches in shared mode. */
UNIV_INLINE
void
......
......@@ -1273,23 +1273,18 @@ void
row_sel_open_pcur(
/*==============*/
plan_t* plan, /*!< in: table plan */
ibool search_latch_locked,
/*!< in: TRUE if the thread currently
has the search latch locked in
s-mode */
mtr_t* mtr) /*!< in: mtr */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: the adaptive hash index latch */
#endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
dict_index_t* index;
func_node_t* cond;
que_node_t* exp;
ulint n_fields;
ulint has_search_latch = 0; /* RW_S_LATCH or 0 */
ulint i;
if (search_latch_locked) {
has_search_latch = RW_S_LATCH;
}
index = plan->index;
/* Calculate the value of the search tuple: the exact match columns
......@@ -1325,7 +1320,7 @@ row_sel_open_pcur(
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
BTR_SEARCH_LEAF, &plan->pcur,
has_search_latch, mtr);
ahi_latch, mtr);
} else {
/* Open the cursor to the start or the end of the index
(FALSE: no init) */
......@@ -1473,7 +1468,7 @@ row_sel_try_search_shortcut(
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch);
row_sel_open_pcur(plan, TRUE, mtr);
row_sel_open_pcur(plan, ahi_latch, mtr);
const rec_t* rec = btr_pcur_get_rec(&(plan->pcur));
......@@ -1659,8 +1654,11 @@ row_sel(
if (!plan->pcur_is_open) {
/* Evaluate the expressions to build the search tuple and
open the cursor */
row_sel_open_pcur(plan, FALSE, &mtr);
row_sel_open_pcur(plan,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
&mtr);
cursor_just_opened = TRUE;
......@@ -3841,7 +3839,7 @@ row_sel_try_search_shortcut_for_mysql(
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, RW_S_LATCH, mtr);
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);
rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec) || rec_is_default_row(rec, index)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment