#include "btr0btr.h"#include "fsp0fsp.h"#include "page0page.h"#include "btr0cur.h"#include "btr0sea.h"#include "btr0pcur.h"#include "rem0cmp.h"#include "lock0lock.h"#include "ibuf0ibuf.h"#include "trx0trx.h"Include dependency graph for btr0btr.c:

Go to the source code of this file.
| static void btr_attach_half_pages | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| rec_t * | split_rec, | |||
| page_t * | new_page, | |||
| ulint | direction, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1440 of file btr0btr.c.
References btr_insert_on_non_leaf_level(), btr_node_ptr_set_child_page_no(), btr_page_get(), btr_page_get_father_node_ptr(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), buf_block_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), dict_tree_build_node_ptr(), FIL_NULL, FSP_DOWN, mem_heap_create, mem_heap_empty(), mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, NULL, page_is_comp(), page_t, rec_get_offsets, RW_X_LATCH, dict_tree_struct::tree_index, ut_a, and ut_ad.
Referenced by btr_page_split_and_insert().
01442 : the index tree */ 01443 page_t* page, /* in: page to be split */ 01444 rec_t* split_rec, /* in: first record on upper 01445 half page */ 01446 page_t* new_page, /* in: the new half page */ 01447 ulint direction, /* in: FSP_UP or FSP_DOWN */ 01448 mtr_t* mtr) /* in: mtr */ 01449 { 01450 ulint space; 01451 rec_t* node_ptr; 01452 page_t* prev_page; 01453 page_t* next_page; 01454 ulint prev_page_no; 01455 ulint next_page_no; 01456 ulint level; 01457 page_t* lower_page; 01458 page_t* upper_page; 01459 ulint lower_page_no; 01460 ulint upper_page_no; 01461 dtuple_t* node_ptr_upper; 01462 mem_heap_t* heap; 01463 01464 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01465 MTR_MEMO_PAGE_X_FIX)); 01466 ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page), 01467 MTR_MEMO_PAGE_X_FIX)); 01468 ut_a(page_is_comp(page) == page_is_comp(new_page)); 01469 01470 /* Create a memory heap where the data tuple is stored */ 01471 heap = mem_heap_create(1024); 01472 01473 /* Based on split direction, decide upper and lower pages */ 01474 if (direction == FSP_DOWN) { 01475 01476 lower_page_no = buf_frame_get_page_no(new_page); 01477 upper_page_no = buf_frame_get_page_no(page); 01478 lower_page = new_page; 01479 upper_page = page; 01480 01481 /* Look from the tree for the node pointer to page */ 01482 node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); 01483 01484 /* Replace the address of the old child node (= page) with the 01485 address of the new lower half */ 01486 01487 btr_node_ptr_set_child_page_no(node_ptr, 01488 rec_get_offsets(node_ptr, 01489 tree->tree_index, 01490 NULL, ULINT_UNDEFINED, &heap), 01491 lower_page_no, mtr); 01492 mem_heap_empty(heap); 01493 } else { 01494 lower_page_no = buf_frame_get_page_no(page); 01495 upper_page_no = buf_frame_get_page_no(new_page); 01496 lower_page = page; 01497 upper_page = new_page; 01498 } 01499 01500 /* Get the level of the split pages */ 01501 level = btr_page_get_level(page, mtr); 01502 01503 /* Build the node pointer (= node key and page address) for the upper 01504 half */ 01505 01506 node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec, 01507 upper_page_no, heap, level); 01508 01509 /* Insert it next to the pointer to the lower half. Note that this 01510 may generate recursion leading to a split on the higher level. */ 01511 01512 btr_insert_on_non_leaf_level(tree, level + 1, node_ptr_upper, mtr); 01513 01514 /* Free the memory heap */ 01515 mem_heap_free(heap); 01516 01517 /* Get the previous and next pages of page */ 01518 01519 prev_page_no = btr_page_get_prev(page, mtr); 01520 next_page_no = btr_page_get_next(page, mtr); 01521 space = buf_frame_get_space_id(page); 01522 01523 /* Update page links of the level */ 01524 01525 if (prev_page_no != FIL_NULL) { 01526 01527 prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); 01528 ut_a(page_is_comp(prev_page) == page_is_comp(page)); 01529 #ifdef UNIV_BTR_DEBUG 01530 ut_a(btr_page_get_next(prev_page, mtr) 01531 == buf_frame_get_page_no(page)); 01532 #endif /* UNIV_BTR_DEBUG */ 01533 01534 btr_page_set_next(prev_page, lower_page_no, mtr); 01535 } 01536 01537 if (next_page_no != FIL_NULL) { 01538 01539 next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr); 01540 ut_a(page_is_comp(next_page) == page_is_comp(page)); 01541 01542 btr_page_set_prev(next_page, upper_page_no, mtr); 01543 } 01544 01545 btr_page_set_prev(lower_page, prev_page_no, mtr); 01546 btr_page_set_next(lower_page, upper_page_no, mtr); 01547 btr_page_set_level(lower_page, level, mtr); 01548 01549 btr_page_set_prev(upper_page, lower_page_no, mtr); 01550 btr_page_set_next(upper_page, next_page_no, mtr); 01551 btr_page_set_level(upper_page, level, mtr); 01552 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2003 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_tree(), btr_level_list_remove(), btr_lift_page_up(), btr_node_ptr_delete(), btr_node_ptr_set_child_page_no(), btr_page_free(), btr_page_get(), btr_page_get_father_node_ptr(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), btr_page_reorganize(), btr_search_drop_page_hash_index(), buf_block_align(), buf_frame_align(), buf_frame_get_page_no(), dict_table_is_comp(), dict_tree_get_lock(), dict_tree_get_space(), FIL_NULL, ibuf_update_free_bits_if_full(), btr_cur_struct::index, lock_update_merge_left(), lock_update_merge_right(), mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, NULL, page, page_copy_rec_list_end(), page_copy_rec_list_start(), page_get_data_size(), page_get_infimum_rec(), page_get_max_insert_size(), page_get_max_insert_size_after_reorganize(), page_get_n_recs(), page_get_supremum_rec(), page_is_comp(), page_rec_get_next(), page_rec_get_prev(), page_t, page_validate(), rec_get_offsets, rec_get_status(), REC_OFFS_NORMAL_SIZE, REC_STATUS_NODE_PTR, RW_X_LATCH, dict_index_struct::table, UNIV_PAGE_SIZE, ut_a, and ut_ad.
Referenced by btr_cur_compress(), and btr_cur_compress_if_useful().
02005 : cursor on the page to merge or lift; 02006 the page must not be empty: in record delete 02007 use btr_discard_page if the page would become 02008 empty */ 02009 mtr_t* mtr) /* in: mtr */ 02010 { 02011 dict_tree_t* tree; 02012 ulint space; 02013 ulint left_page_no; 02014 ulint right_page_no; 02015 page_t* merge_page; 02016 page_t* father_page; 02017 ibool is_left; 02018 page_t* page; 02019 rec_t* orig_pred; 02020 rec_t* orig_succ; 02021 rec_t* node_ptr; 02022 ulint data_size; 02023 ulint n_recs; 02024 ulint max_ins_size; 02025 ulint max_ins_size_reorg; 02026 ulint level; 02027 ulint comp; 02028 02029 page = btr_cur_get_page(cursor); 02030 tree = btr_cur_get_tree(cursor); 02031 comp = page_is_comp(page); 02032 ut_a((ibool)!!comp == dict_table_is_comp(cursor->index->table)); 02033 02034 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 02035 MTR_MEMO_X_LOCK)); 02036 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 02037 MTR_MEMO_PAGE_X_FIX)); 02038 level = btr_page_get_level(page, mtr); 02039 space = dict_tree_get_space(tree); 02040 02041 left_page_no = btr_page_get_prev(page, mtr); 02042 right_page_no = btr_page_get_next(page, mtr); 02043 02044 /* fprintf(stderr, "Merge left page %lu right %lu \n", left_page_no, 02045 right_page_no); */ 02046 02047 node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); 02048 ut_ad(!comp || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR); 02049 father_page = buf_frame_align(node_ptr); 02050 ut_a(comp == page_is_comp(father_page)); 02051 02052 /* Decide the page to which we try to merge and which will inherit 02053 the locks */ 02054 02055 is_left = left_page_no != FIL_NULL; 02056 02057 if (is_left) { 02058 02059 merge_page = btr_page_get(space, left_page_no, RW_X_LATCH, 02060 mtr); 02061 #ifdef UNIV_BTR_DEBUG 02062 ut_a(btr_page_get_next(merge_page, mtr) 02063 == buf_frame_get_page_no(page)); 02064 #endif /* UNIV_BTR_DEBUG */ 02065 } else if (right_page_no != FIL_NULL) { 02066 02067 merge_page = btr_page_get(space, right_page_no, RW_X_LATCH, 02068 mtr); 02069 #ifdef UNIV_BTR_DEBUG 02070 ut_a(btr_page_get_prev(merge_page, mtr) 02071 == buf_frame_get_page_no(page)); 02072 #endif /* UNIV_BTR_DEBUG */ 02073 } else { 02074 /* The page is the only one on the level, lift the records 02075 to the father */ 02076 btr_lift_page_up(tree, page, mtr); 02077 02078 return; 02079 } 02080 02081 n_recs = page_get_n_recs(page); 02082 data_size = page_get_data_size(page); 02083 ut_a(page_is_comp(merge_page) == comp); 02084 02085 max_ins_size_reorg = page_get_max_insert_size_after_reorganize( 02086 merge_page, n_recs); 02087 if (data_size > max_ins_size_reorg) { 02088 02089 /* No space for merge */ 02090 02091 return; 02092 } 02093 02094 ut_ad(page_validate(merge_page, cursor->index)); 02095 02096 max_ins_size = page_get_max_insert_size(merge_page, n_recs); 02097 02098 if (data_size > max_ins_size) { 02099 02100 /* We have to reorganize merge_page */ 02101 02102 btr_page_reorganize(merge_page, cursor->index, mtr); 02103 02104 max_ins_size = page_get_max_insert_size(merge_page, n_recs); 02105 02106 ut_ad(page_validate(merge_page, cursor->index)); 02107 ut_ad(page_get_max_insert_size(merge_page, n_recs) 02108 == max_ins_size_reorg); 02109 } 02110 02111 if (data_size > max_ins_size) { 02112 02113 /* Add fault tolerance, though this should never happen */ 02114 02115 return; 02116 } 02117 02118 btr_search_drop_page_hash_index(page); 02119 02120 /* Remove the page from the level list */ 02121 btr_level_list_remove(tree, page, mtr); 02122 02123 if (is_left) { 02124 btr_node_ptr_delete(tree, page, mtr); 02125 } else { 02126 mem_heap_t* heap = NULL; 02127 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02128 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02129 /* Replace the address of the old child node (= page) with the 02130 address of the merge page to the right */ 02131 02132 btr_node_ptr_set_child_page_no(node_ptr, 02133 rec_get_offsets(node_ptr, cursor->index, 02134 offsets_, ULINT_UNDEFINED, &heap), 02135 right_page_no, mtr); 02136 if (UNIV_LIKELY_NULL(heap)) { 02137 mem_heap_free(heap); 02138 } 02139 btr_node_ptr_delete(tree, merge_page, mtr); 02140 } 02141 02142 /* Move records to the merge page */ 02143 if (is_left) { 02144 orig_pred = page_rec_get_prev( 02145 page_get_supremum_rec(merge_page)); 02146 page_copy_rec_list_start(merge_page, page, 02147 page_get_supremum_rec(page), cursor->index, mtr); 02148 02149 lock_update_merge_left(merge_page, orig_pred, page); 02150 } else { 02151 orig_succ = page_rec_get_next( 02152 page_get_infimum_rec(merge_page)); 02153 page_copy_rec_list_end(merge_page, page, 02154 page_get_infimum_rec(page), cursor->index, mtr); 02155 02156 lock_update_merge_right(orig_succ, page); 02157 } 02158 02159 /* We have added new records to merge_page: update its free bits */ 02160 ibuf_update_free_bits_if_full(cursor->index, merge_page, 02161 UNIV_PAGE_SIZE, ULINT_UNDEFINED); 02162 02163 ut_ad(page_validate(merge_page, cursor->index)); 02164 02165 /* Free the file page */ 02166 btr_page_free(tree, page, mtr); 02167 02168 ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); 02169 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 659 of file btr0btr.c.
References BTR_PAGE_MAX_REC_SIZE, buf_block_align(), buf_frame_get_page_no(), buf_page_get, buf_block_struct::check_index_page_at_flush, DICT_IBUF, FIL_NULL, flst_init(), fseg_alloc_free_page(), fseg_create(), FSP_UP, IBUF_HEADER, IBUF_HEADER_PAGE_NO, ibuf_reset_free_bits_with_type(), IBUF_TREE_ROOT_PAGE_NO, IBUF_TREE_SEG_HEADER, NULL, page, PAGE_BTR_IBUF_FREE_LIST, PAGE_BTR_SEG_LEAF, PAGE_BTR_SEG_TOP, page_create(), page_get_max_insert_size(), PAGE_HEADER, page_t, RW_X_LATCH, SYNC_TREE_NODE_NEW, TRUE, and ut_ad.
Referenced by dict_create_index_tree_step(), dict_hdr_create(), dict_truncate_index_tree(), and fsp_header_init().
00661 : page number of the created root, FIL_NULL if 00662 did not succeed */ 00663 ulint type, /* in: type of the index */ 00664 ulint space, /* in: space where created */ 00665 dulint index_id,/* in: index id */ 00666 ulint comp, /* in: nonzero=compact page format */ 00667 mtr_t* mtr) /* in: mini-transaction handle */ 00668 { 00669 ulint page_no; 00670 buf_frame_t* ibuf_hdr_frame; 00671 buf_frame_t* frame; 00672 page_t* page; 00673 00674 /* Create the two new segments (one, in the case of an ibuf tree) for 00675 the index tree; the segment headers are put on the allocated root page 00676 (for an ibuf tree, not in the root, but on a separate ibuf header 00677 page) */ 00678 00679 if (type & DICT_IBUF) { 00680 /* Allocate first the ibuf header page */ 00681 ibuf_hdr_frame = fseg_create(space, 0, 00682 IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr); 00683 00684 #ifdef UNIV_SYNC_DEBUG 00685 buf_page_dbg_add_level(ibuf_hdr_frame, SYNC_TREE_NODE_NEW); 00686 #endif /* UNIV_SYNC_DEBUG */ 00687 ut_ad(buf_frame_get_page_no(ibuf_hdr_frame) 00688 == IBUF_HEADER_PAGE_NO); 00689 /* Allocate then the next page to the segment: it will be the 00690 tree root page */ 00691 00692 page_no = fseg_alloc_free_page( 00693 ibuf_hdr_frame + IBUF_HEADER 00694 + IBUF_TREE_SEG_HEADER, IBUF_TREE_ROOT_PAGE_NO, 00695 FSP_UP, mtr); 00696 ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); 00697 00698 frame = buf_page_get(space, page_no, RW_X_LATCH, mtr); 00699 } else { 00700 frame = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP, 00701 mtr); 00702 } 00703 00704 if (frame == NULL) { 00705 00706 return(FIL_NULL); 00707 } 00708 00709 page_no = buf_frame_get_page_no(frame); 00710 00711 #ifdef UNIV_SYNC_DEBUG 00712 buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); 00713 #endif /* UNIV_SYNC_DEBUG */ 00714 00715 if (type & DICT_IBUF) { 00716 /* It is an insert buffer tree: initialize the free list */ 00717 00718 ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); 00719 00720 flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); 00721 } else { 00722 /* It is a non-ibuf tree: create a file segment for leaf 00723 pages */ 00724 fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, 00725 mtr); 00726 /* The fseg create acquires a second latch on the page, 00727 therefore we must declare it: */ 00728 #ifdef UNIV_SYNC_DEBUG 00729 buf_page_dbg_add_level(frame, SYNC_TREE_NODE_NEW); 00730 #endif /* UNIV_SYNC_DEBUG */ 00731 } 00732 00733 /* Create a new index page on the the allocated segment page */ 00734 page = page_create(frame, mtr, comp); 00735 buf_block_align(page)->check_index_page_at_flush = TRUE; 00736 00737 /* Set the index id of the page */ 00738 btr_page_set_index_id(page, index_id, mtr); 00739 00740 /* Set the level of the new index page */ 00741 btr_page_set_level(page, 0, mtr); 00742 00743 /* Set the next node and previous node fields */ 00744 btr_page_set_next(page, FIL_NULL, mtr); 00745 btr_page_set_prev(page, FIL_NULL, mtr); 00746 00747 /* We reset the free bits for the page to allow creation of several 00748 trees in the same mtr, otherwise the latch on a bitmap page would 00749 prevent it because of the latching order */ 00750 00751 ibuf_reset_free_bits_with_type(type, page); 00752 00753 /* In the following assertion we test that two records of maximum 00754 allowed size fit on the root page: this fact is needed to ensure 00755 correctness of split algorithms */ 00756 00757 ut_ad(page_get_max_insert_size(page, 2) > 2 * BTR_PAGE_MAX_REC_SIZE); 00758 00759 return(page_no); 00760 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_discard_only_page_on_level | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 2175 of file btr0btr.c.
References btr_page_empty(), btr_page_free(), btr_page_get_father_node_ptr(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), btr_search_drop_page_hash_index(), buf_block_align(), buf_frame_align(), buf_frame_get_page_no(), dict_tree_get_page(), FIL_NULL, ibuf_reset_free_bits(), lock_update_discard(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, page_get_n_recs(), page_get_supremum_rec(), page_t, dict_tree_struct::tree_index, and ut_ad.
Referenced by btr_discard_page().
02177 : index tree */ 02178 page_t* page, /* in: page which is the only on its level */ 02179 mtr_t* mtr) /* in: mtr */ 02180 { 02181 rec_t* node_ptr; 02182 page_t* father_page; 02183 ulint page_level; 02184 02185 ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); 02186 ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); 02187 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 02188 MTR_MEMO_PAGE_X_FIX)); 02189 btr_search_drop_page_hash_index(page); 02190 02191 node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); 02192 father_page = buf_frame_align(node_ptr); 02193 02194 page_level = btr_page_get_level(page, mtr); 02195 02196 lock_update_discard(page_get_supremum_rec(father_page), page); 02197 02198 btr_page_set_level(father_page, page_level, mtr); 02199 02200 /* Free the file page */ 02201 btr_page_free(tree, page, mtr); 02202 02203 if (buf_frame_get_page_no(father_page) == dict_tree_get_page(tree)) { 02204 /* The father is the root page */ 02205 02206 btr_page_empty(father_page, mtr); 02207 02208 /* We play safe and reset the free bits for the father */ 02209 ibuf_reset_free_bits(tree->tree_index, father_page); 02210 } else { 02211 ut_ad(page_get_n_recs(father_page) == 1); 02212 02213 btr_discard_only_page_on_level(tree, father_page, mtr); 02214 } 02215 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2223 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_tree(), btr_discard_only_page_on_level(), btr_level_list_remove(), btr_node_ptr_delete(), btr_page_free(), btr_page_get(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), btr_search_drop_page_hash_index(), btr_set_min_rec_mark(), buf_block_align(), buf_frame_get_page_no(), dict_tree_get_lock(), dict_tree_get_page(), dict_tree_get_space(), FIL_NULL, lock_update_discard(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, page, page_get_infimum_rec(), page_get_supremum_rec(), page_is_comp(), page_rec_get_next(), page_rec_is_user_rec(), page_t, RW_X_LATCH, ut_a, and ut_ad.
Referenced by btr_cur_pessimistic_delete().
02225 : cursor on the page to discard: not on 02226 the root page */ 02227 mtr_t* mtr) /* in: mtr */ 02228 { 02229 dict_tree_t* tree; 02230 ulint space; 02231 ulint left_page_no; 02232 ulint right_page_no; 02233 page_t* merge_page; 02234 page_t* page; 02235 rec_t* node_ptr; 02236 02237 page = btr_cur_get_page(cursor); 02238 tree = btr_cur_get_tree(cursor); 02239 02240 ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); 02241 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 02242 MTR_MEMO_X_LOCK)); 02243 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 02244 MTR_MEMO_PAGE_X_FIX)); 02245 space = dict_tree_get_space(tree); 02246 02247 /* Decide the page which will inherit the locks */ 02248 02249 left_page_no = btr_page_get_prev(page, mtr); 02250 right_page_no = btr_page_get_next(page, mtr); 02251 02252 if (left_page_no != FIL_NULL) { 02253 merge_page = btr_page_get(space, left_page_no, RW_X_LATCH, 02254 mtr); 02255 #ifdef UNIV_BTR_DEBUG 02256 ut_a(btr_page_get_next(merge_page, mtr) 02257 == buf_frame_get_page_no(page)); 02258 #endif /* UNIV_BTR_DEBUG */ 02259 } else if (right_page_no != FIL_NULL) { 02260 merge_page = btr_page_get(space, right_page_no, RW_X_LATCH, 02261 mtr); 02262 #ifdef UNIV_BTR_DEBUG 02263 ut_a(btr_page_get_prev(merge_page, mtr) 02264 == buf_frame_get_page_no(page)); 02265 #endif /* UNIV_BTR_DEBUG */ 02266 } else { 02267 btr_discard_only_page_on_level(tree, page, mtr); 02268 02269 return; 02270 } 02271 02272 ut_a(page_is_comp(merge_page) == page_is_comp(page)); 02273 btr_search_drop_page_hash_index(page); 02274 02275 if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) { 02276 02277 /* We have to mark the leftmost node pointer on the right 02278 side page as the predefined minimum record */ 02279 02280 node_ptr = page_rec_get_next(page_get_infimum_rec(merge_page)); 02281 02282 ut_ad(page_rec_is_user_rec(node_ptr)); 02283 02284 btr_set_min_rec_mark(node_ptr, page_is_comp(merge_page), mtr); 02285 } 02286 02287 btr_node_ptr_delete(tree, page, mtr); 02288 02289 /* Remove the page from the level list */ 02290 btr_level_list_remove(tree, page, mtr); 02291 02292 if (left_page_no != FIL_NULL) { 02293 lock_update_discard(page_get_supremum_rec(merge_page), page); 02294 } else { 02295 lock_update_discard(page_rec_get_next( 02296 page_get_infimum_rec(merge_page)), page); 02297 } 02298 02299 /* Free the file page */ 02300 btr_page_free(tree, page, mtr); 02301 02302 ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); 02303 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 767 of file btr0btr.c.
References btr_page_get(), yaSSL::finished, fseg_free_step(), fseg_free_step_not_header(), mtr_commit(), mtr_start(), PAGE_BTR_SEG_LEAF, PAGE_BTR_SEG_TOP, PAGE_HEADER, page_t, and RW_X_LATCH.
Referenced by dict_drop_index_tree(), and dict_truncate_index_tree().
00769 : space where created */ 00770 ulint root_page_no) /* in: root page number */ 00771 { 00772 ibool finished; 00773 page_t* root; 00774 mtr_t mtr; 00775 00776 leaf_loop: 00777 mtr_start(&mtr); 00778 00779 root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); 00780 00781 /* NOTE: page hash indexes are dropped when a page is freed inside 00782 fsp0fsp. */ 00783 00784 finished = fseg_free_step( 00785 root + PAGE_HEADER + PAGE_BTR_SEG_LEAF, &mtr); 00786 mtr_commit(&mtr); 00787 00788 if (!finished) { 00789 00790 goto leaf_loop; 00791 } 00792 top_loop: 00793 mtr_start(&mtr); 00794 00795 root = btr_page_get(space, root_page_no, RW_X_LATCH, &mtr); 00796 00797 finished = fseg_free_step_not_header( 00798 root + PAGE_HEADER + PAGE_BTR_SEG_TOP, &mtr); 00799 mtr_commit(&mtr); 00800 00801 if (!finished) { 00802 00803 goto top_loop; 00804 } 00805 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 811 of file btr0btr.c.
References btr_page_get(), btr_search_drop_page_hash_index(), yaSSL::finished, fseg_free_step(), PAGE_BTR_SEG_TOP, PAGE_HEADER, page_t, and RW_X_LATCH.
Referenced by dict_drop_index_tree(), and dict_truncate_index_tree().
00813 : space where created */ 00814 ulint root_page_no, /* in: root page number */ 00815 mtr_t* mtr) /* in: a mini-transaction which has already 00816 been started */ 00817 { 00818 ibool finished; 00819 page_t* root; 00820 00821 root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); 00822 00823 btr_search_drop_page_hash_index(root); 00824 top_loop: 00825 finished = fseg_free_step( 00826 root + PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); 00827 if (!finished) { 00828 00829 goto top_loop; 00830 } 00831 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 209 of file btr0btr.c.
References btr_page_get_next(), btr_page_get_prev(), buf_block_align(), buf_frame_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), buf_page_get_with_no_latch, FIL_NULL, mtr_memo_contains(), MTR_MEMO_PAGE_S_FIX, MTR_MEMO_PAGE_X_FIX, NULL, page, page_get_infimum_rec(), page_is_comp(), page_rec_get_next(), page_rec_is_supremum(), page_t, ut_a, and ut_ad.
00211 : next user record, NULL if there is none */ 00212 rec_t* rec, /* in: record on leaf level */ 00213 mtr_t* mtr) /* in: mtr holding a latch on the page, and if 00214 needed, also to the next page */ 00215 { 00216 page_t* page; 00217 page_t* next_page; 00218 ulint next_page_no; 00219 ulint space; 00220 00221 if (!page_rec_is_supremum(rec)) { 00222 00223 rec_t* next_rec = page_rec_get_next(rec); 00224 00225 if (!page_rec_is_supremum(next_rec)) { 00226 00227 return(next_rec); 00228 } 00229 } 00230 00231 page = buf_frame_align(rec); 00232 next_page_no = btr_page_get_next(page, mtr); 00233 space = buf_frame_get_space_id(page); 00234 00235 if (next_page_no != FIL_NULL) { 00236 00237 next_page = buf_page_get_with_no_latch(space, next_page_no, 00238 mtr); 00239 /* The caller must already have a latch to the brother */ 00240 ut_ad((mtr_memo_contains(mtr, buf_block_align(next_page), 00241 MTR_MEMO_PAGE_S_FIX)) 00242 || (mtr_memo_contains(mtr, buf_block_align(next_page), 00243 MTR_MEMO_PAGE_X_FIX))); 00244 #ifdef UNIV_BTR_DEBUG 00245 ut_a(btr_page_get_prev(next_page, mtr) 00246 == buf_frame_get_page_no(page)); 00247 #endif /* UNIV_BTR_DEBUG */ 00248 00249 ut_a(page_is_comp(next_page) == page_is_comp(page)); 00250 return(page_rec_get_next(page_get_infimum_rec(next_page))); 00251 } 00252 00253 return(NULL); 00254 }
Here is the call graph for this function:

Definition at line 157 of file btr0btr.c.
References btr_page_get_next(), btr_page_get_prev(), buf_block_align(), buf_frame_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), buf_page_get_with_no_latch, FIL_NULL, mtr_memo_contains(), MTR_MEMO_PAGE_S_FIX, MTR_MEMO_PAGE_X_FIX, NULL, page, page_get_supremum_rec(), page_is_comp(), page_rec_get_prev(), page_rec_is_infimum(), page_t, ut_a, and ut_ad.
00159 : previous user record, NULL if there is none */ 00160 rec_t* rec, /* in: record on leaf level */ 00161 mtr_t* mtr) /* in: mtr holding a latch on the page, and if 00162 needed, also to the previous page */ 00163 { 00164 page_t* page; 00165 page_t* prev_page; 00166 ulint prev_page_no; 00167 ulint space; 00168 00169 if (!page_rec_is_infimum(rec)) { 00170 00171 rec_t* prev_rec = page_rec_get_prev(rec); 00172 00173 if (!page_rec_is_infimum(prev_rec)) { 00174 00175 return(prev_rec); 00176 } 00177 } 00178 00179 page = buf_frame_align(rec); 00180 prev_page_no = btr_page_get_prev(page, mtr); 00181 space = buf_frame_get_space_id(page); 00182 00183 if (prev_page_no != FIL_NULL) { 00184 00185 prev_page = buf_page_get_with_no_latch(space, prev_page_no, 00186 mtr); 00187 /* The caller must already have a latch to the brother */ 00188 ut_ad((mtr_memo_contains(mtr, buf_block_align(prev_page), 00189 MTR_MEMO_PAGE_S_FIX)) 00190 || (mtr_memo_contains(mtr, buf_block_align(prev_page), 00191 MTR_MEMO_PAGE_X_FIX))); 00192 ut_a(page_is_comp(prev_page) == page_is_comp(page)); 00193 #ifdef UNIV_BTR_DEBUG 00194 ut_a(btr_page_get_next(prev_page, mtr) 00195 == buf_frame_get_page_no(page)); 00196 #endif /* UNIV_BTR_DEBUG */ 00197 00198 return(page_rec_get_prev(page_get_supremum_rec(prev_page))); 00199 } 00200 00201 return(NULL); 00202 }
Here is the call graph for this function:

| ulint btr_get_size | ( | dict_index_t * | index, | |
| ulint | flag | |||
| ) |
Definition at line 370 of file btr0btr.c.
References BTR_N_LEAF_PAGES, btr_root_get(), BTR_TOTAL_SIZE, dict_tree_get_lock(), fseg_n_reserved_pages(), index(), mtr_commit(), mtr_s_lock, mtr_start(), n, PAGE_BTR_SEG_LEAF, PAGE_BTR_SEG_TOP, PAGE_HEADER, page_t, and ut_error.
Referenced by dict_update_statistics_low().
00372 : number of pages */ 00373 dict_index_t* index, /* in: index */ 00374 ulint flag) /* in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ 00375 { 00376 fseg_header_t* seg_header; 00377 page_t* root; 00378 ulint n; 00379 ulint dummy; 00380 mtr_t mtr; 00381 00382 mtr_start(&mtr); 00383 00384 mtr_s_lock(dict_tree_get_lock(index->tree), &mtr); 00385 00386 root = btr_root_get(index->tree, &mtr); 00387 00388 if (flag == BTR_N_LEAF_PAGES) { 00389 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; 00390 00391 fseg_n_reserved_pages(seg_header, &n, &mtr); 00392 00393 } else if (flag == BTR_TOTAL_SIZE) { 00394 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; 00395 00396 n = fseg_n_reserved_pages(seg_header, &dummy, &mtr); 00397 00398 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; 00399 00400 n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); 00401 } else { 00402 ut_error; 00403 } 00404 00405 mtr_commit(&mtr); 00406 00407 return(n); 00408 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool btr_index_page_validate | ( | page_t * | page, | |
| dict_index_t * | index | |||
| ) | [static] |
Definition at line 2618 of file btr0btr.c.
References btr_index_rec_validate(), FALSE, index(), page_cur_is_after_last(), page_cur_move_to_next(), page_cur_set_before_first(), and TRUE.
Referenced by btr_validate_level().
02620 : TRUE if ok */ 02621 page_t* page, /* in: index page */ 02622 dict_index_t* index) /* in: index */ 02623 { 02624 page_cur_t cur; 02625 ibool ret = TRUE; 02626 02627 page_cur_set_before_first(page, &cur); 02628 page_cur_move_to_next(&cur); 02629 02630 for (;;) { 02631 if (page_cur_is_after_last(&cur)) { 02632 02633 break; 02634 } 02635 02636 if (!btr_index_rec_validate(cur.rec, index, TRUE)) { 02637 02638 return(FALSE); 02639 } 02640 02641 page_cur_move_to_next(&cur); 02642 } 02643 02644 return(ret); 02645 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool btr_index_rec_validate | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| ibool | dump_on_error | |||
| ) |
Definition at line 2512 of file btr0btr.c.
References btr_index_rec_validate_report(), buf_frame_align(), buf_page_print(), dict_index_get_n_fields(), dict_index_get_nth_field(), dict_index_get_nth_type(), dict_table_is_comp(), DICT_UNIVERSAL, dtype_get_fixed_size(), FALSE, index(), mem_heap_free, n, NULL, page_is_comp(), page_t, rec_get_n_fields_old(), rec_get_nth_field(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_print_new(), rec_print_old(), and TRUE.
Referenced by btr_index_page_validate(), and row_search_for_mysql().
02514 : TRUE if ok */ 02515 rec_t* rec, /* in: index record */ 02516 dict_index_t* index, /* in: index */ 02517 ibool dump_on_error) /* in: TRUE if the function 02518 should print hex dump of record 02519 and page on error */ 02520 { 02521 ulint len; 02522 ulint n; 02523 ulint i; 02524 page_t* page; 02525 mem_heap_t* heap = NULL; 02526 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 02527 ulint* offsets = offsets_; 02528 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 02529 02530 page = buf_frame_align(rec); 02531 02532 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { 02533 /* The insert buffer index tree can contain records from any 02534 other index: we cannot check the number of fields or 02535 their length */ 02536 02537 return(TRUE); 02538 } 02539 02540 if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) 02541 != dict_table_is_comp(index->table))) { 02542 btr_index_rec_validate_report(page, rec, index); 02543 fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n", 02544 (ulong) !!page_is_comp(page), 02545 (ulong) dict_table_is_comp(index->table)); 02546 02547 return(FALSE); 02548 } 02549 02550 n = dict_index_get_n_fields(index); 02551 02552 if (!page_is_comp(page) 02553 && UNIV_UNLIKELY(rec_get_n_fields_old(rec) != n)) { 02554 btr_index_rec_validate_report(page, rec, index); 02555 fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n", 02556 (ulong) rec_get_n_fields_old(rec), (ulong) n); 02557 02558 if (dump_on_error) { 02559 buf_page_print(page); 02560 02561 fputs("InnoDB: corrupt record ", stderr); 02562 rec_print_old(stderr, rec); 02563 putc('\n', stderr); 02564 } 02565 return(FALSE); 02566 } 02567 02568 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); 02569 02570 for (i = 0; i < n; i++) { 02571 dtype_t* type = dict_index_get_nth_type(index, i); 02572 ulint fixed_size = dtype_get_fixed_size(type); 02573 02574 rec_get_nth_field(rec, offsets, i, &len); 02575 02576 /* Note that prefix indexes are not fixed size even when 02577 their type is CHAR. */ 02578 02579 if ((dict_index_get_nth_field(index, i)->prefix_len == 0 02580 && len != UNIV_SQL_NULL && fixed_size 02581 && len != fixed_size) 02582 || 02583 (dict_index_get_nth_field(index, i)->prefix_len > 0 02584 && len != UNIV_SQL_NULL 02585 && len > 02586 dict_index_get_nth_field(index, i)->prefix_len)) { 02587 02588 btr_index_rec_validate_report(page, rec, index); 02589 fprintf(stderr, 02590 "InnoDB: field %lu len is %lu, should be %lu\n", 02591 (ulong) i, (ulong) len, (ulong) dtype_get_fixed_size(type)); 02592 02593 if (dump_on_error) { 02594 buf_page_print(page); 02595 02596 fputs("InnoDB: corrupt record ", stderr); 02597 rec_print_new(stderr, rec, offsets); 02598 putc('\n', stderr); 02599 } 02600 if (UNIV_LIKELY_NULL(heap)) { 02601 mem_heap_free(heap); 02602 } 02603 return(FALSE); 02604 } 02605 } 02606 02607 if (UNIV_LIKELY_NULL(heap)) { 02608 mem_heap_free(heap); 02609 } 02610 return(TRUE); 02611 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_index_rec_validate_report | ( | page_t * | page, | |
| rec_t * | rec, | |||
| dict_index_t * | index | |||
| ) | [static] |
Definition at line 2495 of file btr0btr.c.
References buf_frame_get_page_no(), dict_index_name_print(), index(), and NULL.
Referenced by btr_index_rec_validate().
02497 : index page */ 02498 rec_t* rec, /* in: index record */ 02499 dict_index_t* index) /* in: index */ 02500 { 02501 fputs("InnoDB: Record in ", stderr); 02502 dict_index_name_print(stderr, NULL, index); 02503 fprintf(stderr, ", page %lu, at offset %lu\n", 02504 buf_frame_get_page_no(page), (ulint)(rec - page)); 02505 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_insert_on_non_leaf_level | ( | dict_tree_t * | tree, | |
| ulint | level, | |||
| dtuple_t * | tuple, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1408 of file btr0btr.c.
References BTR_CONT_MODIFY_TREE, btr_cur_pessimistic_insert(), btr_cur_search_to_nth_level(), BTR_KEEP_SYS_FLAG, BTR_NO_LOCKING_FLAG, BTR_NO_UNDO_LOG_FLAG, DB_SUCCESS, err, NULL, PAGE_CUR_LE, dict_tree_struct::tree_index, ut_a, and ut_ad.
Referenced by btr_attach_half_pages(), and btr_cur_pessimistic_delete().
01410 : tree */ 01411 ulint level, /* in: level, must be > 0 */ 01412 dtuple_t* tuple, /* in: the record to be inserted */ 01413 mtr_t* mtr) /* in: mtr */ 01414 { 01415 big_rec_t* dummy_big_rec; 01416 btr_cur_t cursor; 01417 ulint err; 01418 rec_t* rec; 01419 01420 ut_ad(level > 0); 01421 01422 /* In the following, choose just any index from the tree as the 01423 first parameter for btr_cur_search_to_nth_level. */ 01424 01425 btr_cur_search_to_nth_level(tree->tree_index, 01426 level, tuple, PAGE_CUR_LE, BTR_CONT_MODIFY_TREE, 01427 &cursor, 0, mtr); 01428 01429 err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG 01430 | BTR_KEEP_SYS_FLAG | BTR_NO_UNDO_LOG_FLAG, 01431 &cursor, tuple, &rec, &dummy_big_rec, NULL, mtr); 01432 ut_a(err == DB_SUCCESS); 01433 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_level_list_remove | ( | dict_tree_t *tree | __attribute__((unused)), | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1793 of file btr0btr.c.
References btr_page_get(), btr_page_get_next(), btr_page_get_prev(), buf_block_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), FIL_NULL, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, page_is_comp(), page_t, RW_X_LATCH, ut_a, and ut_ad.
Referenced by btr_compress(), and btr_discard_page().
01795 : index tree */ 01796 page_t* page, /* in: page to remove */ 01797 mtr_t* mtr) /* in: mtr */ 01798 { 01799 ulint space; 01800 ulint prev_page_no; 01801 page_t* prev_page; 01802 ulint next_page_no; 01803 page_t* next_page; 01804 01805 ut_ad(tree && page && mtr); 01806 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01807 MTR_MEMO_PAGE_X_FIX)); 01808 /* Get the previous and next page numbers of page */ 01809 01810 prev_page_no = btr_page_get_prev(page, mtr); 01811 next_page_no = btr_page_get_next(page, mtr); 01812 space = buf_frame_get_space_id(page); 01813 01814 /* Update page links of the level */ 01815 01816 if (prev_page_no != FIL_NULL) { 01817 01818 prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); 01819 ut_a(page_is_comp(prev_page) == page_is_comp(page)); 01820 #ifdef UNIV_BTR_DEBUG 01821 ut_a(btr_page_get_next(prev_page, mtr) 01822 == buf_frame_get_page_no(page)); 01823 #endif /* UNIV_BTR_DEBUG */ 01824 01825 btr_page_set_next(prev_page, next_page_no, mtr); 01826 } 01827 01828 if (next_page_no != FIL_NULL) { 01829 01830 next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr); 01831 ut_a(page_is_comp(next_page) == page_is_comp(page)); 01832 #ifdef UNIV_BTR_DEBUG 01833 ut_a(btr_page_get_prev(next_page, mtr) 01834 == buf_frame_get_page_no(page)); 01835 #endif /* UNIV_BTR_DEBUG */ 01836 01837 btr_page_set_prev(next_page, prev_page_no, mtr); 01838 } 01839 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_lift_page_up | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 1947 of file btr0btr.c.
References btr_page_empty(), btr_page_free(), btr_page_get_father_node_ptr(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), btr_search_drop_page_hash_index(), buf_block_align(), buf_frame_align(), FIL_NULL, ibuf_reset_free_bits(), index(), lock_update_copy_and_discard(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, page_copy_rec_list_end(), page_get_infimum_rec(), page_t, page_validate(), dict_tree_struct::tree_index, and ut_ad.
Referenced by btr_compress().
01949 : index tree */ 01950 page_t* page, /* in: page which is the only on its level; 01951 must not be empty: use 01952 btr_discard_only_page_on_level if the last 01953 record from the page should be removed */ 01954 mtr_t* mtr) /* in: mtr */ 01955 { 01956 page_t* father_page; 01957 ulint page_level; 01958 dict_index_t* index; 01959 01960 ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); 01961 ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); 01962 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01963 MTR_MEMO_PAGE_X_FIX)); 01964 father_page = buf_frame_align( 01965 btr_page_get_father_node_ptr(tree, page, mtr)); 01966 01967 page_level = btr_page_get_level(page, mtr); 01968 index = tree->tree_index; 01969 01970 btr_search_drop_page_hash_index(page); 01971 01972 /* Make the father empty */ 01973 btr_page_empty(father_page, mtr); 01974 01975 /* Move records to the father */ 01976 page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page), 01977 index, mtr); 01978 lock_update_copy_and_discard(father_page, page); 01979 01980 btr_page_set_level(father_page, page_level, mtr); 01981 01982 /* Free the file page */ 01983 btr_page_free(tree, page, mtr); 01984 01985 /* We play safe and reset the free bits for the father */ 01986 ibuf_reset_free_bits(index, father_page); 01987 ut_ad(page_validate(father_page, index)); 01988 ut_ad(btr_check_node_ptr(tree, father_page, mtr)); 01989 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_node_ptr_delete | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1915 of file btr0btr.c.
References btr_cur_compress_if_useful(), btr_cur_pessimistic_delete(), btr_cur_position(), btr_page_get_father_node_ptr(), buf_block_align(), DB_SUCCESS, err, FALSE, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, dict_tree_struct::tree_index, TRUE, ut_a, and ut_ad.
Referenced by btr_compress(), btr_cur_pessimistic_delete(), and btr_discard_page().
01917 : index tree */ 01918 page_t* page, /* in: page whose node pointer is deleted */ 01919 mtr_t* mtr) /* in: mtr */ 01920 { 01921 rec_t* node_ptr; 01922 btr_cur_t cursor; 01923 ibool compressed; 01924 ulint err; 01925 01926 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01927 MTR_MEMO_PAGE_X_FIX)); 01928 /* Delete node pointer on father page */ 01929 01930 node_ptr = btr_page_get_father_node_ptr(tree, page, mtr); 01931 01932 btr_cur_position(tree->tree_index, node_ptr, &cursor); 01933 compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE, 01934 mtr); 01935 ut_a(err == DB_SUCCESS); 01936 01937 if (!compressed) { 01938 btr_cur_compress_if_useful(&cursor, mtr); 01939 } 01940 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static page_t* btr_node_ptr_get_child | ( | rec_t * | node_ptr, | |
| const ulint * | offsets, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 531 of file btr0btr.c.
References btr_node_ptr_get_child_page_no(), btr_page_get(), buf_frame_get_space_id(), NULL, page, page_t, rec_offs_validate(), RW_X_LATCH, and ut_ad.
Referenced by btr_validate_level().
00533 : child page, x-latched */ 00534 rec_t* node_ptr,/* in: node pointer */ 00535 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 00536 mtr_t* mtr) /* in: mtr */ 00537 { 00538 ulint page_no; 00539 ulint space; 00540 page_t* page; 00541 00542 ut_ad(rec_offs_validate(node_ptr, NULL, offsets)); 00543 space = buf_frame_get_space_id(node_ptr); 00544 page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); 00545 00546 page = btr_page_get(space, page_no, RW_X_LATCH, mtr); 00547 00548 return(page); 00549 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void btr_node_ptr_set_child_page_no | ( | rec_t * | rec, | |
| const ulint * | offsets, | |||
| ulint | page_no, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 504 of file btr0btr.c.
References btr_page_get_level(), buf_frame_align(), MLOG_4BYTES, mlog_write_ulint(), NULL, rec_get_node_ptr_flag(), rec_get_nth_field(), rec_offs_comp(), rec_offs_n_fields(), rec_offs_validate(), and ut_ad.
Referenced by btr_attach_half_pages(), and btr_compress().
00506 : node pointer record */ 00507 const ulint* offsets,/* in: array returned by rec_get_offsets() */ 00508 ulint page_no,/* in: child node address */ 00509 mtr_t* mtr) /* in: mtr */ 00510 { 00511 byte* field; 00512 ulint len; 00513 00514 ut_ad(rec_offs_validate(rec, NULL, offsets)); 00515 ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr)); 00516 ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec)); 00517 00518 /* The child address is in the last field */ 00519 field = rec_get_nth_field(rec, offsets, 00520 rec_offs_n_fields(offsets) - 1, &len); 00521 00522 ut_ad(len == 4); 00523 00524 mlog_write_ulint(field, page_no, MLOG_4BYTES, mtr); 00525 }
Here is the call graph for this function:

