#include "btr0sea.h"#include "buf0buf.h"#include "page0page.h"#include "page0cur.h"#include "btr0cur.h"#include "btr0pcur.h"#include "btr0btr.h"#include "ha0ha.h"Include dependency graph for btr0sea.c:

Go to the source code of this file.
| #define BTR_SEARCH_BUILD_LIMIT 100 |
Definition at line 60 of file btr0sea.c.
Referenced by btr_search_guess_on_hash(), and btr_search_update_block_hash_info().
| #define BTR_SEARCH_PAGE_BUILD_LIMIT 16 |
| static void btr_search_build_page_hash_index | ( | dict_index_t * | index, | |
| page_t * | page, | |||
| ulint | n_fields, | |||
| ulint | n_bytes, | |||
| ulint | side | |||
| ) | [static] |
Definition at line 1093 of file btr0sea.c.
References yaSSL::block, btr_page_get_index_id(), btr_search_check_free_space_in_heap(), btr_search_drop_page_hash_index(), btr_search_latch, BTR_SEARCH_LEFT_SIDE, BTR_SEARCH_RIGHT_SIDE, btr_search_sys, buf_block_align(), dict_index_get_n_unique_in_tree(), ha_insert_for_fold(), btr_search_sys_struct::hash_index, index(), mem_alloc, mem_free, mem_heap_free, NULL, page_get_infimum_rec(), page_get_n_recs(), page_rec_get_next(), page_rec_is_supremum(), rec_fold(), rec_get_offsets, rec_offs_n_fields(), REC_OFFS_NORMAL_SIZE, RW_LOCK_EX, rw_lock_s_lock, rw_lock_s_unlock, RW_LOCK_SHARED, rw_lock_x_lock, rw_lock_x_unlock, TRUE, ut_a, and ut_ad.
Referenced by btr_search_info_update_slow(), and btr_search_move_or_delete_hash_entries().
01095 : index for which to build */ 01096 page_t* page, /* in: index page, s- or x-latched */ 01097 ulint n_fields,/* in: hash this many full fields */ 01098 ulint n_bytes,/* in: hash this many bytes from the next 01099 field */ 01100 ulint side) /* in: hash for searches from this side */ 01101 { 01102 hash_table_t* table; 01103 buf_block_t* block; 01104 rec_t* rec; 01105 rec_t* next_rec; 01106 ulint fold; 01107 ulint next_fold; 01108 dulint tree_id; 01109 ulint n_cached; 01110 ulint n_recs; 01111 ulint* folds; 01112 rec_t** recs; 01113 ulint i; 01114 mem_heap_t* heap = NULL; 01115 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01116 ulint* offsets = offsets_; 01117 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01118 01119 ut_ad(index); 01120 01121 block = buf_block_align(page); 01122 table = btr_search_sys->hash_index; 01123 01124 #ifdef UNIV_SYNC_DEBUG 01125 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 01126 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) 01127 || rw_lock_own(&(block->lock), RW_LOCK_EX)); 01128 #endif /* UNIV_SYNC_DEBUG */ 01129 01130 rw_lock_s_lock(&btr_search_latch); 01131 01132 if (block->is_hashed && ((block->curr_n_fields != n_fields) 01133 || (block->curr_n_bytes != n_bytes) 01134 || (block->curr_side != side))) { 01135 01136 rw_lock_s_unlock(&btr_search_latch); 01137 01138 btr_search_drop_page_hash_index(page); 01139 } else { 01140 rw_lock_s_unlock(&btr_search_latch); 01141 } 01142 01143 n_recs = page_get_n_recs(page); 01144 01145 if (n_recs == 0) { 01146 01147 return; 01148 } 01149 01150 /* Check that the values for hash index build are sensible */ 01151 01152 if (n_fields + n_bytes == 0) { 01153 01154 return; 01155 } 01156 01157 if (dict_index_get_n_unique_in_tree(index) < n_fields 01158 || (dict_index_get_n_unique_in_tree(index) == n_fields 01159 && n_bytes > 0)) { 01160 return; 01161 } 01162 01163 /* Calculate and cache fold values and corresponding records into 01164 an array for fast insertion to the hash index */ 01165 01166 folds = mem_alloc(n_recs * sizeof(ulint)); 01167 recs = mem_alloc(n_recs * sizeof(rec_t*)); 01168 01169 n_cached = 0; 01170 01171 tree_id = btr_page_get_index_id(page); 01172 01173 rec = page_get_infimum_rec(page); 01174 rec = page_rec_get_next(rec); 01175 01176 offsets = rec_get_offsets(rec, index, offsets, 01177 n_fields + (n_bytes > 0), &heap); 01178 01179 if (!page_rec_is_supremum(rec)) { 01180 ut_a(n_fields <= rec_offs_n_fields(offsets)); 01181 01182 if (n_bytes > 0) { 01183 ut_a(n_fields < rec_offs_n_fields(offsets)); 01184 } 01185 } 01186 01187 /* FIXME: in a mixed tree, all records may not have enough ordering 01188 fields: */ 01189 fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); 01190 01191 if (side == BTR_SEARCH_LEFT_SIDE) { 01192 01193 folds[n_cached] = fold; 01194 recs[n_cached] = rec; 01195 n_cached++; 01196 } 01197 01198 for (;;) { 01199 next_rec = page_rec_get_next(rec); 01200 01201 if (page_rec_is_supremum(next_rec)) { 01202 01203 if (side == BTR_SEARCH_RIGHT_SIDE) { 01204 01205 folds[n_cached] = fold; 01206 recs[n_cached] = rec; 01207 n_cached++; 01208 } 01209 01210 break; 01211 } 01212 01213 offsets = rec_get_offsets(next_rec, index, offsets, 01214 n_fields + (n_bytes > 0), &heap); 01215 next_fold = rec_fold(next_rec, offsets, n_fields, 01216 n_bytes, tree_id); 01217 01218 if (fold != next_fold) { 01219 /* Insert an entry into the hash index */ 01220 01221 if (side == BTR_SEARCH_LEFT_SIDE) { 01222 01223 folds[n_cached] = next_fold; 01224 recs[n_cached] = next_rec; 01225 n_cached++; 01226 } else { 01227 folds[n_cached] = fold; 01228 recs[n_cached] = rec; 01229 n_cached++; 01230 } 01231 } 01232 01233 rec = next_rec; 01234 fold = next_fold; 01235 } 01236 01237 btr_search_check_free_space_in_heap(); 01238 01239 rw_lock_x_lock(&btr_search_latch); 01240 01241 if (block->is_hashed && ((block->curr_n_fields != n_fields) 01242 || (block->curr_n_bytes != n_bytes) 01243 || (block->curr_side != side))) { 01244 goto exit_func; 01245 } 01246 01247 block->is_hashed = TRUE; 01248 block->n_hash_helps = 0; 01249 01250 block->curr_n_fields = n_fields; 01251 block->curr_n_bytes = n_bytes; 01252 block->curr_side = side; 01253 block->index = index; 01254 01255 for (i = 0; i < n_cached; i++) { 01256 01257 ha_insert_for_fold(table, folds[i], recs[i]); 01258 } 01259 01260 exit_func: 01261 rw_lock_x_unlock(&btr_search_latch); 01262 01263 mem_free(folds); 01264 mem_free(recs); 01265 if (UNIV_LIKELY_NULL(heap)) { 01266 mem_heap_free(heap); 01267 } 01268 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_search_check_free_space_in_heap | ( | void | ) | [static] |
Definition at line 91 of file btr0sea.c.
References btr_search_latch, btr_search_sys, buf_frame_alloc(), buf_frame_free(), btr_search_sys_struct::hash_index, hash_table_struct::heap, NULL, RW_LOCK_EX, RW_LOCK_SHARED, rw_lock_x_lock, rw_lock_x_unlock, and ut_ad.
Referenced by btr_search_build_page_hash_index(), btr_search_info_update_slow(), and btr_search_update_hash_on_insert().
00093 { 00094 buf_frame_t* frame; 00095 hash_table_t* table; 00096 mem_heap_t* heap; 00097 00098 #ifdef UNIV_SYNC_DEBUG 00099 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); 00100 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00101 #endif /* UNIV_SYNC_DEBUG */ 00102 00103 table = btr_search_sys->hash_index; 00104 00105 heap = table->heap; 00106 00107 /* Note that we peek the value of heap->free_block without reserving 00108 the latch: this is ok, because we will not guarantee that there will 00109 be enough free space in the hash table. */ 00110 00111 if (heap->free_block == NULL) { 00112 frame = buf_frame_alloc(); 00113 00114 rw_lock_x_lock(&btr_search_latch); 00115 00116 if (heap->free_block == NULL) { 00117 heap->free_block = frame; 00118 } else { 00119 buf_frame_free(frame); 00120 } 00121 00122 rw_lock_x_unlock(&btr_search_latch); 00123 } 00124 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool btr_search_check_guess | ( | btr_cur_t * | cursor, | |
| ibool | can_only_compare_to_cursor_rec, | |||
| dtuple_t * | tuple, | |||
| ulint | mode, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 533 of file btr0sea.c.
References btr_cur_get_rec(), btr_page_get_next(), btr_page_get_prev(), buf_frame_align(), cmp, dict_index_get_n_unique_in_tree(), FALSE, FIL_NULL, btr_cur_struct::index, btr_cur_struct::low_match, mem_heap_free, NULL, page_cmp_dtuple_rec_with_match(), PAGE_CUR_G, PAGE_CUR_GE, PAGE_CUR_L, PAGE_CUR_LE, page_rec_get_next(), page_rec_get_prev(), page_rec_is_infimum(), page_rec_is_supremum(), page_rec_is_user_rec(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, TRUE, btr_cur_struct::up_match, and ut_ad.
Referenced by btr_search_guess_on_hash().
00535 : TRUE if success */ 00536 btr_cur_t* cursor, /* in: guessed cursor position */ 00537 ibool can_only_compare_to_cursor_rec, 00538 /* in: if we do not have a latch on the page 00539 of cursor, but only a latch on 00540 btr_search_latch, then ONLY the columns 00541 of the record UNDER the cursor are 00542 protected, not the next or previous record 00543 in the chain: we cannot look at the next or 00544 previous record to check our guess! */ 00545 dtuple_t* tuple, /* in: data tuple */ 00546 ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, 00547 or PAGE_CUR_GE */ 00548 mtr_t* mtr) /* in: mtr */ 00549 { 00550 rec_t* rec; 00551 ulint n_unique; 00552 ulint match; 00553 ulint bytes; 00554 int cmp; 00555 mem_heap_t* heap = NULL; 00556 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00557 ulint* offsets = offsets_; 00558 ibool success = FALSE; 00559 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00560 00561 n_unique = dict_index_get_n_unique_in_tree(cursor->index); 00562 00563 rec = btr_cur_get_rec(cursor); 00564 00565 ut_ad(page_rec_is_user_rec(rec)); 00566 00567 match = 0; 00568 bytes = 0; 00569 00570 offsets = rec_get_offsets(rec, cursor->index, offsets, 00571 n_unique, &heap); 00572 cmp = page_cmp_dtuple_rec_with_match(tuple, rec, 00573 offsets, &match, &bytes); 00574 00575 if (mode == PAGE_CUR_GE) { 00576 if (cmp == 1) { 00577 goto exit_func; 00578 } 00579 00580 cursor->up_match = match; 00581 00582 if (match >= n_unique) { 00583 success = TRUE; 00584 goto exit_func; 00585 } 00586 } else if (mode == PAGE_CUR_LE) { 00587 if (cmp == -1) { 00588 goto exit_func; 00589 } 00590 00591 cursor->low_match = match; 00592 00593 } else if (mode == PAGE_CUR_G) { 00594 if (cmp != -1) { 00595 goto exit_func; 00596 } 00597 } else if (mode == PAGE_CUR_L) { 00598 if (cmp != 1) { 00599 goto exit_func; 00600 } 00601 } 00602 00603 if (can_only_compare_to_cursor_rec) { 00604 /* Since we could not determine if our guess is right just by 00605 looking at the record under the cursor, return FALSE */ 00606 goto exit_func; 00607 } 00608 00609 match = 0; 00610 bytes = 0; 00611 00612 if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) { 00613 rec_t* prev_rec; 00614 00615 ut_ad(!page_rec_is_infimum(rec)); 00616 00617 prev_rec = page_rec_get_prev(rec); 00618 00619 if (page_rec_is_infimum(prev_rec)) { 00620 success = btr_page_get_prev( 00621 buf_frame_align(prev_rec), mtr) == FIL_NULL; 00622 00623 goto exit_func; 00624 } 00625 00626 offsets = rec_get_offsets(prev_rec, cursor->index, offsets, 00627 n_unique, &heap); 00628 cmp = page_cmp_dtuple_rec_with_match(tuple, prev_rec, 00629 offsets, &match, &bytes); 00630 if (mode == PAGE_CUR_GE) { 00631 success = cmp == 1; 00632 } else { 00633 success = cmp != -1; 00634 } 00635 00636 goto exit_func; 00637 } else { 00638 rec_t* next_rec; 00639 00640 ut_ad(!page_rec_is_supremum(rec)); 00641 00642 next_rec = page_rec_get_next(rec); 00643 00644 if (page_rec_is_supremum(next_rec)) { 00645 if (btr_page_get_next( 00646 buf_frame_align(next_rec), mtr) == FIL_NULL) { 00647 00648 cursor->up_match = 0; 00649 success = TRUE; 00650 } 00651 00652 goto exit_func; 00653 } 00654 00655 offsets = rec_get_offsets(next_rec, cursor->index, offsets, 00656 n_unique, &heap); 00657 cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, 00658 offsets, &match, &bytes); 00659 if (mode == PAGE_CUR_LE) { 00660 success = cmp == -1; 00661 cursor->up_match = match; 00662 } else { 00663 success = cmp != 1; 00664 } 00665 } 00666 exit_func: 00667 if (UNIV_LIKELY_NULL(heap)) { 00668 mem_heap_free(heap); 00669 } 00670 return(success); 00671 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_drop_page_hash_index | ( | page_t * | page | ) |
Definition at line 893 of file btr0sea.c.
References yaSSL::block, btr_page_get_index_id(), btr_search_latch, btr_search_sys, btr_search_validate(), buf_block_align(), cleanup(), FALSE, ha_remove_all_nodes_to_page(), btr_search_sys_struct::hash_index, index(), mem_alloc, mem_free, mem_heap_free, NULL, page_get_infimum_rec(), page_get_n_recs(), page_rec_get_next(), page_rec_is_supremum(), rec_fold(), rec_get_offsets, rec_offs_n_fields(), RW_LOCK_EX, rw_lock_s_lock, rw_lock_s_unlock, RW_LOCK_SHARED, rw_lock_x_lock, rw_lock_x_unlock, ut_a, ut_ad, ut_dulint_cmp(), and ut_print_timestamp().
Referenced by btr_compress(), btr_discard_only_page_on_level(), btr_discard_page(), btr_free_root(), btr_lift_page_up(), btr_page_empty(), btr_page_reorganize_low(), btr_root_raise_and_insert(), btr_search_build_page_hash_index(), btr_search_drop_page_hash_when_freed(), btr_search_move_or_delete_hash_entries(), and buf_LRU_search_and_free_block().
00895 : index page, s- or x-latched, or an index page 00896 for which we know that block->buf_fix_count == 0 */ 00897 { 00898 hash_table_t* table; 00899 buf_block_t* block; 00900 ulint n_fields; 00901 ulint n_bytes; 00902 rec_t* rec; 00903 ulint fold; 00904 ulint prev_fold; 00905 dulint tree_id; 00906 ulint n_cached; 00907 ulint n_recs; 00908 ulint* folds; 00909 ulint i; 00910 mem_heap_t* heap; 00911 dict_index_t* index; 00912 ulint* offsets; 00913 00914 #ifdef UNIV_SYNC_DEBUG 00915 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); 00916 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00917 #endif /* UNIV_SYNC_DEBUG */ 00918 retry: 00919 rw_lock_s_lock(&btr_search_latch); 00920 00921 block = buf_block_align(page); 00922 00923 if (UNIV_LIKELY(!block->is_hashed)) { 00924 00925 rw_lock_s_unlock(&btr_search_latch); 00926 00927 return; 00928 } 00929 00930 table = btr_search_sys->hash_index; 00931 00932 #ifdef UNIV_SYNC_DEBUG 00933 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) 00934 || rw_lock_own(&(block->lock), RW_LOCK_EX) 00935 || (block->buf_fix_count == 0)); 00936 #endif /* UNIV_SYNC_DEBUG */ 00937 00938 n_fields = block->curr_n_fields; 00939 n_bytes = block->curr_n_bytes; 00940 index = block->index; 00941 00942 /* NOTE: The fields of block must not be accessed after 00943 releasing btr_search_latch, as the index page might only 00944 be s-latched! */ 00945 00946 rw_lock_s_unlock(&btr_search_latch); 00947 00948 ut_a(n_fields + n_bytes > 0); 00949 00950 n_recs = page_get_n_recs(page); 00951 00952 /* Calculate and cache fold values into an array for fast deletion 00953 from the hash index */ 00954 00955 folds = mem_alloc(n_recs * sizeof(ulint)); 00956 00957 n_cached = 0; 00958 00959 rec = page_get_infimum_rec(page); 00960 rec = page_rec_get_next(rec); 00961 00962 tree_id = btr_page_get_index_id(page); 00963 00964 ut_a(0 == ut_dulint_cmp(tree_id, index->id)); 00965 00966 prev_fold = 0; 00967 00968 heap = NULL; 00969 offsets = NULL; 00970 00971 while (!page_rec_is_supremum(rec)) { 00972 /* FIXME: in a mixed tree, not all records may have enough 00973 ordering fields: */ 00974 offsets = rec_get_offsets(rec, index, offsets, 00975 n_fields + (n_bytes > 0), &heap); 00976 ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0)); 00977 fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); 00978 00979 if (fold == prev_fold && prev_fold != 0) { 00980 00981 goto next_rec; 00982 } 00983 00984 /* Remove all hash nodes pointing to this page from the 00985 hash chain */ 00986 00987 folds[n_cached] = fold; 00988 n_cached++; 00989 next_rec: 00990 rec = page_rec_get_next(rec); 00991 prev_fold = fold; 00992 } 00993 00994 if (UNIV_LIKELY_NULL(heap)) { 00995 mem_heap_free(heap); 00996 } 00997 00998 rw_lock_x_lock(&btr_search_latch); 00999 01000 if (UNIV_UNLIKELY(!block->is_hashed)) { 01001 /* Someone else has meanwhile dropped the hash index */ 01002 01003 goto cleanup; 01004 } 01005 01006 ut_a(block->index == index); 01007 01008 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields) 01009 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) { 01010 01011 /* Someone else has meanwhile built a new hash index on the 01012 page, with different parameters */ 01013 01014 rw_lock_x_unlock(&btr_search_latch); 01015 01016 mem_free(folds); 01017 goto retry; 01018 } 01019 01020 for (i = 0; i < n_cached; i++) { 01021 01022 ha_remove_all_nodes_to_page(table, folds[i], page); 01023 } 01024 01025 block->is_hashed = FALSE; 01026 block->index = NULL; 01027 cleanup: 01028 if (UNIV_UNLIKELY(block->n_pointers)) { 01029 /* Corruption */ 01030 ut_print_timestamp(stderr); 01031 fprintf(stderr, 01032 " InnoDB: Corruption of adaptive hash index. After dropping\n" 01033 "InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n", 01034 index->name, (ulong) block->n_pointers); 01035 rw_lock_x_unlock(&btr_search_latch); 01036 01037 btr_search_validate(); 01038 } else { 01039 rw_lock_x_unlock(&btr_search_latch); 01040 } 01041 01042 mem_free(folds); 01043 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1050 of file btr0sea.c.
References btr_search_drop_page_hash_index(), BUF_GET_IF_IN_POOL, buf_page_get_gen(), buf_page_peek_if_search_hashed(), mtr_commit(), mtr_start(), NULL, page, page_t, RW_S_LATCH, and SYNC_TREE_NODE_FROM_HASH.
Referenced by buf_LRU_invalidate_tablespace(), fseg_free_extent(), and fseg_free_page_low().
01052 : space id */ 01053 ulint page_no) /* in: page number */ 01054 { 01055 ibool is_hashed; 01056 page_t* page; 01057 mtr_t mtr; 01058 01059 is_hashed = buf_page_peek_if_search_hashed(space, page_no); 01060 01061 if (!is_hashed) { 01062 01063 return; 01064 } 01065 01066 mtr_start(&mtr); 01067 01068 /* We assume that if the caller has a latch on the page, then the 01069 caller has already dropped the hash index for the page, and we never 01070 get here. Therefore we can acquire the s-latch to the page without 01071 having to fear a deadlock. */ 01072 01073 page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL, 01074 BUF_GET_IF_IN_POOL, __FILE__, __LINE__, 01075 &mtr); 01076 01077 #ifdef UNIV_SYNC_DEBUG 01078 buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); 01079 #endif /* UNIV_SYNC_DEBUG */ 01080 01081 btr_search_drop_page_hash_index(page); 01082 01083 mtr_commit(&mtr); 01084 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool btr_search_guess_on_hash | ( | dict_index_t * | index, | |
| btr_search_t * | info, | |||
| dtuple_t * | tuple, | |||
| ulint | mode, | |||
| ulint | latch_mode, | |||
| btr_cur_t * | cursor, | |||
| ulint | has_search_latch, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 680 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), BTR_CUR_HASH, BTR_CUR_HASH_FAIL, btr_cur_position(), btr_cur_search_to_nth_level(), btr_leaf_page_release(), BTR_MODIFY_LEAF, btr_page_get_index_id(), btr_pcur_get_rec(), btr_pcur_open_on_user_rec(), BTR_SEARCH_BUILD_LIMIT, btr_search_check_guess(), btr_search_latch, BTR_SEARCH_LEAF, btr_search_sys, buf_block_align(), BUF_BLOCK_FILE_PAGE, buf_block_peek_if_too_old(), BUF_BLOCK_REMOVE_HASH, buf_frame_align(), BUF_MAKE_YOUNG, buf_page_get_known_nowait(), buf_page_make_young(), buf_pool, dtuple_fold(), dtuple_get_n_fields(), FALSE, btr_cur_struct::flag, btr_cur_struct::fold, ha_search_and_get_data(), btr_search_sys_struct::hash_index, index(), btr_search_struct::last_hash_succ, btr_cur_struct::n_bytes, btr_search_struct::n_bytes, btr_cur_struct::n_fields, btr_search_struct::n_fields, btr_search_struct::n_hash_potential, buf_pool_struct::n_page_gets, page, PAGE_CUR_GE, page_rec_is_supremum(), page_rec_is_user_rec(), page_t, RW_LOCK_EX, rw_lock_s_lock, rw_lock_s_unlock, SYNC_TREE_NODE_FROM_HASH, TRUE, ut_ad, and ut_dulint_cmp().
Referenced by btr_cur_search_to_nth_level().
00682 : TRUE if succeeded */ 00683 dict_index_t* index, /* in: index */ 00684 btr_search_t* info, /* in: index search info */ 00685 dtuple_t* tuple, /* in: logical record */ 00686 ulint mode, /* in: PAGE_CUR_L, ... */ 00687 ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...; 00688 NOTE that only if has_search_latch 00689 is 0, we will have a latch set on 00690 the cursor page, otherwise we assume 00691 the caller uses his search latch 00692 to protect the record! */ 00693 btr_cur_t* cursor, /* out: tree cursor */ 00694 ulint has_search_latch,/* in: latch mode the caller 00695 currently has on btr_search_latch: 00696 RW_S_LATCH, RW_X_LATCH, or 0 */ 00697 mtr_t* mtr) /* in: mtr */ 00698 { 00699 buf_block_t* block; 00700 rec_t* rec; 00701 page_t* page; 00702 ulint fold; 00703 ulint tuple_n_fields; 00704 dulint tree_id; 00705 ibool can_only_compare_to_cursor_rec = TRUE; 00706 #ifdef notdefined 00707 btr_cur_t cursor2; 00708 btr_pcur_t pcur; 00709 #endif 00710 ut_ad(index && info && tuple && cursor && mtr); 00711 ut_ad((latch_mode == BTR_SEARCH_LEAF) 00712 || (latch_mode == BTR_MODIFY_LEAF)); 00713 00714 /* Note that, for efficiency, the struct info may not be protected by 00715 any latch here! */ 00716 00717 if (UNIV_UNLIKELY(info->n_hash_potential == 0)) { 00718 00719 return(FALSE); 00720 } 00721 00722 cursor->n_fields = info->n_fields; 00723 cursor->n_bytes = info->n_bytes; 00724 00725 tuple_n_fields = dtuple_get_n_fields(tuple); 00726 00727 if (UNIV_UNLIKELY(tuple_n_fields < cursor->n_fields)) { 00728 00729 return(FALSE); 00730 } 00731 00732 if (UNIV_UNLIKELY(tuple_n_fields == cursor->n_fields) 00733 && (cursor->n_bytes > 0)) { 00734 00735 return(FALSE); 00736 } 00737 00738 tree_id = (index->tree)->id; 00739 00740 #ifdef UNIV_SEARCH_PERF_STAT 00741 info->n_hash_succ++; 00742 #endif 00743 fold = dtuple_fold(tuple, cursor->n_fields, cursor->n_bytes, tree_id); 00744 00745 cursor->fold = fold; 00746 cursor->flag = BTR_CUR_HASH; 00747 00748 if (UNIV_LIKELY(!has_search_latch)) { 00749 rw_lock_s_lock(&btr_search_latch); 00750 } 00751 00752 ut_ad(btr_search_latch.writer != RW_LOCK_EX); 00753 ut_ad(btr_search_latch.reader_count > 0); 00754 00755 rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); 00756 00757 if (UNIV_UNLIKELY(!rec)) { 00758 goto failure_unlock; 00759 } 00760 00761 page = buf_frame_align(rec); 00762 00763 if (UNIV_LIKELY(!has_search_latch)) { 00764 00765 if (UNIV_UNLIKELY(!buf_page_get_known_nowait(latch_mode, page, 00766 BUF_MAKE_YOUNG, 00767 __FILE__, __LINE__, 00768 mtr))) { 00769 goto failure_unlock; 00770 } 00771 00772 rw_lock_s_unlock(&btr_search_latch); 00773 can_only_compare_to_cursor_rec = FALSE; 00774 00775 #ifdef UNIV_SYNC_DEBUG 00776 buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); 00777 #endif /* UNIV_SYNC_DEBUG */ 00778 } 00779 00780 block = buf_block_align(page); 00781 00782 if (UNIV_UNLIKELY(block->state == BUF_BLOCK_REMOVE_HASH)) { 00783 if (UNIV_LIKELY(!has_search_latch)) { 00784 00785 btr_leaf_page_release(page, latch_mode, mtr); 00786 } 00787 00788 goto failure; 00789 } 00790 00791 ut_ad(block->state == BUF_BLOCK_FILE_PAGE); 00792 ut_ad(page_rec_is_user_rec(rec)); 00793 00794 btr_cur_position(index, rec, cursor); 00795 00796 /* Check the validity of the guess within the page */ 00797 00798 /* If we only have the latch on btr_search_latch, not on the 00799 page, it only protects the columns of the record the cursor 00800 is positioned on. We cannot look at the next of the previous 00801 record to determine if our guess for the cursor position is 00802 right. */ 00803 if (UNIV_EXPECT(ut_dulint_cmp(tree_id, btr_page_get_index_id(page)), 0) 00804 || !btr_search_check_guess(cursor, 00805 can_only_compare_to_cursor_rec, tuple, mode, mtr)) { 00806 if (UNIV_LIKELY(!has_search_latch)) { 00807 btr_leaf_page_release(page, latch_mode, mtr); 00808 } 00809 00810 goto failure; 00811 } 00812 00813 if (UNIV_LIKELY(info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5)) { 00814 00815 info->n_hash_potential++; 00816 } 00817 00818 #ifdef notdefined 00819 /* These lines of code can be used in a debug version to check 00820 the correctness of the searched cursor position: */ 00821 00822 info->last_hash_succ = FALSE; 00823 00824 /* Currently, does not work if the following fails: */ 00825 ut_ad(!has_search_latch); 00826 00827 btr_leaf_page_release(page, latch_mode, mtr); 00828 00829 btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, 00830 &cursor2, 0, mtr); 00831 if (mode == PAGE_CUR_GE 00832 && page_rec_is_supremum(btr_cur_get_rec(&cursor2))) { 00833 00834 /* If mode is PAGE_CUR_GE, then the binary search 00835 in the index tree may actually take us to the supremum 00836 of the previous page */ 00837 00838 info->last_hash_succ = FALSE; 00839 00840 btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, 00841 &pcur, mtr); 00842 ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor)); 00843 } else { 00844 ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); 00845 } 00846 00847 /* NOTE that it is theoretically possible that the above assertions 00848 fail if the page of the cursor gets removed from the buffer pool 00849 meanwhile! Thus it might not be a bug. */ 00850 #endif 00851 info->last_hash_succ = TRUE; 00852 00853 #ifdef UNIV_SEARCH_PERF_STAT 00854 btr_search_n_succ++; 00855 #endif 00856 if (UNIV_LIKELY(!has_search_latch) 00857 && buf_block_peek_if_too_old(block)) { 00858 00859 buf_page_make_young(page); 00860 } 00861 00862 /* Increment the page get statistics though we did not really 00863 fix the page: for user info only */ 00864 00865 buf_pool->n_page_gets++; 00866 00867 return(TRUE); 00868 00869 /*-------------------------------------------*/ 00870 failure_unlock: 00871 if (UNIV_LIKELY(!has_search_latch)) { 00872 rw_lock_s_unlock(&btr_search_latch); 00873 } 00874 failure: 00875 cursor->flag = BTR_CUR_HASH_FAIL; 00876 00877 #ifdef UNIV_SEARCH_PERF_STAT 00878 info->n_hash_fail++; 00879 00880 if (info->n_hash_succ > 0) { 00881 info->n_hash_succ--; 00882 } 00883 #endif 00884 info->last_hash_succ = FALSE; 00885 00886 return(FALSE); 00887 }
Here is the call graph for this function:

Here is the caller graph for this function:

| btr_search_t* btr_search_info_create | ( | mem_heap_t * | heap | ) |
Definition at line 151 of file btr0sea.c.
References BTR_SEARCH_LEFT_SIDE, BTR_SEARCH_MAGIC_N, FALSE, btr_search_struct::hash_analysis, info, btr_search_struct::last_hash_succ, btr_search_struct::last_search, btr_search_struct::magic_n, mem_heap_alloc(), btr_search_struct::n_bytes, btr_search_struct::n_direction, btr_search_struct::n_fields, btr_search_struct::n_hash_potential, NULL, btr_search_struct::root_guess, and btr_search_struct::side.
Referenced by dict_index_add_to_cache().
00153 : search info struct */ 00154 mem_heap_t* heap) /* in: heap where created */ 00155 { 00156 btr_search_t* info; 00157 00158 info = mem_heap_alloc(heap, sizeof(btr_search_t)); 00159 00160 info->magic_n = BTR_SEARCH_MAGIC_N; 00161 00162 info->last_search = NULL; 00163 info->n_direction = 0; 00164 info->root_guess = NULL; 00165 00166 info->hash_analysis = 0; 00167 info->n_hash_potential = 0; 00168 00169 info->last_hash_succ = FALSE; 00170 00171 #ifdef UNIV_SEARCH_PERF_STAT 00172 info->n_hash_succ = 0; 00173 info->n_hash_fail = 0; 00174 info->n_patt_succ = 0; 00175 info->n_searches = 0; 00176 #endif /* UNIV_SEARCH_PERF_STAT */ 00177 00178 /* Set some sensible values */ 00179 info->n_fields = 1; 00180 info->n_bytes = 0; 00181 00182 info->side = BTR_SEARCH_LEFT_SIDE; 00183 00184 return(info); 00185 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_search_info_update_hash | ( | btr_search_t * | info, | |
| btr_cur_t * | cursor | |||
| ) | [static] |
Definition at line 193 of file btr0sea.c.
References btr_search_latch, BTR_SEARCH_LEFT_SIDE, BTR_SEARCH_RIGHT_SIDE, cmp, DICT_IBUF, dict_index_get_n_unique_in_tree(), btr_search_struct::hash_analysis, btr_cur_struct::index, index(), btr_cur_struct::low_bytes, btr_cur_struct::low_match, btr_search_struct::n_bytes, btr_search_struct::n_fields, btr_search_struct::n_hash_potential, RW_LOCK_EX, RW_LOCK_SHARED, btr_search_struct::side, btr_cur_struct::up_bytes, btr_cur_struct::up_match, ut_ad, and ut_pair_cmp().
Referenced by btr_search_info_update_slow().
00195 : search info */ 00196 btr_cur_t* cursor) /* in: cursor which was just positioned */ 00197 { 00198 dict_index_t* index; 00199 ulint n_unique; 00200 int cmp; 00201 00202 #ifdef UNIV_SYNC_DEBUG 00203 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); 00204 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00205 #endif /* UNIV_SYNC_DEBUG */ 00206 00207 index = cursor->index; 00208 00209 if (index->type & DICT_IBUF) { 00210 /* So many deletes are performed on an insert buffer tree 00211 that we do not consider a hash index useful on it: */ 00212 00213 return; 00214 } 00215 00216 n_unique = dict_index_get_n_unique_in_tree(index); 00217 00218 if (info->n_hash_potential == 0) { 00219 00220 goto set_new_recomm; 00221 } 00222 00223 /* Test if the search would have succeeded using the recommended 00224 hash prefix */ 00225 00226 if (info->n_fields >= n_unique && cursor->up_match >= n_unique) { 00227 00228 info->n_hash_potential++; 00229 00230 return; 00231 } 00232 00233 cmp = ut_pair_cmp(info->n_fields, info->n_bytes, 00234 cursor->low_match, cursor->low_bytes); 00235 00236 if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp <= 0) 00237 || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp > 0)) { 00238 00239 goto set_new_recomm; 00240 } 00241 00242 cmp = ut_pair_cmp(info->n_fields, info->n_bytes, 00243 cursor->up_match, cursor->up_bytes); 00244 00245 if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp > 0) 00246 || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp <= 0)) { 00247 00248 goto set_new_recomm; 00249 } 00250 00251 info->n_hash_potential++; 00252 00253 return; 00254 00255 set_new_recomm: 00256 /* We have to set a new recommendation; skip the hash analysis 00257 for a while to avoid unnecessary CPU time usage when there is no 00258 chance for success */ 00259 00260 info->hash_analysis = 0; 00261 00262 cmp = ut_pair_cmp(cursor->up_match, cursor->up_bytes, 00263 cursor->low_match, cursor->low_bytes); 00264 if (cmp == 0) { 00265 info->n_hash_potential = 0; 00266 00267 /* For extra safety, we set some sensible values here */ 00268 00269 info->n_fields = 1; 00270 info->n_bytes = 0; 00271 00272 info->side = BTR_SEARCH_LEFT_SIDE; 00273 00274 } else if (cmp > 0) { 00275 info->n_hash_potential = 1; 00276 00277 if (cursor->up_match >= n_unique) { 00278 00279 info->n_fields = n_unique; 00280 info->n_bytes = 0; 00281 00282 } else if (cursor->low_match < cursor->up_match) { 00283 00284 info->n_fields = cursor->low_match + 1; 00285 info->n_bytes = 0; 00286 } else { 00287 info->n_fields = cursor->low_match; 00288 info->n_bytes = cursor->low_bytes + 1; 00289 } 00290 00291 info->side = BTR_SEARCH_LEFT_SIDE; 00292 } else { 00293 info->n_hash_potential = 1; 00294 00295 if (cursor->low_match >= n_unique) { 00296 00297 info->n_fields = n_unique; 00298 info->n_bytes = 0; 00299 00300 } else if (cursor->low_match > cursor->up_match) { 00301 00302 info->n_fields = cursor->up_match + 1; 00303 info->n_bytes = 0; 00304 } else { 00305 info->n_fields = cursor->up_match; 00306 info->n_bytes = cursor->up_bytes + 1; 00307 } 00308 00309 info->side = BTR_SEARCH_RIGHT_SIDE; 00310 } 00311 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_info_update_slow | ( | btr_search_t * | info, | |
| btr_cur_t * | cursor | |||
| ) |
Definition at line 454 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), BTR_CUR_HASH_FAIL, btr_search_build_page_hash_index(), btr_search_check_free_space_in_heap(), btr_search_info_update_hash(), btr_search_latch, btr_search_this_is_zero, btr_search_update_block_hash_info(), btr_search_update_hash_ref(), buf_block_align(), btr_cur_struct::flag, btr_cur_struct::index, mem_alloc, mem_free, RW_LOCK_EX, RW_LOCK_SHARED, rw_lock_x_lock, rw_lock_x_unlock, and ut_ad.
00456 : search info */ 00457 btr_cur_t* cursor) /* in: cursor which was just positioned */ 00458 { 00459 buf_block_t* block; 00460 ibool build_index; 00461 ulint* params; 00462 ulint* params2; 00463 00464 #ifdef UNIV_SYNC_DEBUG 00465 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); 00466 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00467 #endif /* UNIV_SYNC_DEBUG */ 00468 00469 block = buf_block_align(btr_cur_get_rec(cursor)); 00470 00471 /* NOTE that the following two function calls do NOT protect 00472 info or block->n_fields etc. with any semaphore, to save CPU time! 00473 We cannot assume the fields are consistent when we return from 00474 those functions! */ 00475 00476 btr_search_info_update_hash(info, cursor); 00477 00478 build_index = btr_search_update_block_hash_info(info, block, cursor); 00479 00480 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) { 00481 00482 btr_search_check_free_space_in_heap(); 00483 } 00484 00485 if (cursor->flag == BTR_CUR_HASH_FAIL) { 00486 /* Update the hash node reference, if appropriate */ 00487 00488 #ifdef UNIV_SEARCH_PERF_STAT 00489 btr_search_n_hash_fail++; 00490 #endif /* UNIV_SEARCH_PERF_STAT */ 00491 00492 rw_lock_x_lock(&btr_search_latch); 00493 00494 btr_search_update_hash_ref(info, block, cursor); 00495 00496 rw_lock_x_unlock(&btr_search_latch); 00497 } 00498 00499 if (build_index) { 00500 /* Note that since we did not protect block->n_fields etc. 00501 with any semaphore, the values can be inconsistent. We have 00502 to check inside the function call that they make sense. We 00503 also malloc an array and store the values there to make sure 00504 the compiler does not let the function call parameters change 00505 inside the called function. It might be that the compiler 00506 would optimize the call just to pass pointers to block. */ 00507 00508 params = mem_alloc(3 * sizeof(ulint)); 00509 params[0] = block->n_fields; 00510 params[1] = block->n_bytes; 00511 params[2] = block->side; 00512 00513 /* Make sure the compiler cannot deduce the values and do 00514 optimizations */ 00515 00516 params2 = params + btr_search_this_is_zero; 00517 00518 btr_search_build_page_hash_index(cursor->index, 00519 block->frame, 00520 params2[0], 00521 params2[1], 00522 params2[2]); 00523 mem_free(params); 00524 } 00525 }
Here is the call graph for this function:

| void btr_search_move_or_delete_hash_entries | ( | page_t * | new_page, | |
| page_t * | page, | |||
| dict_index_t * | index | |||
| ) |
Definition at line 1277 of file btr0sea.c.
References yaSSL::block, btr_search_build_page_hash_index(), btr_search_drop_page_hash_index(), btr_search_latch, buf_block_align(), buf_block_struct::index, index(), buf_block_struct::is_hashed, buf_block_struct::lock, buf_block_struct::n_bytes, buf_block_struct::n_fields, page_is_comp(), RW_LOCK_EX, rw_lock_s_lock, rw_lock_s_unlock, buf_block_struct::side, ut_a, and ut_ad.
Referenced by page_copy_rec_list_end(), and page_copy_rec_list_start().
01279 : records are copied 01280 to this page */ 01281 page_t* page, /* in: index page from which 01282 records were copied, and the 01283 copied records will be deleted 01284 from this page */ 01285 dict_index_t* index) /* in: record descriptor */ 01286 { 01287 buf_block_t* block; 01288 buf_block_t* new_block; 01289 ulint n_fields; 01290 ulint n_bytes; 01291 ulint side; 01292 01293 block = buf_block_align(page); 01294 new_block = buf_block_align(new_page); 01295 ut_a(page_is_comp(page) == page_is_comp(new_page)); 01296 01297 #ifdef UNIV_SYNC_DEBUG 01298 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); 01299 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX)); 01300 #endif /* UNIV_SYNC_DEBUG */ 01301 ut_a(!new_block->is_hashed || new_block->index == index); 01302 ut_a(!block->is_hashed || block->index == index); 01303 01304 rw_lock_s_lock(&btr_search_latch); 01305 01306 if (new_block->is_hashed) { 01307 01308 rw_lock_s_unlock(&btr_search_latch); 01309 01310 btr_search_drop_page_hash_index(page); 01311 01312 return; 01313 } 01314 01315 if (block->is_hashed) { 01316 01317 n_fields = block->curr_n_fields; 01318 n_bytes = block->curr_n_bytes; 01319 side = block->curr_side; 01320 01321 new_block->n_fields = block->curr_n_fields; 01322 new_block->n_bytes = block->curr_n_bytes; 01323 new_block->side = block->curr_side; 01324 01325 rw_lock_s_unlock(&btr_search_latch); 01326 01327 ut_a(n_fields + n_bytes > 0); 01328 01329 btr_search_build_page_hash_index(index, new_page, n_fields, 01330 n_bytes, side); 01331 ut_a(n_fields == block->curr_n_fields); 01332 ut_a(n_bytes == block->curr_n_bytes); 01333 ut_a(side == block->curr_side); 01334 01335 return; 01336 } 01337 01338 rw_lock_s_unlock(&btr_search_latch); 01339 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_sys_create | ( | ulint | hash_size | ) |
Definition at line 130 of file btr0sea.c.
References btr_search_latch, btr_search_latch_temp, btr_search_sys, ha_create(), btr_search_sys_struct::hash_index, mem_alloc, rw_lock_create, SYNC_SEARCH_SYS, and TRUE.
00132 : hash index hash table size */ 00133 { 00134 /* We allocate the search latch from dynamic memory: 00135 see above at the global variable definition */ 00136 00137 btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); 00138 00139 rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS); 00140 00141 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); 00142 00143 btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0); 00144 00145 }
Here is the call graph for this function:

