summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-10-08 18:18:48 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-10-09 08:29:26 +0300
commitd480d28f4f389d34248e3889cc059238a803008e (patch)
treef78a5cca016785e3d2446ac20ebdfc92970348da /storage
parent27664ef29d97be2973982aedcc0c8c90d18b20a4 (diff)
downloadmariadb-git-d480d28f4f389d34248e3889cc059238a803008e.tar.gz
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.
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0btr.cc12
-rw-r--r--storage/innobase/btr/btr0cur.cc28
-rw-r--r--storage/innobase/btr/btr0defragment.cc2
-rw-r--r--storage/innobase/dict/dict0stats.cc4
-rw-r--r--storage/innobase/gis/gis0rtree.cc2
-rw-r--r--storage/innobase/gis/gis0sea.cc2
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc3
-rw-r--r--storage/innobase/include/btr0cur.ic15
-rw-r--r--storage/innobase/include/btr0pcur.ic16
-rw-r--r--storage/innobase/include/page0page.h18
-rw-r--r--storage/innobase/page/page0cur.cc2
-rw-r--r--storage/innobase/page/page0page.cc3
-rw-r--r--storage/innobase/page/page0zip.cc11
13 files changed, 56 insertions, 62 deletions
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<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 */
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);