diff options
Diffstat (limited to 'innobase/btr/btr0sea.c')
-rw-r--r-- | innobase/btr/btr0sea.c | 164 |
1 files changed, 142 insertions, 22 deletions
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 8a54d9de9c0..cfdfefebd1a 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -15,6 +15,7 @@ Created 2/17/1996 Heikki Tuuri #include "page0page.h" #include "page0cur.h" #include "btr0cur.h" +#include "btr0pcur.h" #include "btr0btr.h" ulint btr_search_n_succ = 0; @@ -145,6 +146,8 @@ btr_search_info_create( info = mem_heap_alloc(heap, sizeof(btr_search_t)); + info->magic_n = BTR_SEARCH_MAGIC_N; + info->last_search = NULL; info->n_direction = 0; info->root_guess = NULL; @@ -159,6 +162,12 @@ btr_search_info_create( info->n_patt_succ = 0; info->n_searches = 0; + /* Set some sensible values */ + info->n_fields = 1; + info->n_bytes = 0; + + info->side = BTR_SEARCH_LEFT_SIDE; + return(info); } @@ -197,7 +206,7 @@ btr_search_info_update_hash( /* Test if the search would have succeeded using the recommended hash prefix */ - if ((info->n_fields >= n_unique) && (cursor->up_match >= n_unique)) { + if (info->n_fields >= n_unique && cursor->up_match >= n_unique) { info->n_hash_potential++; @@ -207,8 +216,8 @@ btr_search_info_update_hash( cmp = ut_pair_cmp(info->n_fields, info->n_bytes, cursor->low_match, cursor->low_bytes); - if (((info->side == BTR_SEARCH_LEFT_SIDE) && (cmp <= 0)) - || ((info->side == BTR_SEARCH_RIGHT_SIDE) && (cmp > 0))) { + if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp <= 0) + || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp > 0)) { goto set_new_recomm; } @@ -216,8 +225,8 @@ btr_search_info_update_hash( cmp = ut_pair_cmp(info->n_fields, info->n_bytes, cursor->up_match, cursor->up_bytes); - if (((info->side == BTR_SEARCH_LEFT_SIDE) && (cmp > 0)) - || ((info->side == BTR_SEARCH_RIGHT_SIDE) && (cmp <= 0))) { + if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp > 0) + || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp <= 0)) { goto set_new_recomm; } @@ -233,19 +242,18 @@ set_new_recomm: info->hash_analysis = 0; - if ((cursor->up_match >= n_unique) - || (cursor->low_match >= n_unique)) { - info->n_fields = n_unique; - info->n_bytes = 0; - - info->side = BTR_SEARCH_LEFT_SIDE; - } - cmp = ut_pair_cmp(cursor->up_match, cursor->up_bytes, cursor->low_match, cursor->low_bytes); if (cmp == 0) { info->n_hash_potential = 0; + /* For extra safety, we set some sensible values here */ + + info->n_fields = 1; + info->n_bytes = 0; + + info->side = BTR_SEARCH_LEFT_SIDE; + } else if (cmp > 0) { info->n_hash_potential = 1; @@ -305,6 +313,9 @@ btr_search_update_block_hash_info( info->last_hash_succ = FALSE; + ut_a(block->magic_n == BUF_BLOCK_MAGIC_N); + ut_a(info->magic_n == BTR_SEARCH_MAGIC_N); + if ((block->n_hash_helps > 0) && (info->n_hash_potential > 0) && (block->n_fields == info->n_fields) @@ -440,7 +451,9 @@ btr_search_info_update_slow( rw_lock_x_unlock(&btr_search_latch); } - if (build_index) { + if (build_index) { + ut_a(block->n_fields + block->n_bytes > 0); + btr_search_build_page_hash_index(block->frame, block->n_fields, block->n_bytes, @@ -622,6 +635,7 @@ btr_search_guess_on_hash( dulint tree_id; #ifdef notdefined btr_cur_t cursor2; + btr_pcur_t pcur; #endif ut_ad(index && info && tuple && cursor && mtr); ut_ad((latch_mode == BTR_SEARCH_LEAF) @@ -664,6 +678,9 @@ btr_search_guess_on_hash( rw_lock_s_lock(&btr_search_latch); } + ut_a(btr_search_latch.writer != RW_LOCK_EX); + ut_a(btr_search_latch.reader_count > 0); + rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); if (!rec) { @@ -754,7 +771,26 @@ btr_search_guess_on_hash( btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, &cursor2, 0, mtr); - ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); + if (mode == PAGE_CUR_GE + && btr_cur_get_rec(&cursor2) == page_get_supremum_rec( + buf_frame_align(btr_cur_get_rec(&cursor2)))) { + + /* If mode is PAGE_CUR_GE, then the binary search + in the index tree may actually take us to the supremum + of the previous page */ + + info->last_hash_succ = FALSE; + + btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, + &pcur, mtr); + ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor)); + } else { + ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); + } + + /* NOTE that it is theoretically possible that the above assertions + fail if the page of the cursor gets removed from the buffer pool + meanwhile! Thus it might not be a bug. */ info->last_hash_succ = TRUE; #endif @@ -835,6 +871,8 @@ btr_search_drop_page_hash_index( n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; + ut_a(n_fields + n_bytes > 0); + rw_lock_s_unlock(&btr_search_latch); n_recs = page_get_n_recs(page); @@ -851,6 +889,14 @@ btr_search_drop_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); + if (rec != sup) { + ut_a(n_fields <= rec_get_n_fields(rec)); + + if (n_bytes > 0) { + ut_a(n_fields < rec_get_n_fields(rec)); + } + } + tree_id = btr_page_get_index_id(page); prev_fold = 0; @@ -861,7 +907,7 @@ btr_search_drop_page_hash_index( fold = rec_fold(rec, n_fields, n_bytes, tree_id); - if ((fold == prev_fold) && (prev_fold != 0)) { + if (fold == prev_fold && prev_fold != 0) { goto next_rec; } @@ -873,6 +919,7 @@ btr_search_drop_page_hash_index( n_cached++; next_rec: rec = page_rec_get_next(rec); + prev_fold = fold; } rw_lock_x_lock(&btr_search_latch); @@ -913,7 +960,7 @@ btr_search_drop_page_hash_when_freed( mtr_start(&mtr); /* We assume that if the caller has a latch on the page, - then the caller has already drooped the hash index for the page, + then the caller has already dropped the hash index for the page, and we never get here. Therefore we can acquire the s-latch to the page without fearing a deadlock. */ @@ -980,6 +1027,8 @@ btr_search_build_page_hash_index( return; } + ut_a(n_fields + n_bytes > 0); + /* Calculate and cache fold values and corresponding records into an array for fast insertion to the hash index */ @@ -995,6 +1044,14 @@ btr_search_build_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); + if (rec != sup) { + ut_a(n_fields <= rec_get_n_fields(rec)); + + if (n_bytes > 0) { + ut_a(n_fields < rec_get_n_fields(rec)); + } + } + /* FIXME: in a mixed tree, all records may not have enough ordering fields: */ @@ -1126,6 +1183,8 @@ btr_search_move_or_delete_hash_entries( rw_lock_s_unlock(&btr_search_latch); + ut_a(n_fields + n_bytes > 0); + btr_search_build_page_hash_index(new_page, n_fields, n_bytes, side); ut_a(n_fields == block->curr_n_fields); @@ -1166,9 +1225,11 @@ btr_search_update_hash_on_delete( return; } + ut_a(block->curr_n_fields + block->curr_n_bytes > 0); + table = btr_search_sys->hash_index; - tree_id = ((cursor->index)->tree)->id; + tree_id = cursor->index->tree->id; fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes, tree_id); @@ -1285,7 +1346,6 @@ btr_search_update_hash_on_insert( if (rec != page_get_infimum_rec(page)) { fold = rec_fold(rec, n_fields, n_bytes, tree_id); - } else { if (side == BTR_SEARCH_LEFT_SIDE) { @@ -1370,7 +1430,7 @@ btr_search_print_info(void) rw_lock_x_lock(&btr_search_latch); - ha_print_info(btr_search_sys->hash_index); +/* ha_print_info(btr_search_sys->hash_index); */ rw_lock_x_unlock(&btr_search_latch); } @@ -1436,11 +1496,71 @@ btr_search_validate(void) /*=====================*/ /* out: TRUE if ok */ { + buf_block_t* block; + page_t* page; + ha_node_t* node; + ulint n_page_dumps = 0; + ibool ok = TRUE; + ulint i; + char rec_str[500]; + rw_lock_x_lock(&btr_search_latch); + + for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { + node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; + + while (node != NULL) { + block = buf_block_align(node->data); + page = buf_frame_align(node->data); + + if (!block->is_hashed + || node->fold != rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))) { + ok = FALSE; + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error in an adaptive hash index pointer to page %lu\n" +"ptr mem address %lu index id %lu %lu, node fold %lu, rec fold %lu\n", + buf_frame_get_page_no(page), + (ulint)(node->data), + ut_dulint_get_high(btr_page_get_index_id(page)), + ut_dulint_get_low(btr_page_get_index_id(page)), + node->fold, rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))); + + rec_sprintf(rec_str, 450, (rec_t*)(node->data)); + + fprintf(stderr, + "InnoDB: Record %s\n" + "InnoDB: on that page.", rec_str); + + fprintf(stderr, +"Page mem address %lu, is hashed %lu, n fields %lu, n bytes %lu\n" +"side %lu\n", + (ulint)page, block->is_hashed, block->curr_n_fields, + block->curr_n_bytes, block->curr_side); + + if (n_page_dumps < 20) { + buf_page_print(page); + n_page_dumps++; + } + } + + node = node->next; + } + } - ut_a(ha_validate(btr_search_sys->hash_index)); + if (!ha_validate(btr_search_sys->hash_index)) { + + ok = FALSE; + } rw_lock_x_unlock(&btr_search_latch); - return(TRUE); + return(ok); } |