Here is the caller graph for this function:

| page_t* btr_page_alloc | ( | dict_tree_t * | tree, | |
| ulint | hint_page_no, | |||
| byte | file_direction, | |||
| ulint | level, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 316 of file btr0btr.c.
References btr_page_alloc_for_ibuf(), btr_root_get(), buf_page_get, DICT_IBUF, dict_tree_get_space(), FIL_NULL, fseg_alloc_free_page_general(), NULL, PAGE_BTR_SEG_LEAF, PAGE_BTR_SEG_TOP, PAGE_HEADER, page_t, RW_X_LATCH, SYNC_TREE_NODE_NEW, TRUE, and dict_tree_struct::type.
Referenced by btr_page_split_and_insert(), btr_root_raise_and_insert(), and btr_store_big_rec_extern_fields().
00318 : new allocated page, x-latched; 00319 NULL if out of space */ 00320 dict_tree_t* tree, /* in: index tree */ 00321 ulint hint_page_no, /* in: hint of a good page */ 00322 byte file_direction, /* in: direction where a possible 00323 page split is made */ 00324 ulint level, /* in: level where the page is placed 00325 in the tree */ 00326 mtr_t* mtr) /* in: mtr */ 00327 { 00328 fseg_header_t* seg_header; 00329 page_t* root; 00330 page_t* new_page; 00331 ulint new_page_no; 00332 00333 if (tree->type & DICT_IBUF) { 00334 00335 return(btr_page_alloc_for_ibuf(tree, mtr)); 00336 } 00337 00338 root = btr_root_get(tree, mtr); 00339 00340 if (level == 0) { 00341 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; 00342 } else { 00343 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; 00344 } 00345 00346 /* Parameter TRUE below states that the caller has made the 00347 reservation for free extents, and thus we know that a page can 00348 be allocated: */ 00349 00350 new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no, 00351 file_direction, TRUE, mtr); 00352 if (new_page_no == FIL_NULL) { 00353 00354 return(NULL); 00355 } 00356 00357 new_page = buf_page_get(dict_tree_get_space(tree), new_page_no, 00358 RW_X_LATCH, mtr); 00359 #ifdef UNIV_SYNC_DEBUG 00360 buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW); 00361 #endif /* UNIV_SYNC_DEBUG */ 00362 00363 return(new_page); 00364 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static page_t* btr_page_alloc_for_ibuf | ( | dict_tree_t * | tree, | |
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 281 of file btr0btr.c.
References btr_root_get(), buf_page_get, dict_tree_get_space(), FIL_NULL, flst_get_first(), flst_remove(), flst_validate(), fil_addr_struct::page, PAGE_BTR_IBUF_FREE_LIST, PAGE_BTR_IBUF_FREE_LIST_NODE, PAGE_HEADER, page_t, RW_X_LATCH, SYNC_TREE_NODE_NEW, ut_a, and ut_ad.
Referenced by btr_page_alloc().
00283 : new allocated page, x-latched */ 00284 dict_tree_t* tree, /* in: index tree */ 00285 mtr_t* mtr) /* in: mtr */ 00286 { 00287 fil_addr_t node_addr; 00288 page_t* root; 00289 page_t* new_page; 00290 00291 root = btr_root_get(tree, mtr); 00292 00293 node_addr = flst_get_first(root + PAGE_HEADER 00294 + PAGE_BTR_IBUF_FREE_LIST, mtr); 00295 ut_a(node_addr.page != FIL_NULL); 00296 00297 new_page = buf_page_get(dict_tree_get_space(tree), node_addr.page, 00298 RW_X_LATCH, mtr); 00299 #ifdef UNIV_SYNC_DEBUG 00300 buf_page_dbg_add_level(new_page, SYNC_TREE_NODE_NEW); 00301 #endif /* UNIV_SYNC_DEBUG */ 00302 00303 flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 00304 new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, 00305 mtr); 00306 ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); 00307 00308 return(new_page); 00309 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_page_create | ( | page_t * | page, | |
| dict_tree_t * | tree, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 261 of file btr0btr.c.
References buf_block_align(), buf_block_struct::check_index_page_at_flush, dict_table_is_comp(), dict_tree_struct::id, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, page_create(), dict_index_struct::table, dict_tree_struct::tree_index, TRUE, and ut_ad.
Referenced by btr_page_split_and_insert(), and btr_root_raise_and_insert().
00263 : page to be created */ 00264 dict_tree_t* tree, /* in: index tree */ 00265 mtr_t* mtr) /* in: mtr */ 00266 { 00267 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00268 MTR_MEMO_PAGE_X_FIX)); 00269 page_create(page, mtr, 00270 dict_table_is_comp(tree->tree_index->table)); 00271 buf_block_align(page)->check_index_page_at_flush = TRUE; 00272 00273 btr_page_set_index_id(page, tree->id, mtr); 00274 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 960 of file btr0btr.c.
References btr_search_drop_page_hash_index(), buf_block_align(), buf_block_struct::check_index_page_at_flush, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, page_create(), page_is_comp(), TRUE, and ut_ad.
Referenced by btr_discard_only_page_on_level(), and btr_lift_page_up().
00962 : page to be emptied */ 00963 mtr_t* mtr) /* in: mtr */ 00964 { 00965 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00966 MTR_MEMO_PAGE_X_FIX)); 00967 btr_search_drop_page_hash_index(page); 00968 00969 /* Recreate the page: note that global data on page (possible 00970 segment headers, next page-field, etc.) is preserved intact */ 00971 00972 page_create(page, mtr, page_is_comp(page)); 00973 buf_block_align(page)->check_index_page_at_flush = TRUE; 00974 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_page_free | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 485 of file btr0btr.c.
References btr_page_free_low(), btr_page_get_level(), buf_block_align(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, and ut_ad.
Referenced by btr_compress(), btr_discard_only_page_on_level(), btr_discard_page(), and btr_lift_page_up().
00487 : index tree */ 00488 page_t* page, /* in: page to be freed, x-latched */ 00489 mtr_t* mtr) /* in: mtr */ 00490 { 00491 ulint level; 00492 00493 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00494 MTR_MEMO_PAGE_X_FIX)); 00495 level = btr_page_get_level(page, mtr); 00496 00497 btr_page_free_low(tree, page, level, mtr); 00498 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_page_free_for_ibuf | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 415 of file btr0btr.c.
References btr_root_get(), buf_block_align(), flst_add_first(), flst_validate(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, PAGE_BTR_IBUF_FREE_LIST, PAGE_BTR_IBUF_FREE_LIST_NODE, PAGE_HEADER, page_t, and ut_ad.
Referenced by btr_page_free_low().
00417 : index tree */ 00418 page_t* page, /* in: page to be freed, x-latched */ 00419 mtr_t* mtr) /* in: mtr */ 00420 { 00421 page_t* root; 00422 00423 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00424 MTR_MEMO_PAGE_X_FIX)); 00425 root = btr_root_get(tree, mtr); 00426 00427 flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 00428 page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); 00429 00430 ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 00431 mtr)); 00432 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_page_free_low | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| ulint | level, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 440 of file btr0btr.c.
References btr_page_free_for_ibuf(), btr_root_get(), buf_block_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), buf_frame_modify_clock_inc(), DICT_IBUF, fseg_free_page(), mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, PAGE_BTR_SEG_LEAF, PAGE_BTR_SEG_TOP, PAGE_HEADER, page_t, dict_tree_struct::type, and ut_ad.
Referenced by btr_free_externally_stored_field(), and btr_page_free().
00442 : index tree */ 00443 page_t* page, /* in: page to be freed, x-latched */ 00444 ulint level, /* in: page level */ 00445 mtr_t* mtr) /* in: mtr */ 00446 { 00447 fseg_header_t* seg_header; 00448 page_t* root; 00449 ulint space; 00450 ulint page_no; 00451 00452 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00453 MTR_MEMO_PAGE_X_FIX)); 00454 /* The page gets invalid for optimistic searches: increment the frame 00455 modify clock */ 00456 00457 buf_frame_modify_clock_inc(page); 00458 00459 if (tree->type & DICT_IBUF) { 00460 00461 btr_page_free_for_ibuf(tree, page, mtr); 00462 00463 return; 00464 } 00465 00466 root = btr_root_get(tree, mtr); 00467 00468 if (level == 0) { 00469 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; 00470 } else { 00471 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; 00472 } 00473 00474 space = buf_frame_get_space_id(page); 00475 page_no = buf_frame_get_page_no(page); 00476 00477 fseg_free_page(seg_header, space, page_no, mtr); 00478 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static rec_t* btr_page_get_father_for_rec | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| rec_t * | user_rec, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 556 of file btr0btr.c.
References BTR_CONT_MODIFY_TREE, btr_cur_get_rec(), btr_cur_search_to_nth_level(), btr_node_ptr_get_child_page_no(), btr_page_get_level(), buf_frame_align(), buf_frame_get_page_no(), buf_page_print(), dict_tree_build_node_ptr(), dict_tree_get_lock(), dict_tree_get_page(), FALSE, index(), mem_heap_create, mem_heap_free, mtr_memo_contains(), MTR_MEMO_X_LOCK, NULL, PAGE_CUR_LE, page_get_infimum_rec(), page_rec_get_next(), page_rec_is_user_rec(), page_rec_print(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, dict_tree_struct::tree_index, TRUE, ut_a, ut_ad, and ut_print_name().
Referenced by btr_page_get_father_node_ptr(), and btr_validate_level().
00558 : pointer to node pointer record, 00559 its page x-latched */ 00560 dict_tree_t* tree, /* in: index tree */ 00561 page_t* page, /* in: page: must contain at least one 00562 user record */ 00563 rec_t* user_rec,/* in: user_record on page */ 00564 mtr_t* mtr) /* in: mtr */ 00565 { 00566 mem_heap_t* heap; 00567 dtuple_t* tuple; 00568 btr_cur_t cursor; 00569 rec_t* node_ptr; 00570 dict_index_t* index; 00571 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 00572 ulint* offsets = offsets_; 00573 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 00574 00575 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 00576 MTR_MEMO_X_LOCK)); 00577 ut_a(page_rec_is_user_rec(user_rec)); 00578 00579 ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); 00580 00581 heap = mem_heap_create(100); 00582 00583 tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap, 00584 btr_page_get_level(page, mtr)); 00585 index = tree->tree_index; 00586 00587 /* In the following, we choose just any index from the tree as the 00588 first parameter for btr_cur_search_to_nth_level. */ 00589 00590 btr_cur_search_to_nth_level(index, 00591 btr_page_get_level(page, mtr) + 1, 00592 tuple, PAGE_CUR_LE, 00593 BTR_CONT_MODIFY_TREE, &cursor, 0, mtr); 00594 00595 node_ptr = btr_cur_get_rec(&cursor); 00596 offsets = rec_get_offsets(node_ptr, index, offsets, 00597 ULINT_UNDEFINED, &heap); 00598 00599 if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != 00600 buf_frame_get_page_no(page)) { 00601 rec_t* print_rec; 00602 fputs("InnoDB: Dump of the child page:\n", stderr); 00603 buf_page_print(buf_frame_align(page)); 00604 fputs("InnoDB: Dump of the parent page:\n", stderr); 00605 buf_page_print(buf_frame_align(node_ptr)); 00606 00607 fputs("InnoDB: Corruption of an index tree: table ", stderr); 00608 ut_print_name(stderr, NULL, TRUE, index->table_name); 00609 fputs(", index ", stderr); 00610 ut_print_name(stderr, NULL, FALSE, index->name); 00611 fprintf(stderr, ",\n" 00612 "InnoDB: father ptr page no %lu, child page no %lu\n", 00613 (ulong) 00614 btr_node_ptr_get_child_page_no(node_ptr, offsets), 00615 (ulong) buf_frame_get_page_no(page)); 00616 print_rec = page_rec_get_next(page_get_infimum_rec(page)); 00617 offsets = rec_get_offsets(print_rec, index, 00618 offsets, ULINT_UNDEFINED, &heap); 00619 page_rec_print(print_rec, offsets); 00620 offsets = rec_get_offsets(node_ptr, index, offsets, 00621 ULINT_UNDEFINED, &heap); 00622 page_rec_print(node_ptr, offsets); 00623 00624 fputs( 00625 "InnoDB: You should dump + drop + reimport the table to fix the\n" 00626 "InnoDB: corruption. If the crash happens at the database startup, see\n" 00627 "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html about\n" 00628 "InnoDB: forcing recovery. Then dump + drop + reimport.\n", stderr); 00629 } 00630 00631 ut_a(btr_node_ptr_get_child_page_no(node_ptr, offsets) == 00632 buf_frame_get_page_no(page)); 00633 mem_heap_free(heap); 00634 00635 return(node_ptr); 00636 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static rec_t * btr_page_get_father_node_ptr | ( | dict_tree_t * | tree, | |
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 643 of file btr0btr.c.
References btr_page_get_father_for_rec(), page_get_infimum_rec(), and page_rec_get_next().
Referenced by btr_attach_half_pages(), btr_compress(), btr_discard_only_page_on_level(), btr_lift_page_up(), btr_node_ptr_delete(), and btr_validate_level().
00645 : pointer to node pointer record */ 00646 dict_tree_t* tree, /* in: index tree */ 00647 page_t* page, /* in: page: must contain at least one 00648 user record */ 00649 mtr_t* mtr) /* in: mtr */ 00650 { 00651 return(btr_page_get_father_for_rec(tree, page, 00652 page_rec_get_next(page_get_infimum_rec(page)), mtr)); 00653 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1098 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_rec(), FALSE, page, page_get_infimum_rec(), page_header_get_ptr(), PAGE_LAST_INSERT, page_rec_get_next(), page_t, and TRUE.
Referenced by btr_cur_optimistic_insert(), and btr_page_split_and_insert().
01100 : TRUE if split recommended */ 01101 btr_cur_t* cursor, /* in: cursor at which to insert */ 01102 rec_t** split_rec) /* out: if split recommended, 01103 the first record on upper half page, 01104 or NULL if tuple to be inserted should 01105 be first */ 01106 { 01107 page_t* page; 01108 rec_t* insert_point; 01109 rec_t* infimum; 01110 01111 page = btr_cur_get_page(cursor); 01112 insert_point = btr_cur_get_rec(cursor); 01113 01114 if (page_header_get_ptr(page, PAGE_LAST_INSERT) 01115 == page_rec_get_next(insert_point)) { 01116 01117 infimum = page_get_infimum_rec(page); 01118 01119 /* If the convergence is in the middle of a page, include also 01120 the record immediately before the new insert to the upper 01121 page. Otherwise, we could repeatedly move from page to page 01122 lots of records smaller than the convergence point. */ 01123 01124 if (infimum != insert_point 01125 && page_rec_get_next(infimum) != insert_point) { 01126 01127 *split_rec = insert_point; 01128 } else { 01129 *split_rec = page_rec_get_next(insert_point); 01130 } 01131 01132 return(TRUE); 01133 } 01134 01135 return(FALSE); 01136 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1143 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_rec(), FALSE, NULL, page, page_header_get_ptr(), PAGE_LAST_INSERT, page_rec_get_next(), page_rec_is_supremum(), page_t, and TRUE.
Referenced by btr_cur_optimistic_insert(), and btr_page_split_and_insert().
01145 : TRUE if split recommended */ 01146 btr_cur_t* cursor, /* in: cursor at which to insert */ 01147 rec_t** split_rec) /* out: if split recommended, 01148 the first record on upper half page, 01149 or NULL if tuple to be inserted should 01150 be first */ 01151 { 01152 page_t* page; 01153 rec_t* insert_point; 01154 01155 page = btr_cur_get_page(cursor); 01156 insert_point = btr_cur_get_rec(cursor); 01157 01158 /* We use eager heuristics: if the new insert would be right after 01159 the previous insert on the same page, we assume that there is a 01160 pattern of sequential inserts here. */ 01161 01162 if (UNIV_LIKELY(page_header_get_ptr(page, PAGE_LAST_INSERT) 01163 == insert_point)) { 01164 01165 rec_t* next_rec; 01166 01167 next_rec = page_rec_get_next(insert_point); 01168 01169 if (page_rec_is_supremum(next_rec)) { 01170 split_at_new: 01171 /* Split at the new record to insert */ 01172 *split_rec = NULL; 01173 } else { 01174 rec_t* next_next_rec = page_rec_get_next(next_rec); 01175 if (page_rec_is_supremum(next_next_rec)) { 01176 01177 goto split_at_new; 01178 } 01179 01180 /* If there are >= 2 user records up from the insert 01181 point, split all but 1 off. We want to keep one because 01182 then sequential inserts can use the adaptive hash 01183 index, as they can do the necessary checks of the right 01184 search position just by looking at the records on this 01185 page. */ 01186 01187 *split_rec = next_next_rec; 01188 } 01189 01190 return(TRUE); 01191 } 01192 01193 return(FALSE); 01194 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1202 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_rec(), btr_cur_struct::index, mem_heap_free, n, NULL, page, page_dir_calc_reserved_space(), page_get_data_size(), page_get_free_space_of_empty(), page_get_infimum_rec(), page_get_n_recs(), page_is_comp(), page_rec_get_next(), page_rec_is_supremum(), page_t, rec_get_converted_size(), rec_get_offsets, rec_offs_size(), and ut_ad.
Referenced by btr_page_split_and_insert().
01204 : split record, or NULL if 01205 tuple will be the first record on 01206 upper half-page */ 01207 btr_cur_t* cursor, /* in: cursor at which insert 01208 should be made */ 01209 dtuple_t* tuple) /* in: tuple to insert */ 01210 { 01211 page_t* page; 01212 ulint insert_size; 01213 ulint free_space; 01214 ulint total_data; 01215 ulint total_n_recs; 01216 ulint total_space; 01217 ulint incl_data; 01218 rec_t* ins_rec; 01219 rec_t* rec; 01220 rec_t* next_rec; 01221 ulint n; 01222 mem_heap_t* heap; 01223 ulint* offsets; 01224 01225 page = btr_cur_get_page(cursor); 01226 01227 insert_size = rec_get_converted_size(cursor->index, tuple); 01228 free_space = page_get_free_space_of_empty(page_is_comp(page)); 01229 01230 /* free_space is now the free space of a created new page */ 01231 01232 total_data = page_get_data_size(page) + insert_size; 01233 total_n_recs = page_get_n_recs(page) + 1; 01234 ut_ad(total_n_recs >= 2); 01235 total_space = total_data + page_dir_calc_reserved_space(total_n_recs); 01236 01237 n = 0; 01238 incl_data = 0; 01239 ins_rec = btr_cur_get_rec(cursor); 01240 rec = page_get_infimum_rec(page); 01241 01242 heap = NULL; 01243 offsets = NULL; 01244 01245 /* We start to include records to the left half, and when the 01246 space reserved by them exceeds half of total_space, then if 01247 the included records fit on the left page, they will be put there 01248 if something was left over also for the right page, 01249 otherwise the last included record will be the first on the right 01250 half page */ 01251 01252 for (;;) { 01253 /* Decide the next record to include */ 01254 if (rec == ins_rec) { 01255 rec = NULL; /* NULL denotes that tuple is 01256 now included */ 01257 } else if (rec == NULL) { 01258 rec = page_rec_get_next(ins_rec); 01259 } else { 01260 rec = page_rec_get_next(rec); 01261 } 01262 01263 if (rec == NULL) { 01264 /* Include tuple */ 01265 incl_data += insert_size; 01266 } else { 01267 offsets = rec_get_offsets(rec, cursor->index, 01268 offsets, ULINT_UNDEFINED, &heap); 01269 incl_data += rec_offs_size(offsets); 01270 } 01271 01272 n++; 01273 01274 if (incl_data + page_dir_calc_reserved_space(n) 01275 >= total_space / 2) { 01276 01277 if (incl_data + page_dir_calc_reserved_space(n) 01278 <= free_space) { 01279 /* The next record will be the first on 01280 the right half page if it is not the 01281 supremum record of page */ 01282 01283 if (rec == ins_rec) { 01284 rec = NULL; 01285 01286 goto func_exit; 01287 } else if (rec == NULL) { 01288 next_rec = page_rec_get_next(ins_rec); 01289 } else { 01290 next_rec = page_rec_get_next(rec); 01291 } 01292 ut_ad(next_rec); 01293 if (!page_rec_is_supremum(next_rec)) { 01294 rec = next_rec; 01295 } 01296 } 01297 01298 func_exit: 01299 if (UNIV_LIKELY_NULL(heap)) { 01300 mem_heap_free(heap); 01301 } 01302 return(rec); 01303 } 01304 } 01305 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool btr_page_insert_fits | ( | btr_cur_t * | cursor, | |
| rec_t * | split_rec, | |||
| const ulint * | offsets, | |||
| dtuple_t * | tuple, | |||
| mem_heap_t * | heap | |||
| ) | [static] |
Definition at line 1312 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_rec(), cmp_dtuple_rec(), FALSE, btr_cur_struct::index, NULL, page, page_dir_calc_reserved_space(), page_get_data_size(), page_get_free_space_of_empty(), page_get_infimum_rec(), page_get_n_recs(), page_get_supremum_rec(), page_is_comp(), page_rec_get_next(), page_t, rec_get_converted_size(), rec_get_offsets, rec_offs_comp(), rec_offs_size(), rec_offs_validate(), TRUE, and ut_ad.
Referenced by btr_page_split_and_insert().
01314 : TRUE if fits */ 01315 btr_cur_t* cursor, /* in: cursor at which insert 01316 should be made */ 01317 rec_t* split_rec, /* in: suggestion for first record 01318 on upper half-page, or NULL if 01319 tuple to be inserted should be first */ 01320 const ulint* offsets, /* in: rec_get_offsets( 01321 split_rec, cursor->index) */ 01322 dtuple_t* tuple, /* in: tuple to insert */ 01323 mem_heap_t* heap) /* in: temporary memory heap */ 01324 { 01325 page_t* page; 01326 ulint insert_size; 01327 ulint free_space; 01328 ulint total_data; 01329 ulint total_n_recs; 01330 rec_t* rec; 01331 rec_t* end_rec; 01332 ulint* offs; 01333 01334 page = btr_cur_get_page(cursor); 01335 01336 ut_ad(!split_rec == !offsets); 01337 ut_ad(!offsets 01338 || !page_is_comp(page) == !rec_offs_comp(offsets)); 01339 ut_ad(!offsets 01340 || rec_offs_validate(split_rec, cursor->index, offsets)); 01341 01342 insert_size = rec_get_converted_size(cursor->index, tuple); 01343 free_space = page_get_free_space_of_empty(page_is_comp(page)); 01344 01345 /* free_space is now the free space of a created new page */ 01346 01347 total_data = page_get_data_size(page) + insert_size; 01348 total_n_recs = page_get_n_recs(page) + 1; 01349 01350 /* We determine which records (from rec to end_rec, not including 01351 end_rec) will end up on the other half page from tuple when it is 01352 inserted. */ 01353 01354 if (split_rec == NULL) { 01355 rec = page_rec_get_next(page_get_infimum_rec(page)); 01356 end_rec = page_rec_get_next(btr_cur_get_rec(cursor)); 01357 01358 } else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) { 01359 01360 rec = page_rec_get_next(page_get_infimum_rec(page)); 01361 end_rec = split_rec; 01362 } else { 01363 rec = split_rec; 01364 end_rec = page_get_supremum_rec(page); 01365 } 01366 01367 if (total_data + page_dir_calc_reserved_space(total_n_recs) 01368 <= free_space) { 01369 01370 /* Ok, there will be enough available space on the 01371 half page where the tuple is inserted */ 01372 01373 return(TRUE); 01374 } 01375 01376 offs = NULL; 01377 01378 while (rec != end_rec) { 01379 /* In this loop we calculate the amount of reserved 01380 space after rec is removed from page. */ 01381 01382 offs = rec_get_offsets(rec, cursor->index, offs, 01383 ULINT_UNDEFINED, &heap); 01384 01385 total_data -= rec_offs_size(offs); 01386 total_n_recs--; 01387 01388 if (total_data + page_dir_calc_reserved_space(total_n_recs) 01389 <= free_space) { 01390 01391 /* Ok, there will be enough available space on the 01392 half page where the tuple is inserted */ 01393 01394 return(TRUE); 01395 } 01396 01397 rec = page_rec_get_next(rec); 01398 } 01399 01400 return(FALSE); 01401 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void btr_page_reorganize | ( | page_t * | page, | |
| dict_index_t * | index, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 922 of file btr0btr.c.
References btr_page_reorganize_low(), FALSE, and index().
Referenced by btr_compress(), btr_cur_insert_if_possible(), btr_cur_optimistic_insert(), btr_page_split_and_insert(), btr_root_raise_and_insert(), and ibuf_insert_to_index_page().
00924 : page to be reorganized */ 00925 dict_index_t* index, /* in: record descriptor */ 00926 mtr_t* mtr) /* in: mtr */ 00927 { 00928 btr_page_reorganize_low(FALSE, page, index, mtr); 00929 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_page_reorganize_low | ( | ibool | recovery, | |
| page_t * | page, | |||
| dict_index_t * | index, | |||
| mtr_t * | mtr | |||
| ) | [static] |
Definition at line 837 of file btr0btr.c.
References btr_search_drop_page_hash_index(), buf_block_align(), buf_frame_alloc(), buf_frame_copy(), buf_frame_free(), buf_page_print(), buf_block_struct::check_index_page_at_flush, dict_table_is_comp(), index(), lock_move_reorganize_page(), MLOG_COMP_PAGE_REORGANIZE, mlog_open_and_write_index(), MLOG_PAGE_REORGANIZE, MTR_LOG_NONE, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, mtr_set_log_mode(), page_copy_rec_list_end_no_locks(), page_create(), page_get_data_size(), page_get_infimum_rec(), page_get_max_insert_size_after_reorganize(), page_get_max_trx_id(), page_is_comp(), page_set_max_trx_id(), page_t, TRUE, and ut_ad.
Referenced by btr_page_reorganize(), and btr_parse_page_reorganize().
00839 : TRUE if called in recovery: 00840 locks should not be updated, i.e., 00841 there cannot exist locks on the 00842 page, and a hash index should not be 00843 dropped: it cannot exist */ 00844 page_t* page, /* in: page to be reorganized */ 00845 dict_index_t* index, /* in: record descriptor */ 00846 mtr_t* mtr) /* in: mtr */ 00847 { 00848 page_t* new_page; 00849 ulint log_mode; 00850 ulint data_size1; 00851 ulint data_size2; 00852 ulint max_ins_size1; 00853 ulint max_ins_size2; 00854 00855 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 00856 MTR_MEMO_PAGE_X_FIX)); 00857 ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); 00858 data_size1 = page_get_data_size(page); 00859 max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1); 00860 00861 /* Write the log record */ 00862 mlog_open_and_write_index(mtr, page, index, page_is_comp(page) 00863 ? MLOG_COMP_PAGE_REORGANIZE 00864 : MLOG_PAGE_REORGANIZE, 0); 00865 00866 /* Turn logging off */ 00867 log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); 00868 00869 new_page = buf_frame_alloc(); 00870 00871 /* Copy the old page to temporary space */ 00872 buf_frame_copy(new_page, page); 00873 00874 if (!recovery) { 00875 btr_search_drop_page_hash_index(page); 00876 } 00877 00878 /* Recreate the page: note that global data on page (possible 00879 segment headers, next page-field, etc.) is preserved intact */ 00880 00881 page_create(page, mtr, page_is_comp(page)); 00882 buf_block_align(page)->check_index_page_at_flush = TRUE; 00883 00884 /* Copy the records from the temporary space to the recreated page; 00885 do not copy the lock bits yet */ 00886 00887 page_copy_rec_list_end_no_locks(page, new_page, 00888 page_get_infimum_rec(new_page), index, mtr); 00889 /* Copy max trx id to recreated page */ 00890 page_set_max_trx_id(page, page_get_max_trx_id(new_page)); 00891 00892 if (!recovery) { 00893 /* Update the record lock bitmaps */ 00894 lock_move_reorganize_page(page, new_page); 00895 } 00896 00897 data_size2 = page_get_data_size(page); 00898 max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1); 00899 00900 if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) { 00901 buf_page_print(page); 00902 buf_page_print(new_page); 00903 fprintf(stderr, 00904 "InnoDB: Error: page old data size %lu new data size %lu\n" 00905 "InnoDB: Error: page old max ins size %lu new max ins size %lu\n" 00906 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", 00907 (unsigned long) data_size1, (unsigned long) data_size2, 00908 (unsigned long) max_ins_size1, 00909 (unsigned long) max_ins_size2); 00910 } 00911 00912 buf_frame_free(new_page); 00913 00914 /* Restore logging mode */ 00915 mtr_set_log_mode(mtr, log_mode); 00916 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1563 of file btr0btr.c.
References btr_attach_half_pages(), btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_rec(), btr_cur_get_tree(), btr_page_alloc(), btr_page_create(), btr_page_get_level(), btr_page_get_split_rec_to_left(), btr_page_get_split_rec_to_right(), btr_page_get_sure_split_rec(), btr_page_insert_fits(), btr_page_reorganize(), buf, buf_block_align(), buf_frame_get_page_no(), cmp_dtuple_rec(), dict_index_get_n_unique_in_tree(), dict_tree_get_lock(), FSP_DOWN, FSP_UP, ibuf_reset_free_bits(), ibuf_update_free_bits_for_two_pages_low(), btr_cur_struct::index, lock_update_split_left(), lock_update_split_right(), mem_alloc, mem_free, mem_heap_create, mem_heap_empty(), mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, mtr_memo_release(), MTR_MEMO_X_LOCK, NULL, page, PAGE_CUR_LE, page_cur_search(), page_cur_tuple_insert(), page_get_middle_rec(), page_get_n_recs(), page_move_rec_list_end(), page_move_rec_list_start(), page_rec_get_next(), page_t, page_validate(), rec_convert_dtuple_to_rec(), rec_get_converted_size(), rec_get_offsets, RW_LOCK_EX, dict_tree_struct::tree_index, and ut_ad.
Referenced by btr_cur_pessimistic_insert(), and btr_root_raise_and_insert().
01565 : inserted record; NOTE: the tree 01566 x-latch is released! NOTE: 2 free disk 01567 pages must be available! */ 01568 btr_cur_t* cursor, /* in: cursor at which to insert; when the 01569 function returns, the cursor is positioned 01570 on the predecessor of the inserted record */ 01571 dtuple_t* tuple, /* in: tuple to insert */ 01572 mtr_t* mtr) /* in: mtr */ 01573 { 01574 dict_tree_t* tree; 01575 page_t* page; 01576 ulint page_no; 01577 byte direction; 01578 ulint hint_page_no; 01579 page_t* new_page; 01580 rec_t* split_rec; 01581 page_t* left_page; 01582 page_t* right_page; 01583 page_t* insert_page; 01584 page_cur_t* page_cursor; 01585 rec_t* first_rec; 01586 byte* buf = 0; /* remove warning */ 01587 rec_t* move_limit; 01588 ibool insert_will_fit; 01589 ulint n_iterations = 0; 01590 rec_t* rec; 01591 mem_heap_t* heap; 01592 ulint n_uniq; 01593 ulint* offsets; 01594 01595 heap = mem_heap_create(1024); 01596 n_uniq = dict_index_get_n_unique_in_tree(cursor->index); 01597 func_start: 01598 mem_heap_empty(heap); 01599 offsets = NULL; 01600 tree = btr_cur_get_tree(cursor); 01601 01602 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 01603 MTR_MEMO_X_LOCK)); 01604 #ifdef UNIV_SYNC_DEBUG 01605 ut_ad(rw_lock_own(dict_tree_get_lock(tree), RW_LOCK_EX)); 01606 #endif /* UNIV_SYNC_DEBUG */ 01607 01608 page = btr_cur_get_page(cursor); 01609 01610 ut_ad(mtr_memo_contains(mtr, buf_block_align(page), 01611 MTR_MEMO_PAGE_X_FIX)); 01612 ut_ad(page_get_n_recs(page) >= 2); 01613 01614 page_no = buf_frame_get_page_no(page); 01615 01616 /* 1. Decide the split record; split_rec == NULL means that the 01617 tuple to be inserted should be the first record on the upper 01618 half-page */ 01619 01620 if (n_iterations > 0) { 01621 direction = FSP_UP; 01622 hint_page_no = page_no + 1; 01623 split_rec = btr_page_get_sure_split_rec(cursor, tuple); 01624 01625 } else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) { 01626 direction = FSP_UP; 01627 hint_page_no = page_no + 1; 01628 01629 } else if (btr_page_get_split_rec_to_left(cursor, &split_rec)) { 01630 direction = FSP_DOWN; 01631 hint_page_no = page_no - 1; 01632 } else { 01633 direction = FSP_UP; 01634 hint_page_no = page_no + 1; 01635 split_rec = page_get_middle_rec(page); 01636 } 01637 01638 /* 2. Allocate a new page to the tree */ 01639 new_page = btr_page_alloc(tree, hint_page_no, direction, 01640 btr_page_get_level(page, mtr), mtr); 01641 btr_page_create(new_page, tree, mtr); 01642 01643 /* 3. Calculate the first record on the upper half-page, and the 01644 first record (move_limit) on original page which ends up on the 01645 upper half */ 01646 01647 if (split_rec != NULL) { 01648 first_rec = split_rec; 01649 move_limit = split_rec; 01650 } else { 01651 buf = mem_alloc(rec_get_converted_size(cursor->index, tuple)); 01652 01653 first_rec = rec_convert_dtuple_to_rec(buf, 01654 cursor->index, tuple); 01655 move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); 01656 } 01657 01658 /* 4. Do first the modifications in the tree structure */ 01659 01660 btr_attach_half_pages(tree, page, first_rec, new_page, direction, mtr); 01661 01662 if (split_rec == NULL) { 01663 mem_free(buf); 01664 } 01665 01666 /* If the split is made on the leaf level and the insert will fit 01667 on the appropriate half-page, we may release the tree x-latch. 01668 We can then move the records after releasing the tree latch, 01669 thus reducing the tree latch contention. */ 01670 01671 if (split_rec) { 01672 offsets = rec_get_offsets(split_rec, cursor->index, offsets, 01673 n_uniq, &heap); 01674 01675 insert_will_fit = btr_page_insert_fits(cursor, 01676 split_rec, offsets, tuple, heap); 01677 } else { 01678 insert_will_fit = btr_page_insert_fits(cursor, 01679 NULL, NULL, tuple, heap); 01680 } 01681 01682 if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) { 01683 01684 mtr_memo_release(mtr, dict_tree_get_lock(tree), 01685 MTR_MEMO_X_LOCK); 01686 } 01687 01688 /* 5. Move then the records to the new page */ 01689 if (direction == FSP_DOWN) { 01690 /* fputs("Split left\n", stderr); */ 01691 01692 page_move_rec_list_start(new_page, page, move_limit, 01693 cursor->index, mtr); 01694 left_page = new_page; 01695 right_page = page; 01696 01697 lock_update_split_left(right_page, left_page); 01698 } else { 01699 /* fputs("Split right\n", stderr); */ 01700 01701 page_move_rec_list_end(new_page, page, move_limit, 01702 cursor->index, mtr); 01703 left_page = page; 01704 right_page = new_page; 01705 01706 lock_update_split_right(right_page, left_page); 01707 } 01708 01709 /* 6. The split and the tree modification is now completed. Decide the 01710 page where the tuple should be inserted */ 01711 01712 if (split_rec == NULL) { 01713 insert_page = right_page; 01714 01715 } else { 01716 offsets = rec_get_offsets(first_rec, cursor->index, 01717 offsets, n_uniq, &heap); 01718 01719 if (cmp_dtuple_rec(tuple, first_rec, offsets) >= 0) { 01720 01721 insert_page = right_page; 01722 } else { 01723 insert_page = left_page; 01724 } 01725 } 01726 01727 /* 7. Reposition the cursor for insert and try insertion */ 01728 page_cursor = btr_cur_get_page_cur(cursor); 01729 01730 page_cur_search(insert_page, cursor->index, tuple, 01731 PAGE_CUR_LE, page_cursor); 01732 01733 rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr); 01734 01735 if (rec != NULL) { 01736 /* Insert fit on the page: update the free bits for the 01737 left and right pages in the same mtr */ 01738 01739 ibuf_update_free_bits_for_two_pages_low(cursor->index, 01740 left_page, 01741 right_page, mtr); 01742 /* fprintf(stderr, "Split and insert done %lu %lu\n", 01743 buf_frame_get_page_no(left_page), 01744 buf_frame_get_page_no(right_page)); */ 01745 mem_heap_free(heap); 01746 return(rec); 01747 } 01748 01749 /* 8. If insert did not fit, try page reorganization */ 01750 01751 btr_page_reorganize(insert_page, cursor->index, mtr); 01752 01753 page_cur_search(insert_page, cursor->index, tuple, 01754 PAGE_CUR_LE, page_cursor); 01755 rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr); 01756 01757 if (rec == NULL) { 01758 /* The insert did not fit on the page: loop back to the 01759 start of the function for a new split */ 01760 01761 /* We play safe and reset the free bits for new_page */ 01762 ibuf_reset_free_bits(cursor->index, new_page); 01763 01764 /* fprintf(stderr, "Split second round %lu\n", 01765 buf_frame_get_page_no(page)); */ 01766 n_iterations++; 01767 ut_ad(n_iterations < 2); 01768 ut_ad(!insert_will_fit); 01769 01770 goto func_start; 01771 } 01772 01773 /* Insert fit on the page: update the free bits for the 01774 left and right pages in the same mtr */ 01775 01776 ibuf_update_free_bits_for_two_pages_low(cursor->index, left_page, 01777 right_page, mtr); 01778 /* fprintf(stderr, "Split and insert done %lu %lu\n", 01779 buf_frame_get_page_no(left_page), 01780 buf_frame_get_page_no(right_page)); */ 01781 01782 ut_ad(page_validate(left_page, tree->tree_index)); 01783 ut_ad(page_validate(right_page, tree->tree_index)); 01784 01785 mem_heap_free(heap); 01786 return(rec); 01787 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* btr_parse_page_reorganize | ( | byte * | ptr, | |
| byte *end_ptr | __attribute__((unused)), | |||
| dict_index_t * | index, | |||
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 935 of file btr0btr.c.
References btr_page_reorganize_low(), index(), TRUE, and ut_ad.
Referenced by recv_parse_or_apply_log_rec_body().
00937 : end of log record or NULL */ 00938 byte* ptr, /* in: buffer */ 00939 byte* end_ptr __attribute__((unused)), 00940 /* in: buffer end */ 00941 dict_index_t* index, /* in: record descriptor */ 00942 page_t* page, /* in: page or NULL */ 00943 mtr_t* mtr) /* in: mtr or NULL */ 00944 { 00945 ut_ad(ptr && end_ptr); 00946 00947 /* The record is empty, except for the record initial part */ 00948 00949 if (page) { 00950 btr_page_reorganize_low(TRUE, page, index, mtr); 00951 } 00952 00953 return(ptr); 00954 }
Here is the call graph for this function:

