#include "univ.i"#include "rem0rec.h"#include "dict0dict.h"#include "btr0types.h"#include "mtr0mtr.h"#include "ha0ha.h"Include dependency graph for btr0sea.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
| #define BTR_SEA_TIMEOUT 10000 |
| #define btr_search_latch (*btr_search_latch_temp) |
Definition at line 219 of file btr0sea.h.
Referenced by btr_cur_del_mark_set_clust_rec(), btr_cur_del_mark_set_sec_rec(), btr_cur_search_to_nth_level(), btr_cur_update_in_place(), 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_info_update_hash(), btr_search_info_update_slow(), btr_search_move_or_delete_hash_entries(), btr_search_sys_create(), btr_search_update_block_hash_info(), 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(), page_set_max_trx_id(), row_search_for_mysql(), row_sel(), row_sel_try_search_shortcut(), and trx_search_latch_release_if_reserved().
| #define BTR_SEARCH_LEFT_SIDE 1 |
Definition at line 232 of file btr0sea.h.
Referenced by btr_search_build_page_hash_index(), btr_search_info_create(), btr_search_info_update_hash(), btr_search_update_hash_on_insert(), buf_page_init(), and buf_page_init_for_backup_restore().
| #define BTR_SEARCH_MAGIC_N 1112765 |
Definition at line 193 of file btr0sea.h.
Referenced by btr_search_info_create(), and btr_search_update_block_hash_info().
| #define BTR_SEARCH_RIGHT_SIDE 2 |
Definition at line 233 of file btr0sea.h.
Referenced by btr_search_build_page_hash_index(), btr_search_info_update_hash(), btr_search_update_hash_node_on_insert(), and btr_search_update_hash_on_insert().
| typedef struct btr_search_sys_struct btr_search_sys_t |
| 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:

| UNIV_INLINE btr_search_t* btr_search_get_info | ( | dict_index_t * | index | ) |
| 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_search_struct::n_bytes, btr_cur_struct::n_bytes, btr_search_struct::n_fields, btr_cur_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:

| UNIV_INLINE void btr_search_info_update | ( | dict_index_t * | index, | |
| btr_cur_t * | cursor | |||
| ) |
| 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(), index(), buf_block_struct::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:

| 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:

| 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:

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

