Commit 3da31938 authored by marko's avatar marko

Port r152 from branches/5.0: Account for a race condition when dropping the

adaptive hash index for a B-tree page.  (Bug #16582)

btr_search_drop_page_hash_index(): Retry the operation if a hash index
with different parameters was built meanwhile.  Add diagnostics for the
case that hash node pointers to the page remain.  This fix is from Heikki.

btr_search_info_update_hash(), btr_search_info_update_slow():
Document the parameter "info" as in/out.
parent 463d8e33
......@@ -191,7 +191,7 @@ static
void
btr_search_info_update_hash(
/*========================*/
btr_search_t* info, /* in: search info */
btr_search_t* info, /* in/out: search info */
btr_cur_t* cursor) /* in: cursor which was just positioned */
{
dict_index_t* index;
......@@ -452,7 +452,7 @@ Updates the search info. */
void
btr_search_info_update_slow(
/*========================*/
btr_search_t* info, /* in: search info */
btr_search_t* info, /* in/out: search info */
btr_cur_t* cursor) /* in: cursor which was just positioned */
{
buf_block_t* block;
......@@ -912,12 +912,12 @@ btr_search_drop_page_hash_index(
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
retry:
rw_lock_s_lock(&btr_search_latch);
block = buf_block_align(page);
if (!block->is_hashed) {
if (UNIV_LIKELY(!block->is_hashed)) {
rw_lock_s_unlock(&btr_search_latch);
......@@ -958,6 +958,8 @@ btr_search_drop_page_hash_index(
tree_id = btr_page_get_index_id(page);
ut_a(0 == ut_dulint_cmp(tree_id, index->id));
prev_fold = 0;
heap = NULL;
......@@ -992,6 +994,26 @@ btr_search_drop_page_hash_index(
rw_lock_x_lock(&btr_search_latch);
if (UNIV_UNLIKELY(!block->is_hashed)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
}
ut_a(block->index == index);
if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
|| UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
/* Someone else has meanwhile built a new hash index on the
page, with different parameters */
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
goto retry;
}
for (i = 0; i < n_cached; i++) {
ha_remove_all_nodes_to_page(table, folds[i], page);
......@@ -999,8 +1021,20 @@ btr_search_drop_page_hash_index(
block->is_hashed = FALSE;
block->index = NULL;
cleanup:
if (UNIV_UNLIKELY(block->n_pointers)) {
/* Corruption */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Corruption of adaptive hash index. After dropping\n"
"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n",
index->name, (ulong) block->n_pointers);
rw_lock_x_unlock(&btr_search_latch);
rw_lock_x_unlock(&btr_search_latch);
btr_search_validate();
} else {
rw_lock_x_unlock(&btr_search_latch);
}
mem_free(folds);
}
......
......@@ -16,7 +16,7 @@ Updates the search info. */
void
btr_search_info_update_slow(
/*========================*/
btr_search_t* info, /* in: search info */
btr_search_t* info, /* in/out: search info */
btr_cur_t* cursor);/* in: cursor which was just positioned */
/************************************************************************
......
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