Here is the caller graph for this function:

| byte* btr_parse_set_min_rec_mark | ( | byte * | ptr, | |
| byte * | end_ptr, | |||
| ulint | comp, | |||
| page_t * | page, | |||
| mtr_t * | mtr | |||
| ) |
Definition at line 1865 of file btr0btr.c.
References btr_set_min_rec_mark(), mach_read_from_2(), NULL, page_is_comp(), and ut_a.
Referenced by recv_parse_or_apply_log_rec_body().
01867 : end of log record or NULL */ 01868 byte* ptr, /* in: buffer */ 01869 byte* end_ptr,/* in: buffer end */ 01870 ulint comp, /* in: nonzero=compact page format */ 01871 page_t* page, /* in: page or NULL */ 01872 mtr_t* mtr) /* in: mtr or NULL */ 01873 { 01874 rec_t* rec; 01875 01876 if (end_ptr < ptr + 2) { 01877 01878 return(NULL); 01879 } 01880 01881 if (page) { 01882 ut_a(!page_is_comp(page) == !comp); 01883 01884 rec = page + mach_read_from_2(ptr); 01885 01886 btr_set_min_rec_mark(rec, comp, mtr); 01887 } 01888 01889 return(ptr + 2); 01890 }
Here is the call graph for this function:

