Skip to content

Commit

Permalink
Add page_has_prev(), page_has_next(), page_has_siblings()
Browse files Browse the repository at this point in the history
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 32170f8
from MariaDB Server 10.3.
  • Loading branch information
dr-m committed Oct 9, 2019
1 parent 27664ef commit d480d28
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 62 deletions.
12 changes: 5 additions & 7 deletions storage/innobase/btr/btr0btr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -5077,13 +5075,13 @@ btr_validate_level(
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;

Expand Down
28 changes: 11 additions & 17 deletions storage/innobase/btr/btr0cur.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1898,7 +1895,7 @@ btr_cur_search_to_nth_level(
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) {
Expand Down Expand Up @@ -2015,7 +2012,7 @@ btr_cur_search_to_nth_level(
} 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/btr/btr0defragment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions storage/innobase/dict/dict0stats.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/gis/gis0rtree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ rtr_page_split_and_insert(

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)));
}
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/gis/gis0sea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions storage/innobase/ibuf/ibuf0ibuf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 6 additions & 9 deletions storage/innobase/include/btr0cur.ic
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 4 additions & 12 deletions storage/innobase/include/btr0pcur.ic
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/*********************************************************//**
Expand All @@ -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));
}

/*********************************************************//**
Expand Down
18 changes: 18 additions & 0 deletions storage/innobase/include/page0page.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const uint32_t*>(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<const uint32_t*>(page + FIL_PAGE_NEXT)
!= FIL_NULL;
}

/************************************************************//**
Gets the pointer to the next record on the page.
@return pointer to next record */
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/page/page0cur.cc
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ page_cur_search_with_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

Expand Down
3 changes: 1 addition & 2 deletions storage/innobase/page/page0page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 4 additions & 7 deletions storage/innobase/page/page0zip.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -3187,8 +3186,7 @@ page_zip_decompress_low(
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))) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit d480d28

Please sign in to comment.