| static ibool btr_search_update_block_hash_info | ( | btr_search_t * | info, | |
| buf_block_t * | block, | |||
| btr_cur_t * | cursor | |||
| ) | [static] |
Definition at line 319 of file btr0sea.c.
References yaSSL::block, BTR_SEARCH_BUILD_LIMIT, btr_search_latch, BTR_SEARCH_MAGIC_N, BTR_SEARCH_PAGE_BUILD_LIMIT, BUF_BLOCK_MAGIC_N, dict_table_struct::does_not_fit_in_memory, FALSE, btr_cur_struct::index, btr_search_struct::last_hash_succ, lock, btr_search_struct::magic_n, btr_search_struct::n_bytes, btr_search_struct::n_fields, btr_search_struct::n_hash_potential, page_get_n_recs(), RW_LOCK_EX, RW_LOCK_SHARED, btr_search_struct::side, dict_index_struct::table, TRUE, ut_a, and ut_ad.
Referenced by btr_search_info_update_slow().
00321 : TRUE if building a (new) hash index on 00322 the block is recommended */ 00323 btr_search_t* info, /* in: search info */ 00324 buf_block_t* block, /* in: buffer block */ 00325 btr_cur_t* cursor) /* in: cursor */ 00326 { 00327 #ifdef UNIV_SYNC_DEBUG 00328 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); 00329 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00330 ut_ad(rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_SHARED) 00331 || rw_lock_own(&((buf_block_t*) block)->lock, RW_LOCK_EX)); 00332 #endif /* UNIV_SYNC_DEBUG */ 00333 ut_ad(cursor); 00334 00335 info->last_hash_succ = FALSE; 00336 00337 ut_a(block->magic_n == BUF_BLOCK_MAGIC_N); 00338 ut_a(info->magic_n == BTR_SEARCH_MAGIC_N); 00339 00340 if ((block->n_hash_helps > 0) 00341 && (info->n_hash_potential > 0) 00342 && (block->n_fields == info->n_fields) 00343 && (block->n_bytes == info->n_bytes) 00344 && (block->side == info->side)) { 00345 00346 if ((block->is_hashed) 00347 && (block->curr_n_fields == info->n_fields) 00348 && (block->curr_n_bytes == info->n_bytes) 00349 && (block->curr_side == info->side)) { 00350 00351 /* The search would presumably have succeeded using 00352 the hash index */ 00353 00354 info->last_hash_succ = TRUE; 00355 } 00356 00357 block->n_hash_helps++; 00358 } else { 00359 block->n_hash_helps = 1; 00360 block->n_fields = info->n_fields; 00361 block->n_bytes = info->n_bytes; 00362 block->side = info->side; 00363 } 00364 00365 if (cursor->index->table->does_not_fit_in_memory) { 00366 block->n_hash_helps = 0; 00367 } 00368 00369 if ((block->n_hash_helps > page_get_n_recs(block->frame) 00370 / BTR_SEARCH_PAGE_BUILD_LIMIT) 00371 && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { 00372 00373 if ((!block->is_hashed) 00374 || (block->n_hash_helps 00375 > 2 * page_get_n_recs(block->frame)) 00376 || (block->n_fields != block->curr_n_fields) 00377 || (block->n_bytes != block->curr_n_bytes) 00378 || (block->side != block->curr_side)) { 00379 00380 /* Build a new hash index on the page */ 00381 00382 return(TRUE); 00383 } 00384 } 00385 00386 return(FALSE); 00387 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_update_hash_node_on_insert | ( | btr_cur_t * | cursor | ) |
Definition at line 1397 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), BTR_CUR_HASH, btr_search_latch, BTR_SEARCH_RIGHT_SIDE, btr_search_sys, btr_search_update_hash_on_insert(), buf_block_align(), btr_cur_struct::flag, btr_cur_struct::fold, ha_search_and_update_if_found(), btr_search_sys_struct::hash_index, btr_cur_struct::index, btr_cur_struct::n_bytes, btr_cur_struct::n_fields, page_rec_get_next(), RW_LOCK_EX, rw_lock_x_lock, rw_lock_x_unlock, ut_a, and ut_ad.
Referenced by btr_cur_optimistic_insert().
01399 : cursor which was positioned to the 01400 place to insert using btr_cur_search_..., 01401 and the new record has been inserted next 01402 to the cursor */ 01403 { 01404 hash_table_t* table; 01405 buf_block_t* block; 01406 rec_t* rec; 01407 01408 rec = btr_cur_get_rec(cursor); 01409 01410 block = buf_block_align(rec); 01411 01412 #ifdef UNIV_SYNC_DEBUG 01413 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); 01414 #endif /* UNIV_SYNC_DEBUG */ 01415 01416 if (!block->is_hashed) { 01417 01418 return; 01419 } 01420 01421 ut_a(block->index == cursor->index); 01422 01423 rw_lock_x_lock(&btr_search_latch); 01424 01425 if ((cursor->flag == BTR_CUR_HASH) 01426 && (cursor->n_fields == block->curr_n_fields) 01427 && (cursor->n_bytes == block->curr_n_bytes) 01428 && (block->curr_side == BTR_SEARCH_RIGHT_SIDE)) { 01429 01430 table = btr_search_sys->hash_index; 01431 01432 ha_search_and_update_if_found(table, cursor->fold, rec, 01433 page_rec_get_next(rec)); 01434 01435 rw_lock_x_unlock(&btr_search_latch); 01436 } else { 01437 rw_lock_x_unlock(&btr_search_latch); 01438 01439 btr_search_update_hash_on_insert(cursor); 01440 } 01441 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_update_hash_on_delete | ( | btr_cur_t * | cursor | ) |
Definition at line 1345 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), btr_search_latch, btr_search_sys, buf_block_align(), ha_search_and_delete_if_found(), btr_search_sys_struct::hash_index, dict_tree_struct::id, btr_cur_struct::index, mem_heap_free, NULL, rec_fold(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_LOCK_EX, rw_lock_x_lock, rw_lock_x_unlock, dict_index_struct::tree, ut_a, and ut_ad.
Referenced by btr_cur_optimistic_delete(), btr_cur_optimistic_update(), btr_cur_pessimistic_delete(), btr_cur_pessimistic_update(), and btr_cur_update_in_place().
01347 : cursor which was positioned on the 01348 record to delete using btr_cur_search_..., 01349 the record is not yet deleted */ 01350 { 01351 hash_table_t* table; 01352 buf_block_t* block; 01353 rec_t* rec; 01354 ulint fold; 01355 dulint tree_id; 01356 ibool found; 01357 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01358 mem_heap_t* heap = NULL; 01359 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01360 01361 rec = btr_cur_get_rec(cursor); 01362 01363 block = buf_block_align(rec); 01364 01365 #ifdef UNIV_SYNC_DEBUG 01366 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); 01367 #endif /* UNIV_SYNC_DEBUG */ 01368 01369 if (!block->is_hashed) { 01370 01371 return; 01372 } 01373 01374 ut_a(block->index == cursor->index); 01375 ut_a(block->curr_n_fields + block->curr_n_bytes > 0); 01376 01377 table = btr_search_sys->hash_index; 01378 01379 tree_id = cursor->index->tree->id; 01380 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, 01381 ULINT_UNDEFINED, &heap), block->curr_n_fields, 01382 block->curr_n_bytes, tree_id); 01383 if (UNIV_LIKELY_NULL(heap)) { 01384 mem_heap_free(heap); 01385 } 01386 rw_lock_x_lock(&btr_search_latch); 01387 01388 found = ha_search_and_delete_if_found(table, fold, rec); 01389 01390 rw_lock_x_unlock(&btr_search_latch); 01391 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_search_update_hash_on_insert | ( | btr_cur_t * | cursor | ) |
Definition at line 1447 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), btr_search_check_free_space_in_heap(), btr_search_latch, BTR_SEARCH_LEFT_SIDE, BTR_SEARCH_RIGHT_SIDE, btr_search_sys, buf_block_align(), FALSE, ha_insert_for_fold(), btr_search_sys_struct::hash_index, btr_cur_struct::index, mem_heap_free, NULL, page_rec_get_next(), page_rec_is_infimum(), page_rec_is_supremum(), rec_fold(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_LOCK_EX, rw_lock_x_lock, rw_lock_x_unlock, TRUE, ut_a, and ut_ad.
Referenced by btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(), and btr_search_update_hash_node_on_insert().
01449 : cursor which was positioned to the 01450 place to insert using btr_cur_search_..., 01451 and the new record has been inserted next 01452 to the cursor */ 01453 { 01454 hash_table_t* table; 01455 buf_block_t* block; 01456 rec_t* rec; 01457 rec_t* ins_rec; 01458 rec_t* next_rec; 01459 dulint tree_id; 01460 ulint fold; 01461 ulint ins_fold; 01462 ulint next_fold = 0; /* remove warning (??? bug ???) */ 01463 ulint n_fields; 01464 ulint n_bytes; 01465 ulint side; 01466 ibool locked = FALSE; 01467 mem_heap_t* heap = NULL; 01468 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01469 ulint* offsets = offsets_; 01470 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01471 01472 table = btr_search_sys->hash_index; 01473 01474 btr_search_check_free_space_in_heap(); 01475 01476 rec = btr_cur_get_rec(cursor); 01477 01478 block = buf_block_align(rec); 01479 01480 #ifdef UNIV_SYNC_DEBUG 01481 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); 01482 #endif /* UNIV_SYNC_DEBUG */ 01483 01484 if (!block->is_hashed) { 01485 01486 return; 01487 } 01488 01489 ut_a(block->index == cursor->index); 01490 01491 tree_id = ((cursor->index)->tree)->id; 01492 01493 n_fields = block->curr_n_fields; 01494 n_bytes = block->curr_n_bytes; 01495 side = block->curr_side; 01496 01497 ins_rec = page_rec_get_next(rec); 01498 next_rec = page_rec_get_next(ins_rec); 01499 01500 offsets = rec_get_offsets(ins_rec, cursor->index, offsets, 01501 ULINT_UNDEFINED, &heap); 01502 ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id); 01503 01504 if (!page_rec_is_supremum(next_rec)) { 01505 offsets = rec_get_offsets(next_rec, cursor->index, offsets, 01506 n_fields + (n_bytes > 0), &heap); 01507 next_fold = rec_fold(next_rec, offsets, n_fields, 01508 n_bytes, tree_id); 01509 } 01510 01511 if (!page_rec_is_infimum(rec)) { 01512 offsets = rec_get_offsets(rec, cursor->index, offsets, 01513 n_fields + (n_bytes > 0), &heap); 01514 fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id); 01515 } else { 01516 if (side == BTR_SEARCH_LEFT_SIDE) { 01517 01518 rw_lock_x_lock(&btr_search_latch); 01519 01520 locked = TRUE; 01521 01522 ha_insert_for_fold(table, ins_fold, ins_rec); 01523 } 01524 01525 goto check_next_rec; 01526 } 01527 01528 if (fold != ins_fold) { 01529 01530 if (!locked) { 01531 01532 rw_lock_x_lock(&btr_search_latch); 01533 01534 locked = TRUE; 01535 } 01536 01537 if (side == BTR_SEARCH_RIGHT_SIDE) { 01538 ha_insert_for_fold(table, fold, rec); 01539 } else { 01540 ha_insert_for_fold(table, ins_fold, ins_rec); 01541 } 01542 } 01543 01544 check_next_rec: 01545 if (page_rec_is_supremum(next_rec)) { 01546 01547 if (side == BTR_SEARCH_RIGHT_SIDE) { 01548 01549 if (!locked) { 01550 rw_lock_x_lock(&btr_search_latch); 01551 01552 locked = TRUE; 01553 } 01554 01555 ha_insert_for_fold(table, ins_fold, ins_rec); 01556 } 01557 01558 goto function_exit; 01559 } 01560 01561 if (ins_fold != next_fold) { 01562 01563 if (!locked) { 01564 01565 rw_lock_x_lock(&btr_search_latch); 01566 01567 locked = TRUE; 01568 } 01569 01570 if (side == BTR_SEARCH_RIGHT_SIDE) { 01571 01572 ha_insert_for_fold(table, ins_fold, ins_rec); 01573 /* 01574 fputs("Hash insert for ", stderr); 01575 dict_index_name_print(stderr, cursor->index); 01576 fprintf(stderr, " fold %lu\n", ins_fold); 01577 */ 01578 } else { 01579 ha_insert_for_fold(table, next_fold, next_rec); 01580 } 01581 } 01582 01583 function_exit: 01584 if (UNIV_LIKELY_NULL(heap)) { 01585 mem_heap_free(heap); 01586 } 01587 if (locked) { 01588 rw_lock_x_unlock(&btr_search_latch); 01589 } 01590 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_search_update_hash_ref | ( | btr_search_t * | info, | |
| buf_block_t * | block, | |||
| btr_cur_t * | cursor | |||
| ) | [static] |
Definition at line 399 of file btr0sea.c.
References yaSSL::block, btr_cur_get_rec(), BTR_CUR_HASH_FAIL, btr_search_latch, btr_search_sys, buf_block_align(), btr_cur_struct::flag, ha_insert_for_fold(), btr_search_sys_struct::hash_index, btr_cur_struct::index, mem_heap_free, btr_search_struct::n_bytes, btr_search_struct::n_fields, btr_search_struct::n_hash_potential, NULL, page_rec_is_user_rec(), rec_fold(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_LOCK_EX, RW_LOCK_SHARED, btr_search_struct::side, ut_a, and ut_ad.
Referenced by btr_search_info_update_slow().
00401 : search info */ 00402 buf_block_t* block, /* in: buffer block where cursor positioned */ 00403 btr_cur_t* cursor) /* in: cursor */ 00404 { 00405 ulint fold; 00406 rec_t* rec; 00407 dulint tree_id; 00408 00409 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL); 00410 #ifdef UNIV_SYNC_DEBUG 00411 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00412 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) 00413 || rw_lock_own(&(block->lock), RW_LOCK_EX)); 00414 #endif /* UNIV_SYNC_DEBUG */ 00415 ut_ad(buf_block_align(btr_cur_get_rec(cursor)) == block); 00416 ut_a(!block->is_hashed || block->index == cursor->index); 00417 00418 if (block->is_hashed 00419 && (info->n_hash_potential > 0) 00420 && (block->curr_n_fields == info->n_fields) 00421 && (block->curr_n_bytes == info->n_bytes) 00422 && (block->curr_side == info->side)) { 00423 mem_heap_t* heap = NULL; 00424 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00425 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00426 00427 rec = btr_cur_get_rec(cursor); 00428 00429 if (!page_rec_is_user_rec(rec)) { 00430 00431 return; 00432 } 00433 00434 tree_id = ((cursor->index)->tree)->id; 00435 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, 00436 offsets_, ULINT_UNDEFINED, &heap), 00437 block->curr_n_fields, 00438 block->curr_n_bytes, tree_id); 00439 if (UNIV_LIKELY_NULL(heap)) { 00440 mem_heap_free(heap); 00441 } 00442 #ifdef UNIV_SYNC_DEBUG 00443 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); 00444 #endif /* UNIV_SYNC_DEBUG */ 00445 00446 ha_insert_for_fold(btr_search_sys->hash_index, fold, rec); 00447 } 00448 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool btr_search_validate | ( | void | ) |
Definition at line 1596 of file btr0sea.c.
References yaSSL::block, btr_page_get_index_id(), btr_search_latch, btr_search_sys, buf_block_align(), buf_frame_align(), buf_frame_get_page_no(), buf_page_print(), ha_node_struct::data, FALSE, ha_node_struct::fold, ha_validate(), hash_get_n_cells(), hash_get_nth_cell(), btr_search_sys_struct::hash_index, mem_heap_free, ha_node_struct::next, hash_cell_struct::node, NULL, ok(), os_thread_yield(), page, page_t, rec_fold(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_print_new(), rw_lock_x_lock, rw_lock_x_unlock, TRUE, ut_dulint_get_high(), ut_dulint_get_low(), ut_min(), and ut_print_timestamp().
Referenced by btr_search_drop_page_hash_index(), and row_check_table_for_mysql().
01598 : TRUE if ok */ 01599 { 01600 buf_block_t* block; 01601 page_t* page; 01602 ha_node_t* node; 01603 ulint n_page_dumps = 0; 01604 ibool ok = TRUE; 01605 ulint i; 01606 ulint cell_count; 01607 mem_heap_t* heap = NULL; 01608 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 01609 ulint* offsets = offsets_; 01610 01611 /* How many cells to check before temporarily releasing 01612 btr_search_latch. */ 01613 ulint chunk_size = 10000; 01614 01615 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 01616 01617 rw_lock_x_lock(&btr_search_latch); 01618 01619 cell_count = hash_get_n_cells(btr_search_sys->hash_index); 01620 01621 for (i = 0; i < cell_count; i++) { 01622 /* We release btr_search_latch every once in a while to 01623 give other queries a chance to run. */ 01624 if ((i != 0) && ((i % chunk_size) == 0)) { 01625 rw_lock_x_unlock(&btr_search_latch); 01626 os_thread_yield(); 01627 rw_lock_x_lock(&btr_search_latch); 01628 } 01629 01630 node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; 01631 01632 while (node != NULL) { 01633 block = buf_block_align(node->data); 01634 page = buf_frame_align(node->data); 01635 offsets = rec_get_offsets((rec_t*) node->data, 01636 block->index, offsets, 01637 block->curr_n_fields 01638 + (block->curr_n_bytes > 0), &heap); 01639 01640 if (!block->is_hashed 01641 || node->fold != rec_fold((rec_t*)(node->data), 01642 offsets, 01643 block->curr_n_fields, 01644 block->curr_n_bytes, 01645 btr_page_get_index_id(page))) { 01646 ok = FALSE; 01647 ut_print_timestamp(stderr); 01648 01649 fprintf(stderr, 01650 " InnoDB: Error in an adaptive hash index pointer to page %lu\n" 01651 "ptr mem address %p index id %lu %lu, node fold %lu, rec fold %lu\n", 01652 (ulong) buf_frame_get_page_no(page), 01653 node->data, 01654 (ulong) ut_dulint_get_high(btr_page_get_index_id(page)), 01655 (ulong) ut_dulint_get_low(btr_page_get_index_id(page)), 01656 (ulong) node->fold, 01657 (ulong) rec_fold((rec_t*)(node->data), 01658 offsets, 01659 block->curr_n_fields, 01660 block->curr_n_bytes, 01661 btr_page_get_index_id(page))); 01662 01663 fputs("InnoDB: Record ", stderr); 01664 rec_print_new(stderr, (rec_t*)node->data, 01665 offsets); 01666 fprintf(stderr, "\nInnoDB: on that page." 01667 "Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n" 01668 "side %lu\n", 01669 page, (ulong) block->is_hashed, 01670 (ulong) block->curr_n_fields, 01671 (ulong) block->curr_n_bytes, (ulong) block->curr_side); 01672 01673 if (n_page_dumps < 20) { 01674 buf_page_print(page); 01675 n_page_dumps++; 01676 } 01677 } 01678 01679 node = node->next; 01680 } 01681 } 01682 01683 for (i = 0; i < cell_count; i += chunk_size) { 01684 ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1); 01685 01686 /* We release btr_search_latch every once in a while to 01687 give other queries a chance to run. */ 01688 if (i != 0) { 01689 rw_lock_x_unlock(&btr_search_latch); 01690 os_thread_yield(); 01691 rw_lock_x_lock(&btr_search_latch); 01692 } 01693 01694 if (!ha_validate(btr_search_sys->hash_index, i, end_index)) { 01695 ok = FALSE; 01696 } 01697 } 01698 01699 rw_lock_x_unlock(&btr_search_latch); 01700 if (UNIV_LIKELY_NULL(heap)) { 01701 mem_heap_free(heap); 01702 } 01703 01704 return(ok); 01705 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte btr_sea_pad1[64] |
| byte btr_sea_pad2[64] |
Definition at line 49 of file btr0sea.c.
Referenced by btr_search_build_page_hash_index(), btr_search_check_free_space_in_heap(), btr_search_drop_page_hash_index(), btr_search_guess_on_hash(), btr_search_sys_create(), btr_search_update_hash_node_on_insert(), btr_search_update_hash_on_delete(), btr_search_update_hash_on_insert(), btr_search_update_hash_ref(), btr_search_validate(), and srv_printf_innodb_monitor().
1.4.7