Here is the caller graph for this function:

| page_t* btr_root_get | ( | dict_tree_t * | tree, | |
| mtr_t * | mtr | |||
| ) |
Definition at line 132 of file btr0btr.c.
References btr_page_get(), dict_table_is_comp(), dict_tree_get_page(), dict_tree_get_space(), page_is_comp(), page_t, RW_X_LATCH, dict_index_struct::table, dict_tree_struct::tree_index, and ut_a.
Referenced by btr_get_size(), btr_page_alloc(), btr_page_alloc_for_ibuf(), btr_page_free_for_ibuf(), btr_page_free_low(), btr_validate_level(), btr_validate_tree(), and row_purge_upd_exist_or_extern().
00134 : root page, x-latched */ 00135 dict_tree_t* tree, /* in: index tree */ 00136 mtr_t* mtr) /* in: mtr */ 00137 { 00138 ulint space; 00139 ulint root_page_no; 00140 page_t* root; 00141 00142 space = dict_tree_get_space(tree); 00143 root_page_no = dict_tree_get_page(tree); 00144 00145 root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); 00146 ut_a((ibool)!!page_is_comp(root) == 00147 dict_table_is_comp(tree->tree_index->table)); 00148 00149 return(root); 00150 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 984 of file btr0btr.c.
References btr_cur_get_page(), btr_cur_get_page_cur(), btr_cur_get_tree(), btr_page_alloc(), btr_page_create(), btr_page_get_level(), btr_page_reorganize(), btr_page_split_and_insert(), btr_search_drop_page_hash_index(), btr_set_min_rec_mark(), buf_block_align(), buf_frame_get_page_no(), dict_tree_build_node_ptr(), dict_tree_get_lock(), dict_tree_get_page(), FIL_NULL, FSP_NO_DIR, ibuf_reset_free_bits(), btr_cur_struct::index, lock_update_root_raise(), mem_heap_create, mem_heap_free, mtr_memo_contains(), MTR_MEMO_PAGE_X_FIX, MTR_MEMO_X_LOCK, PAGE_CUR_LE, page_cur_search(), page_cur_set_before_first(), page_cur_tuple_insert(), page_get_infimum_rec(), page_is_comp(), page_move_rec_list_end(), page_rec_get_next(), page_t, dict_tree_struct::tree_index, and ut_ad.
Referenced by btr_cur_pessimistic_insert().
00986 : inserted record */ 00987 btr_cur_t* cursor, /* in: cursor at which to insert: must be 00988 on the root page; when the function returns, 00989 the cursor is positioned on the predecessor 00990 of the inserted record */ 00991 dtuple_t* tuple, /* in: tuple to insert */ 00992 mtr_t* mtr) /* in: mtr */ 00993 { 00994 dict_tree_t* tree; 00995 page_t* root; 00996 page_t* new_page; 00997 ulint new_page_no; 00998 rec_t* rec; 00999 mem_heap_t* heap; 01000 dtuple_t* node_ptr; 01001 ulint level; 01002 rec_t* node_ptr_rec; 01003 page_cur_t* page_cursor; 01004 01005 root = btr_cur_get_page(cursor); 01006 tree = btr_cur_get_tree(cursor); 01007 01008 ut_ad(dict_tree_get_page(tree) == buf_frame_get_page_no(root)); 01009 ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), 01010 MTR_MEMO_X_LOCK)); 01011 ut_ad(mtr_memo_contains(mtr, buf_block_align(root), 01012 MTR_MEMO_PAGE_X_FIX)); 01013 btr_search_drop_page_hash_index(root); 01014 01015 /* Allocate a new page to the tree. Root splitting is done by first 01016 moving the root records to the new page, emptying the root, putting 01017 a node pointer to the new page, and then splitting the new page. */ 01018 01019 new_page = btr_page_alloc(tree, 0, FSP_NO_DIR, 01020 btr_page_get_level(root, mtr), mtr); 01021 01022 btr_page_create(new_page, tree, mtr); 01023 01024 level = btr_page_get_level(root, mtr); 01025 01026 /* Set the levels of the new index page and root page */ 01027 btr_page_set_level(new_page, level, mtr); 01028 btr_page_set_level(root, level + 1, mtr); 01029 01030 /* Set the next node and previous node fields of new page */ 01031 btr_page_set_next(new_page, FIL_NULL, mtr); 01032 btr_page_set_prev(new_page, FIL_NULL, mtr); 01033 01034 /* Move the records from root to the new page */ 01035 01036 page_move_rec_list_end(new_page, root, page_get_infimum_rec(root), 01037 cursor->index, mtr); 01038 /* If this is a pessimistic insert which is actually done to 01039 perform a pessimistic update then we have stored the lock 01040 information of the record to be inserted on the infimum of the 01041 root page: we cannot discard the lock structs on the root page */ 01042 01043 lock_update_root_raise(new_page, root); 01044 01045 /* Create a memory heap where the node pointer is stored */ 01046 heap = mem_heap_create(100); 01047 01048 rec = page_rec_get_next(page_get_infimum_rec(new_page)); 01049 new_page_no = buf_frame_get_page_no(new_page); 01050 01051 /* Build the node pointer (= node key and page address) for the 01052 child */ 01053 01054 node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap, 01055 level); 01056 /* Reorganize the root to get free space */ 01057 btr_page_reorganize(root, cursor->index, mtr); 01058 01059 page_cursor = btr_cur_get_page_cur(cursor); 01060 01061 /* Insert node pointer to the root */ 01062 01063 page_cur_set_before_first(root, page_cursor); 01064 01065 node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr, 01066 cursor->index, mtr); 01067 01068 ut_ad(node_ptr_rec); 01069 01070 /* The node pointer must be marked as the predefined minimum record, 01071 as there is no lower alphabetical limit to records in the leftmost 01072 node of a level: */ 01073 01074 btr_set_min_rec_mark(node_ptr_rec, page_is_comp(root), mtr); 01075 01076 /* Free the memory heap */ 01077 mem_heap_free(heap); 01078 01079 /* We play safe and reset the free bits for the new page */ 01080 01081 /* fprintf(stderr, "Root raise new page no %lu\n", 01082 buf_frame_get_page_no(new_page)); */ 01083 01084 ibuf_reset_free_bits(tree->tree_index, new_page); 01085 /* Reposition the cursor to the child node */ 01086 page_cur_search(new_page, cursor->index, tuple, 01087 PAGE_CUR_LE, page_cursor); 01088 01089 /* Split the child and insert tuple */ 01090 return(btr_page_split_and_insert(cursor, tuple, mtr)); 01091 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1896 of file btr0btr.c.
References btr_set_min_rec_mark_log(), rec_get_info_bits(), REC_INFO_MIN_REC_FLAG, and rec_set_info_bits().
Referenced by btr_cur_pessimistic_delete(), btr_discard_page(), btr_parse_set_min_rec_mark(), and btr_root_raise_and_insert().
01898 : record */ 01899 ulint comp, /* in: nonzero=compact page format */ 01900 mtr_t* mtr) /* in: mtr */ 01901 { 01902 ulint info_bits; 01903 01904 info_bits = rec_get_info_bits(rec, comp); 01905 01906 rec_set_info_bits(rec, comp, info_bits | REC_INFO_MIN_REC_FLAG); 01907 01908 btr_set_min_rec_mark_log(rec, comp, mtr); 01909 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1846 of file btr0btr.c.
References MLOG_2BYTES, mlog_catenate_ulint(), MLOG_COMP_REC_MIN_MARK, MLOG_REC_MIN_MARK, mlog_write_initial_log_record(), UNIV_PAGE_SIZE, and ut_align_offset().
Referenced by btr_set_min_rec_mark().
01848 : record */ 01849 ulint comp, /* nonzero=compact record format */ 01850 mtr_t* mtr) /* in: mtr */ 01851 { 01852 mlog_write_initial_log_record(rec, 01853 comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr); 01854 01855 /* Write rec offset as a 2-byte ulint */ 01856 mlog_catenate_ulint(mtr, ut_align_offset(rec, UNIV_PAGE_SIZE), 01857 MLOG_2BYTES); 01858 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool btr_validate_level | ( | dict_tree_t * | tree, | |
| trx_t * | trx, | |||
| ulint | level | |||
| ) | [static] |
Definition at line 2691 of file btr0btr.c.
References btr_index_page_validate(), btr_node_ptr_get_child(), btr_node_ptr_get_child_page_no(), btr_page_get(), btr_page_get_father_for_rec(), btr_page_get_father_node_ptr(), btr_page_get_level(), btr_page_get_next(), btr_page_get_prev(), btr_root_get(), btr_validate_report1(), btr_validate_report2(), buf_frame_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), buf_page_print(), cmp_dtuple_rec(), cmp_rec_rec(), dict_tree_build_node_ptr(), dict_tree_get_lock(), dict_tree_get_page(), FALSE, FIL_NULL, index(), mem_heap_create, mem_heap_empty(), mem_heap_free, mtr_commit(), mtr_start(), mtr_x_lock, NULL, page_cur_get_rec(), page_cur_move_to_next(), page_cur_set_before_first(), page_get_infimum_rec(), page_get_n_recs(), page_get_supremum_rec(), page_is_comp(), page_rec_get_next(), page_rec_get_prev(), page_t, page_validate(), rec_get_info_bits(), rec_get_offsets, REC_INFO_MIN_REC_FLAG, rec_print(), rec_print_new(), RW_X_LATCH, dict_tree_struct::tree_index, TRUE, trx_is_interrupted(), and ut_a.
Referenced by btr_validate_tree().
02693 : TRUE if ok */ 02694 dict_tree_t* tree, /* in: index tree */ 02695 trx_t* trx, /* in: transaction or NULL */ 02696 ulint level) /* in: level number */ 02697 { 02698 ulint space; 02699 page_t* page; 02700 page_t* right_page = 0; /* remove warning */ 02701 page_t* father_page; 02702 page_t* right_father_page; 02703 rec_t* node_ptr; 02704 rec_t* right_node_ptr; 02705 rec_t* rec; 02706 ulint right_page_no; 02707 ulint left_page_no; 02708 page_cur_t cursor; 02709 dtuple_t* node_ptr_tuple; 02710 ibool ret = TRUE; 02711 dict_index_t* index; 02712 mtr_t mtr; 02713 mem_heap_t* heap = mem_heap_create(256); 02714 ulint* offsets = NULL; 02715 ulint* offsets2= NULL; 02716 02717 mtr_start(&mtr); 02718 02719 mtr_x_lock(dict_tree_get_lock(tree), &mtr); 02720 02721 page = btr_root_get(tree, &mtr); 02722 02723 space = buf_frame_get_space_id(page); 02724 02725 index = tree->tree_index; 02726 02727 while (level != btr_page_get_level(page, &mtr)) { 02728 02729 ut_a(btr_page_get_level(page, &mtr) > 0); 02730 02731 page_cur_set_before_first(page, &cursor); 02732 page_cur_move_to_next(&cursor); 02733 02734 node_ptr = page_cur_get_rec(&cursor); 02735 offsets = rec_get_offsets(node_ptr, index, offsets, 02736 ULINT_UNDEFINED, &heap); 02737 page = btr_node_ptr_get_child(node_ptr, offsets, &mtr); 02738 } 02739 02740 /* Now we are on the desired level. Loop through the pages on that 02741 level. */ 02742 loop: 02743 if (trx_is_interrupted(trx)) { 02744 mtr_commit(&mtr); 02745 mem_heap_free(heap); 02746 return(ret); 02747 } 02748 mem_heap_empty(heap); 02749 offsets = offsets2 = NULL; 02750 mtr_x_lock(dict_tree_get_lock(tree), &mtr); 02751 02752 /* Check ordering etc. of records */ 02753 02754 if (!page_validate(page, index)) { 02755 btr_validate_report1(index, level, page); 02756 02757 ret = FALSE; 02758 } else if (level == 0) { 02759 /* We are on level 0. Check that the records have the right 02760 number of fields, and field lengths are right. */ 02761 02762 if (!btr_index_page_validate(page, index)) { 02763 02764 ret = FALSE; 02765 } 02766 } 02767 02768 ut_a(btr_page_get_level(page, &mtr) == level); 02769 02770 right_page_no = btr_page_get_next(page, &mtr); 02771 left_page_no = btr_page_get_prev(page, &mtr); 02772 02773 ut_a((page_get_n_recs(page) > 0) 02774 || ((level == 0) && 02775 (buf_frame_get_page_no(page) == dict_tree_get_page(tree)))); 02776 02777 if (right_page_no != FIL_NULL) { 02778 rec_t* right_rec; 02779 right_page = btr_page_get(space, right_page_no, RW_X_LATCH, 02780 &mtr); 02781 if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr) 02782 != buf_frame_get_page_no(page))) { 02783 btr_validate_report2(index, level, page, right_page); 02784 fputs("InnoDB: broken FIL_PAGE_NEXT" 02785 " or FIL_PAGE_PREV links\n", stderr); 02786 buf_page_print(page); 02787 buf_page_print(right_page); 02788 02789 ret = FALSE; 02790 } 02791 02792 if (UNIV_UNLIKELY(page_is_comp(right_page) 02793 != page_is_comp(page))) { 02794 btr_validate_report2(index, level, page, right_page); 02795 fputs("InnoDB: 'compact' flag mismatch\n", stderr); 02796 buf_page_print(page); 02797 buf_page_print(right_page); 02798 02799 ret = FALSE; 02800 02801 goto node_ptr_fails; 02802 } 02803 02804 rec = page_rec_get_prev(page_get_supremum_rec(page)); 02805 right_rec = page_rec_get_next( 02806 page_get_infimum_rec(right_page)); 02807 offsets = rec_get_offsets(rec, index, 02808 offsets, ULINT_UNDEFINED, &heap); 02809 offsets2 = rec_get_offsets(right_rec, index, 02810 offsets2, ULINT_UNDEFINED, &heap); 02811 if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec, 02812 offsets, offsets2, index) >= 0)) { 02813 02814 btr_validate_report2(index, level, page, right_page); 02815 02816 fputs("InnoDB: records in wrong order" 02817 " on adjacent pages\n", stderr); 02818 02819 buf_page_print(page); 02820 buf_page_print(right_page); 02821 02822 fputs("InnoDB: record ", stderr); 02823 rec = page_rec_get_prev(page_get_supremum_rec(page)); 02824 rec_print(stderr, rec, index); 02825 putc('\n', stderr); 02826 fputs("InnoDB: record ", stderr); 02827 rec = page_rec_get_next(page_get_infimum_rec( 02828 right_page)); 02829 rec_print(stderr, rec, index); 02830 putc('\n', stderr); 02831 02832 ret = FALSE; 02833 } 02834 } 02835 02836 if (level > 0 && left_page_no == FIL_NULL) { 02837 ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits( 02838 page_rec_get_next(page_get_infimum_rec(page)), 02839 page_is_comp(page))); 02840 } 02841 02842 if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) { 02843 02844 /* Check father node pointers */ 02845 02846 node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr); 02847 father_page = buf_frame_align(node_ptr); 02848 offsets = rec_get_offsets(node_ptr, index, 02849 offsets, ULINT_UNDEFINED, &heap); 02850 02851 if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != 02852 buf_frame_get_page_no(page) 02853 || node_ptr != btr_page_get_father_for_rec(tree, page, 02854 page_rec_get_prev(page_get_supremum_rec(page)), 02855 &mtr)) { 02856 btr_validate_report1(index, level, page); 02857 02858 fputs("InnoDB: node pointer to the page is wrong\n", 02859 stderr); 02860 02861 buf_page_print(father_page); 02862 buf_page_print(page); 02863 02864 fputs("InnoDB: node ptr ", stderr); 02865 rec_print_new(stderr, node_ptr, offsets); 02866 02867 fprintf(stderr, "\n" 02868 "InnoDB: node ptr child page n:o %lu\n", 02869 (unsigned long) btr_node_ptr_get_child_page_no( 02870 node_ptr, offsets)); 02871 02872 fputs("InnoDB: record on page ", stderr); 02873 rec = btr_page_get_father_for_rec(tree, page, 02874 page_rec_get_prev(page_get_supremum_rec(page)), 02875 &mtr); 02876 rec_print(stderr, rec, index); 02877 putc('\n', stderr); 02878 ret = FALSE; 02879 02880 goto node_ptr_fails; 02881 } 02882 02883 if (btr_page_get_level(page, &mtr) > 0) { 02884 offsets = rec_get_offsets(node_ptr, index, 02885 offsets, ULINT_UNDEFINED, &heap); 02886 02887 node_ptr_tuple = dict_tree_build_node_ptr( 02888 tree, 02889 page_rec_get_next( 02890 page_get_infimum_rec(page)), 02891 0, heap, 02892 btr_page_get_level(page, &mtr)); 02893 02894 if (cmp_dtuple_rec(node_ptr_tuple, node_ptr, 02895 offsets)) { 02896 rec_t* first_rec = page_rec_get_next( 02897 page_get_infimum_rec(page)); 02898 02899 btr_validate_report1(index, level, page); 02900 02901 buf_page_print(father_page); 02902 buf_page_print(page); 02903 02904 fputs("InnoDB: Error: node ptrs differ" 02905 " on levels > 0\n" 02906 "InnoDB: node ptr ", stderr); 02907 rec_print_new(stderr, node_ptr, offsets); 02908 fputs("InnoDB: first rec ", stderr); 02909 rec_print(stderr, first_rec, index); 02910 putc('\n', stderr); 02911 ret = FALSE; 02912 02913 goto node_ptr_fails; 02914 } 02915 } 02916 02917 if (left_page_no == FIL_NULL) { 02918 ut_a(node_ptr == page_rec_get_next( 02919 page_get_infimum_rec(father_page))); 02920 ut_a(btr_page_get_prev(father_page, &mtr) == FIL_NULL); 02921 } 02922 02923 if (right_page_no == FIL_NULL) { 02924 ut_a(node_ptr == page_rec_get_prev( 02925 page_get_supremum_rec(father_page))); 02926 ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL); 02927 } else { 02928 right_node_ptr = btr_page_get_father_node_ptr(tree, 02929 right_page, &mtr); 02930 if (page_rec_get_next(node_ptr) != 02931 page_get_supremum_rec(father_page)) { 02932 02933 if (right_node_ptr != 02934 page_rec_get_next(node_ptr)) { 02935 ret = FALSE; 02936 fputs( 02937 "InnoDB: node pointer to the right page is wrong\n", 02938 stderr); 02939 02940 btr_validate_report1(index, level, 02941 page); 02942 02943 buf_page_print(father_page); 02944 buf_page_print(page); 02945 buf_page_print(right_page); 02946 } 02947 } else { 02948 right_father_page = buf_frame_align( 02949 right_node_ptr); 02950 02951 if (right_node_ptr != page_rec_get_next( 02952 page_get_infimum_rec( 02953 right_father_page))) { 02954 ret = FALSE; 02955 fputs( 02956 "InnoDB: node pointer 2 to the right page is wrong\n", 02957 stderr); 02958 02959 btr_validate_report1(index, level, 02960 page); 02961 02962 buf_page_print(father_page); 02963 buf_page_print(right_father_page); 02964 buf_page_print(page); 02965 buf_page_print(right_page); 02966 } 02967 02968 if (buf_frame_get_page_no(right_father_page) 02969 != btr_page_get_next(father_page, &mtr)) { 02970 02971 ret = FALSE; 02972 fputs( 02973 "InnoDB: node pointer 3 to the right page is wrong\n", 02974 stderr); 02975 02976 btr_validate_report1(index, level, 02977 page); 02978 02979 buf_page_print(father_page); 02980 buf_page_print(right_father_page); 02981 buf_page_print(page); 02982 buf_page_print(right_page); 02983 } 02984 } 02985 } 02986 } 02987 02988 node_ptr_fails: 02989 /* Commit the mini-transaction to release the latch on 'page'. 02990 Re-acquire the latch on right_page, which will become 'page' 02991 on the next loop. The page has already been checked. */ 02992 mtr_commit(&mtr); 02993 02994 if (right_page_no != FIL_NULL) { 02995 mtr_start(&mtr); 02996 02997 page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); 02998 02999 goto loop; 03000 } 03001 03002 mem_heap_free(heap); 03003 return(ret); 03004 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_validate_report1 | ( | dict_index_t * | index, | |
| ulint | level, | |||
| page_t * | page | |||
| ) | [static] |
Definition at line 2651 of file btr0btr.c.
References buf_frame_get_page_no(), dict_index_name_print(), index(), and NULL.
Referenced by btr_validate_level().
02652 : TRUE if ok */ 02653 dict_index_t* index, /* in: index */ 02654 ulint level, /* in: B-tree level */ 02655 page_t* page) /* in: index page */ 02656 { 02657 fprintf(stderr, "InnoDB: Error in page %lu of ", 02658 buf_frame_get_page_no(page)); 02659 dict_index_name_print(stderr, NULL, index); 02660 if (level) { 02661 fprintf(stderr, ", index tree level %lu", level); 02662 } 02663 putc('\n', stderr); 02664 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void btr_validate_report2 | ( | dict_index_t * | index, | |
| ulint | level, | |||
| page_t * | page1, | |||
| page_t * | page2 | |||
| ) | [static] |
Definition at line 2670 of file btr0btr.c.
References buf_frame_get_page_no(), dict_index_name_print(), index(), and NULL.
Referenced by btr_validate_level().
02671 : TRUE if ok */ 02672 dict_index_t* index, /* in: index */ 02673 ulint level, /* in: B-tree level */ 02674 page_t* page1, /* in: first index page */ 02675 page_t* page2) /* in: second index page */ 02676 { 02677 fprintf(stderr, "InnoDB: Error in pages %lu and %lu of ", 02678 buf_frame_get_page_no(page1), 02679 buf_frame_get_page_no(page2)); 02680 dict_index_name_print(stderr, NULL, index); 02681 if (level) { 02682 fprintf(stderr, ", index tree level %lu", level); 02683 } 02684 putc('\n', stderr); 02685 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool btr_validate_tree | ( | dict_tree_t * | tree, | |
| trx_t * | trx | |||
| ) |
Definition at line 3010 of file btr0btr.c.
References btr_page_get_level(), btr_root_get(), btr_validate_level(), dict_tree_get_lock(), FALSE, mtr_commit(), mtr_start(), mtr_x_lock, n, page_t, TRUE, and trx_is_interrupted().
Referenced by ibuf_delete_rec(), and row_check_table_for_mysql().
03012 : TRUE if ok */ 03013 dict_tree_t* tree, /* in: tree */ 03014 trx_t* trx) /* in: transaction or NULL */ 03015 { 03016 mtr_t mtr; 03017 page_t* root; 03018 ulint i; 03019 ulint n; 03020 03021 mtr_start(&mtr); 03022 mtr_x_lock(dict_tree_get_lock(tree), &mtr); 03023 03024 root = btr_root_get(tree, &mtr); 03025 n = btr_page_get_level(root, &mtr); 03026 03027 for (i = 0; i <= n && !trx_is_interrupted(trx); i++) { 03028 if (!btr_validate_level(tree, trx, n - i)) { 03029 03030 mtr_commit(&mtr); 03031 03032 return(FALSE); 03033 } 03034 } 03035 03036 mtr_commit(&mtr); 03037 03038 return(TRUE); 03039 }
Here is the call graph for this function:

Here is the caller graph for this function:

1.4.7

