From d480d28f4f389d34248e3889cc059238a803008e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 8 Oct 2019 18:18:48 +0300 Subject: Add page_has_prev(), page_has_next(), page_has_siblings() Until now, InnoDB inefficiently compared the aligned fields FIL_PAGE_PREV, FIL_PAGE_NEXT to the byte-order-agnostic value FIL_NULL. This is a backport of 32170f8c6d55c497ae7a791997e17ff7c992b86f from MariaDB Server 10.3. --- storage/innobase/btr/btr0btr.cc | 12 +++++------- storage/innobase/btr/btr0cur.cc | 28 +++++++++++----------------- storage/innobase/btr/btr0defragment.cc | 2 +- storage/innobase/dict/dict0stats.cc | 4 ++-- storage/innobase/gis/gis0rtree.cc | 2 +- storage/innobase/gis/gis0sea.cc | 2 +- storage/innobase/ibuf/ibuf0ibuf.cc | 3 +-- storage/innobase/include/btr0cur.ic | 15 ++++++--------- storage/innobase/include/btr0pcur.ic | 16 ++++------------ storage/innobase/include/page0page.h | 18 ++++++++++++++++++ storage/innobase/page/page0cur.cc | 2 +- storage/innobase/page/page0page.cc | 3 +-- storage/innobase/page/page0zip.cc | 11 ++++------- 13 files changed, 56 insertions(+), 62 deletions(-) (limited to 'storage') diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index f2b7b0d3f73..1bd49fa048e 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1987,7 +1987,7 @@ btr_root_raise_and_insert( they should already have been set. The previous node field must be FIL_NULL if root_page_zip != NULL, because the REC_INFO_MIN_REC_FLAG (of the first user record) will be - set if and only if btr_page_get_prev() == FIL_NULL. */ + set if and only if !page_has_prev(). */ btr_page_set_next(root, root_page_zip, FIL_NULL, mtr); btr_page_set_prev(root, root_page_zip, FIL_NULL, mtr); @@ -3361,8 +3361,7 @@ btr_lift_page_up( bool lift_father_up; buf_block_t* block_orig = block; - ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); - ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); + ut_ad(!page_has_siblings(page)); ut_ad(mtr_is_block_fix(mtr, block, MTR_MEMO_PAGE_X_FIX, index->table)); page_level = btr_page_get_level(page, mtr); @@ -3429,8 +3428,7 @@ btr_lift_page_up( page = buf_block_get_frame(block); page_level = btr_page_get_level(page, mtr); - ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); - ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); + ut_ad(!page_has_siblings(page)); ut_ad(mtr_is_block_fix( mtr, block, MTR_MEMO_PAGE_X_FIX, index->table)); @@ -5077,13 +5075,13 @@ loop: if (left_page_no == FIL_NULL) { ut_a(node_ptr == page_rec_get_next( page_get_infimum_rec(father_page))); - ut_a(btr_page_get_prev(father_page, &mtr) == FIL_NULL); + ut_a(!page_has_prev(father_page)); } if (right_page_no == FIL_NULL) { ut_a(node_ptr == page_rec_get_prev( page_get_supremum_rec(father_page))); - ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL); + ut_a(!page_has_next(father_page)); } else { const rec_t* right_node_ptr; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index b23cacac227..d0d453ed828 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -595,10 +595,10 @@ btr_cur_will_modify_tree( /* is first, 2nd or last record */ if (page_rec_is_first(rec, page) - || (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL + || (page_has_next(page) && (page_rec_is_last(rec, page) || page_rec_is_second_last(rec, page))) - || (mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL + || (page_has_prev(page) && page_rec_is_second(rec, page))) { return(true); } @@ -680,13 +680,10 @@ btr_cur_need_opposite_intention( { switch (lock_intention) { case BTR_INTENTION_DELETE: - return((mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL - && page_rec_is_first(rec, page)) - || (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL - && page_rec_is_last(rec, page))); + return (page_has_prev(page) && page_rec_is_first(rec, page)) || + (page_has_next(page) && page_rec_is_last(rec, page)); case BTR_INTENTION_INSERT: - return(mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL - && page_rec_is_last(rec, page)); + return page_has_next(page) && page_rec_is_last(rec, page); case BTR_INTENTION_BOTH: return(false); } @@ -1898,7 +1895,7 @@ need_opposite_intention: MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX)); - if (btr_page_get_prev(page, mtr) != FIL_NULL + if (page_has_prev(page) && page_rec_is_first(node_ptr, page)) { if (leftmost_from_level == 0) { @@ -2015,7 +2012,7 @@ need_opposite_intention: } else if (!dict_index_is_spatial(index) && latch_mode == BTR_MODIFY_TREE && lock_intention == BTR_INTENTION_INSERT - && mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL + && page_has_next(page) && page_rec_is_last(page_cur_get_rec(page_cursor), page)) { /* btr_insert_into_right_sibling() might cause @@ -5302,7 +5299,7 @@ btr_cur_pessimistic_delete( } else if (UNIV_UNLIKELY(page_rec_is_first(rec, page))) { rec_t* next_rec = page_rec_get_next(rec); - if (btr_page_get_prev(page, mtr) == FIL_NULL) { + if (!page_has_prev(page)) { /* If we delete the leftmost node pointer on a non-leaf level, we must mark the new leftmost node @@ -6325,7 +6322,8 @@ btr_estimate_number_of_different_key_vals( } } - if (n_cols == dict_index_get_n_unique_in_tree(index)) { + if (n_cols == dict_index_get_n_unique_in_tree(index) + && page_has_siblings(page)) { /* If there is more than one leaf page in the tree, we add one because we know that the first record @@ -6336,11 +6334,7 @@ btr_estimate_number_of_different_key_vals( algorithm grossly underestimated the number of rows in the table. */ - if (btr_page_get_prev(page, &mtr) != FIL_NULL - || btr_page_get_next(page, &mtr) != FIL_NULL) { - - n_diff[n_cols - 1]++; - } + n_diff[n_cols - 1]++; } mtr_commit(&mtr); diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 6995c6f0998..bcabfd3a3bf 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -602,7 +602,7 @@ btr_defragment_n_pages( } if (n_pages == 1) { - if (btr_page_get_prev(first_page, mtr) == FIL_NULL) { + if (!page_has_prev(first_page)) { /* last page in the index */ if (dict_index_get_page(index) == page_get_page_no(first_page)) diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 4db4687e600..f49fb87e4ea 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1076,7 +1076,7 @@ dict_stats_analyze_index_level( ut_a(btr_page_get_level(page, mtr) == level); /* there should not be any pages on the left */ - ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); + ut_a(!page_has_prev(page)); /* check whether the first record on the leftmost page is marked as such, if we are on a non-leaf level */ @@ -1689,7 +1689,7 @@ dict_stats_analyze_index_for_n_prefix( ut_a(btr_page_get_level(page, mtr) == n_diff_data->level); /* there should not be any pages on the left */ - ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); + ut_a(!page_has_prev(page)); /* check whether the first record on the leftmost page is marked as such; we are on a non-leaf level */ diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 2965a19a5e0..dc9e34903c2 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1063,7 +1063,7 @@ func_start: page_no = block->page.id.page_no(); - if (btr_page_get_prev(page, mtr) == FIL_NULL && !page_is_leaf(page)) { + if (!page_has_prev(page) && !page_is_leaf(page)) { first_rec = page_rec_get_next( page_get_infimum_rec(buf_block_get_frame(block))); } diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index f1e4b82fd36..0a0a542689a 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1713,7 +1713,7 @@ rtr_cur_search_with_match( first page as much as possible, as there will be problem when update MIN_REC rec in compress table */ if (buf_block_get_page_zip(block) - && mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL + && !page_has_prev(page) && page_get_n_recs(page) >= 2) { rec = page_rec_get_next_const(rec); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 5581d1d1093..34cba10c6b5 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -3254,8 +3254,7 @@ ibuf_get_entry_counter_func( return(ULINT_UNDEFINED); } else if (!page_rec_is_infimum(rec)) { return(ibuf_get_entry_counter_low(mtr, rec, space, page_no)); - } else if (only_leaf - || fil_page_get_prev(page_align(rec)) == FIL_NULL) { + } else if (only_leaf || !page_has_prev(page_align(rec))) { /* The parent node pointer did not contain the searched for (space, page_no), which means that the search ended on the correct page regardless of the diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index 1decfa09e5b..7cf6c5982fa 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -138,10 +138,9 @@ btr_cur_compress_recommendation( LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2U, return(FALSE)); - if ((page_get_data_size(page) - < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) - || ((btr_page_get_next(page, mtr) == FIL_NULL) - && (btr_page_get_prev(page, mtr) == FIL_NULL))) { + if (page_get_data_size(page) + < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) + || !page_has_siblings(page)) { /* The page fillfactor has dropped below a predefined minimum value OR the level in the B-tree contains just @@ -174,11 +173,9 @@ btr_cur_can_delete_without_compress( page = btr_cur_get_page(cursor); - if ((page_get_data_size(page) - rec_size - < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) - || ((btr_page_get_next(page, mtr) == FIL_NULL) - && (btr_page_get_prev(page, mtr) == FIL_NULL)) - || (page_get_n_recs(page) < 2)) { + if (page_get_data_size(page) - rec_size + < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index) + || !page_has_siblings(page) || page_get_n_recs(page) < 2) { /* The page fillfactor will drop below a predefined minimum value, OR the level in the B-tree contains just diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 51ebcfbb2ee..8b0da666250 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -219,12 +219,8 @@ btr_pcur_is_before_first_in_tree( ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { - - return(FALSE); - } - - return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor))); + return !page_has_prev(btr_pcur_get_page(cursor)) + && page_cur_is_before_first(btr_pcur_get_page_cur(cursor)); } /*********************************************************//** @@ -240,12 +236,8 @@ btr_pcur_is_after_last_in_tree( ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) { - - return(FALSE); - } - - return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor))); + return !page_has_next(btr_pcur_get_page(cursor)) + && page_cur_is_after_last(btr_pcur_get_page_cur(cursor)); } /*********************************************************//** diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index ee261b55d16..c50e72a6542 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -697,6 +697,24 @@ inline bool page_has_siblings(const page_t* page) != ~uint64_t(0); } +/** Determine whether a page has a predecessor. +@param[in] page page frame +@return true if the page has a predecessor */ +inline bool page_has_prev(const page_t* page) +{ + return *reinterpret_cast(page + FIL_PAGE_PREV) + != FIL_NULL; +} + +/** Determine whether a page has a successor. +@param[in] page page frame +@return true if the page has a successor */ +inline bool page_has_next(const page_t* page) +{ + return *reinterpret_cast(page + FIL_PAGE_NEXT) + != FIL_NULL; +} + /************************************************************//** Gets the pointer to the next record on the page. @return pointer to next record */ diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 92ff3e104ba..4071db7b4d9 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -521,7 +521,7 @@ up_rec_match: ulint rec_info = rec_get_info_bits(mid_rec, rec_offs_comp(offsets)); ut_ad(rec_info & REC_INFO_MIN_REC_FLAG); - ut_ad(btr_page_get_prev(page, &mtr) == FIL_NULL); + ut_ad(!page_has_prev(page)); mtr_commit(&mtr); #endif diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 12a0f44011d..f950af02e31 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2764,8 +2764,7 @@ page_delete_rec( if (!rec_offs_any_extern(offsets) && ((page_get_data_size(page) - rec_offs_size(offsets) < BTR_CUR_PAGE_COMPRESS_LIMIT(index)) - || (mach_read_from_4(page + FIL_PAGE_NEXT) == FIL_NULL - && mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL) + || !page_has_siblings(page) || (page_get_n_recs(page) < 2))) { ulint root_page_no = dict_index_get_page(index); diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index e90c5f67f8e..9e3e58efa3a 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -670,8 +670,7 @@ page_zip_dir_encode( status = REC_STATUS_ORDINARY; } else { status = REC_STATUS_NODE_PTR; - if (UNIV_UNLIKELY - (mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL)) { + if (UNIV_UNLIKELY(!page_has_prev(page))) { min_mark = REC_INFO_MIN_REC_FLAG; } } @@ -3187,8 +3186,7 @@ zlib_error: goto err_exit; } - info_bits = mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL - ? REC_INFO_MIN_REC_FLAG : 0; + info_bits = page_has_prev(page) ? 0 : REC_INFO_MIN_REC_FLAG; if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip, page, info_bits))) { @@ -4826,9 +4824,8 @@ page_zip_copy_recs( + page_zip->m_end < page_zip_get_size(page_zip)); if (!page_is_leaf(src) - && UNIV_UNLIKELY(mach_read_from_4(src + FIL_PAGE_PREV) == FIL_NULL) - && UNIV_LIKELY(mach_read_from_4(page - + FIL_PAGE_PREV) != FIL_NULL)) { + && UNIV_UNLIKELY(!page_has_prev(src)) + && UNIV_LIKELY(page_has_prev(page))) { /* Clear the REC_INFO_MIN_REC_FLAG of the first user record. */ ulint offs = rec_get_next_offs(page + PAGE_NEW_INFIMUM, TRUE); -- cgit v1.2.1