summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-09-18 10:53:31 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-09-18 10:53:31 +0300
commit71e856e152c303d1beaea240a85a00fa0d447de0 (patch)
treec3b538ba33d8448a759fa65e1b715e67a6ef9dfc
parent2eeac537151058d0a695026766389ef1f867dc79 (diff)
downloadmariadb-git-71e856e152c303d1beaea240a85a00fa0d447de0.tar.gz
MDEV-12353 preparation: Clean up page directory operations
page_mem_free(): Define in the same file with the only caller page_cur_delete_rec(). page_dir_slot_set_rec(): Add const qualifier to a parameter. page_dir_delete_slot(): Merge with the only caller page_dir_balance_slot(). page_dir_add_slot(): Merge with the only caller page_dir_split_slot(). page_dir_split_slot(), page_dir_balance_slot(): Define in the same compilation unit with the callers, and simplify the code.
-rw-r--r--storage/innobase/include/page0page.h40
-rw-r--r--storage/innobase/include/page0page.ic46
-rw-r--r--storage/innobase/page/page0cur.cc148
-rw-r--r--storage/innobase/page/page0page.cc206
4 files changed, 147 insertions, 293 deletions
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index cce4a92ae8b..2e022cddc03 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -679,8 +679,8 @@ UNIV_INLINE
void
page_dir_slot_set_rec(
/*==================*/
- page_dir_slot_t* slot, /*!< in: directory slot */
- rec_t* rec); /*!< in: record on the page */
+ page_dir_slot_t*slot, /*!< in: directory slot */
+ const rec_t* rec); /*!< in: record on the page */
/***************************************************************//**
Gets the number of records owned by a directory slot.
@return number of records */
@@ -957,20 +957,6 @@ page_mem_alloc_heap(
ulint* heap_no);/*!< out: this contains the heap number
of the allocated record
if allocation succeeds */
-/************************************************************//**
-Puts a record to free list. */
-UNIV_INLINE
-void
-page_mem_free(
-/*==========*/
- page_t* page, /*!< in/out: index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page,
- or NULL */
- rec_t* rec, /*!< in: pointer to the (origin of)
- record */
- const dict_index_t* index, /*!< in: index of rec */
- const ulint* offsets);/*!< in: array returned by
- rec_get_offsets() */
/** Read the PAGE_DIRECTION field from a byte.
@param[in] ptr pointer to PAGE_DIRECTION_B
@@ -1164,28 +1150,6 @@ page_move_rec_list_start(
dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull(1, 2, 4, 5)));
-/****************************************************************//**
-Splits a directory slot which owns too many records. */
-void
-page_dir_split_slot(
-/*================*/
- page_t* page, /*!< in: index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose
- uncompressed part will be written, or NULL */
- ulint slot_no)/*!< in: the directory slot */
- MY_ATTRIBUTE((nonnull(1)));
-/*************************************************************//**
-Tries to balance the given directory slot with too few records
-with the upper neighbor, so that there are at least the minimum number
-of records owned by the slot; this may result in the merging of
-two slots. */
-void
-page_dir_balance_slot(
-/*==================*/
- page_t* page, /*!< in/out: index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
- ulint slot_no)/*!< in: the directory slot */
- MY_ATTRIBUTE((nonnull(1)));
/**********************************************************//**
Parses a log record of a record list end or start deletion.
@return end of log record or NULL */
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index 5ab50b7bb8e..2359e61aad0 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -559,8 +559,8 @@ UNIV_INLINE
void
page_dir_slot_set_rec(
/*==================*/
- page_dir_slot_t* slot, /*!< in: directory slot */
- rec_t* rec) /*!< in: record on the page */
+ page_dir_slot_t*slot, /*!< in: directory slot */
+ const rec_t* rec) /*!< in: record on the page */
{
ut_ad(page_rec_check(rec));
@@ -1001,48 +1001,6 @@ page_get_max_insert_size_after_reorganize(
return(free_space - occupied);
}
-/************************************************************//**
-Puts a record to free list. */
-UNIV_INLINE
-void
-page_mem_free(
-/*==========*/
- page_t* page, /*!< in/out: index page */
- page_zip_des_t* page_zip, /*!< in/out: compressed page,
- or NULL */
- rec_t* rec, /*!< in: pointer to the
- (origin of) record */
- const dict_index_t* index, /*!< in: index of rec */
- const ulint* offsets) /*!< in: array returned by
- rec_get_offsets() */
-{
- rec_t* free;
- ulint garbage;
-
- ut_ad(rec_offs_validate(rec, index, offsets));
- free = page_header_get_ptr(page, PAGE_FREE);
-
- if (srv_immediate_scrub_data_uncompressed) {
- /* scrub record */
- memset(rec, 0, rec_offs_data_size(offsets));
- }
-
- page_rec_set_next(rec, free);
- page_header_set_ptr(page, page_zip, PAGE_FREE, rec);
-
- garbage = page_header_get_field(page, PAGE_GARBAGE);
-
- page_header_set_field(page, page_zip, PAGE_GARBAGE,
- garbage + rec_offs_size(offsets));
-
- if (page_zip) {
- page_zip_dir_delete(page_zip, rec, index, offsets, free);
- } else {
- page_header_set_field(page, page_zip, PAGE_N_RECS,
- ulint(page_get_n_recs(page)) - 1);
- }
-}
-
/** Read the PAGE_DIRECTION field from a byte.
@param[in] ptr pointer to PAGE_DIRECTION_B
@return the value of the PAGE_DIRECTION field */
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index 4fdfafa5d0a..efd9618fad5 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -1243,6 +1243,118 @@ page_direction_increment(
1U + page_header_get_field(page, PAGE_N_DIRECTION));
}
+/** Split a directory slot which owns too many records.
+@param[in,out] page index page
+@param[in,out] page_zip ROW_FORMAT=COMPRESSED page, or NULL
+@param[in] s the slot that needs to be split */
+static void page_dir_split_slot(page_t* page, page_zip_des_t* page_zip,
+ ulint s)
+{
+ ut_ad(!page_zip || page_is_comp(page));
+ ut_ad(s);
+
+ page_dir_slot_t* slot = page_dir_get_nth_slot(page, s);
+ const ulint n_owned = PAGE_DIR_SLOT_MAX_N_OWNED + 1;
+
+ ut_ad(page_dir_slot_get_n_owned(slot) == n_owned);
+ compile_time_assert((PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2
+ >= PAGE_DIR_SLOT_MIN_N_OWNED);
+
+ /* 1. We loop to find a record approximately in the middle of the
+ records owned by the slot. */
+
+ const rec_t* rec = page_dir_slot_get_rec(slot + PAGE_DIR_SLOT_SIZE);
+
+ for (ulint i = n_owned / 2; i--; ) {
+ rec = page_rec_get_next_const(rec);
+ }
+
+ /* 2. Add a directory slot immediately below this one. */
+ const ulint n_slots = page_dir_get_n_slots(page);
+ page_dir_set_n_slots(page, page_zip, n_slots + 1);
+ page_dir_slot_t* last_slot = page_dir_get_nth_slot(page, n_slots);
+ memmove(last_slot, last_slot + PAGE_DIR_SLOT_SIZE, slot - last_slot);
+
+ /* 3. We store the appropriate values to the new slot. */
+
+ page_dir_slot_set_rec(slot, rec);
+ page_dir_slot_set_n_owned(slot, page_zip, n_owned / 2);
+
+ /* 4. Finally, we update the number of records field of the
+ original slot */
+
+ page_dir_slot_set_n_owned(slot - PAGE_DIR_SLOT_SIZE,
+ page_zip, n_owned - (n_owned / 2));
+}
+
+/** Try to balance an underfilled directory slot with an adjacent one,
+so that there are at least the minimum number of records owned by the slot;
+this may result in merging the two slots.
+@param[in,out] page index page
+@param[in,out] page_zip ROW_FORMAT=COMPRESSED page, or NULL
+@param[in] s the slot to be balanced */
+static void page_dir_balance_slot(page_t* page, page_zip_des_t* page_zip,
+ ulint s)
+{
+ ut_ad(!page_zip || page_is_comp(page));
+ ut_ad(s > 0);
+
+ const ulint n_slots = page_dir_get_n_slots(page);
+
+ if (UNIV_UNLIKELY(s + 1 == n_slots)) {
+ /* The last directory slot cannot be balanced. */
+ return;
+ }
+
+ ut_ad(s < n_slots);
+
+ page_dir_slot_t* slot = page_dir_get_nth_slot(page, s);
+ page_dir_slot_t* up_slot = slot - PAGE_DIR_SLOT_SIZE;
+ const ulint up_n_owned = page_dir_slot_get_n_owned(up_slot);
+
+ ut_ad(page_dir_slot_get_n_owned(slot)
+ == PAGE_DIR_SLOT_MIN_N_OWNED - 1);
+
+ if (up_n_owned <= PAGE_DIR_SLOT_MIN_N_OWNED) {
+ compile_time_assert(2 * PAGE_DIR_SLOT_MIN_N_OWNED - 1
+ <= PAGE_DIR_SLOT_MAX_N_OWNED);
+ /* Merge the slots. */
+ ulint n_owned = page_dir_slot_get_n_owned(slot);
+ page_dir_slot_set_n_owned(slot, page_zip, 0);
+ page_dir_slot_set_n_owned(up_slot, page_zip,
+ n_owned
+ + page_dir_slot_get_n_owned(up_slot));
+ /* Shift the slots */
+ page_dir_slot_t* last_slot = page_dir_get_nth_slot(
+ page, n_slots - 1);
+ memmove(last_slot + PAGE_DIR_SLOT_SIZE, last_slot,
+ slot - last_slot);
+ mach_write_to_2(last_slot, 0);
+ page_dir_set_n_slots(page, page_zip, n_slots - 1);
+ return;
+ }
+
+ /* Transfer one record to the underfilled slot */
+ rec_t* old_rec = const_cast<rec_t*>(page_dir_slot_get_rec(slot));
+ rec_t* new_rec;
+
+ if (page_is_comp(page)) {
+ new_rec = rec_get_next_ptr(old_rec, TRUE);
+
+ rec_set_n_owned_new(old_rec, page_zip, 0);
+ rec_set_n_owned_new(new_rec, page_zip,
+ PAGE_DIR_SLOT_MIN_N_OWNED);
+ } else {
+ new_rec = rec_get_next_ptr(old_rec, FALSE);
+
+ rec_set_n_owned_old(old_rec, 0);
+ rec_set_n_owned_old(new_rec, PAGE_DIR_SLOT_MIN_N_OWNED);
+ }
+
+ page_dir_slot_set_rec(slot, new_rec);
+ page_dir_slot_set_n_owned(up_slot, page_zip, up_n_owned - 1);
+}
+
/***********************************************************//**
Inserts a record next to page cursor on an uncompressed page.
Returns pointer to inserted record if succeed, i.e., enough
@@ -2280,6 +2392,36 @@ page_cur_parse_delete_rec(
return(ptr);
}
+/** Prepend a record to the PAGE_FREE list.
+@param[in,out] page index page
+@param[in,out] page_zip ROW_FORMAT=COMPRESSED page, or NULL
+@param[in,out] rec record being deleted
+@param[in] index the index that the page belongs to
+@param[in] offsets rec_get_offsets(rec, index) */
+static void page_mem_free(page_t* page, page_zip_des_t* page_zip, rec_t* rec,
+ const dict_index_t* index, const ulint* offsets)
+{
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ const rec_t* free = page_header_get_ptr(page, PAGE_FREE);
+
+ if (srv_immediate_scrub_data_uncompressed) {
+ /* scrub record */
+ memset(rec, 0, rec_offs_data_size(offsets));
+ }
+
+ page_rec_set_next(rec, free);
+ page_header_set_ptr(page, page_zip, PAGE_FREE, rec);
+ page_header_set_field(page, page_zip, PAGE_GARBAGE,
+ rec_offs_size(offsets)
+ + page_header_get_field(page, PAGE_GARBAGE));
+ if (page_zip) {
+ page_zip_dir_delete(page_zip, rec, index, offsets, free);
+ } else {
+ page_header_set_field(page, page_zip, PAGE_N_RECS,
+ ulint(page_get_n_recs(page)) - 1);
+ }
+}
+
/***********************************************************//**
Deletes a record at the page cursor. The cursor is moved to the next
record after the deleted one. */
@@ -2351,11 +2493,6 @@ page_cur_delete_rec(
cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
- /* 0. Write the log record */
- if (mtr != 0) {
- page_cur_delete_rec_write_log(current_rec, index, mtr);
- }
-
/* 1. Reset the last insert info in the page header and increment
the modify clock for the frame */
@@ -2368,6 +2505,7 @@ page_cur_delete_rec(
if (mtr != 0) {
buf_block_modify_clock_inc(page_cur_get_block(cursor));
+ page_cur_delete_rec_write_log(current_rec, index, mtr);
}
/* 2. Find the next and the previous record. Note that the cursor is
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index c4c5d1727ee..15ce614391c 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -1386,212 +1386,6 @@ page_move_rec_list_start(
return(TRUE);
}
-/**************************************************************//**
-Used to delete n slots from the directory. This function updates
-also n_owned fields in the records, so that the first slot after
-the deleted ones inherits the records of the deleted slots. */
-UNIV_INLINE
-void
-page_dir_delete_slot(
-/*=================*/
- page_t* page, /*!< in/out: the index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
- ulint slot_no)/*!< in: slot to be deleted */
-{
- page_dir_slot_t* slot;
- ulint n_owned;
- ulint i;
- ulint n_slots;
-
- ut_ad(!page_zip || page_is_comp(page));
- ut_ad(slot_no > 0);
- ut_ad(slot_no + 1 < page_dir_get_n_slots(page));
-
- n_slots = page_dir_get_n_slots(page);
-
- /* 1. Reset the n_owned fields of the slots to be
- deleted */
- slot = page_dir_get_nth_slot(page, slot_no);
- n_owned = page_dir_slot_get_n_owned(slot);
- page_dir_slot_set_n_owned(slot, page_zip, 0);
-
- /* 2. Update the n_owned value of the first non-deleted slot */
-
- slot = page_dir_get_nth_slot(page, slot_no + 1);
- page_dir_slot_set_n_owned(slot, page_zip,
- n_owned + page_dir_slot_get_n_owned(slot));
-
- /* 3. Destroy the slot by copying slots */
- for (i = slot_no + 1; i < n_slots; i++) {
- rec_t* rec = (rec_t*)
- page_dir_slot_get_rec(page_dir_get_nth_slot(page, i));
- page_dir_slot_set_rec(page_dir_get_nth_slot(page, i - 1), rec);
- }
-
- /* 4. Zero out the last slot, which will be removed */
- mach_write_to_2(page_dir_get_nth_slot(page, n_slots - 1), 0);
-
- /* 5. Update the page header */
- page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots - 1);
-}
-
-/**************************************************************//**
-Used to add n slots to the directory. Does not set the record pointers
-in the added slots or update n_owned values: this is the responsibility
-of the caller. */
-UNIV_INLINE
-void
-page_dir_add_slot(
-/*==============*/
- page_t* page, /*!< in/out: the index page */
- page_zip_des_t* page_zip,/*!< in/out: comprssed page, or NULL */
- ulint start) /*!< in: the slot above which the new slots
- are added */
-{
- page_dir_slot_t* slot;
- ulint n_slots;
-
- n_slots = page_dir_get_n_slots(page);
-
- ut_ad(start < n_slots - 1);
-
- /* Update the page header */
- page_dir_set_n_slots(page, page_zip, n_slots + 1);
-
- /* Move slots up */
- slot = page_dir_get_nth_slot(page, n_slots);
- memmove(slot, slot + PAGE_DIR_SLOT_SIZE,
- (n_slots - 1 - start) * PAGE_DIR_SLOT_SIZE);
-}
-
-/****************************************************************//**
-Splits a directory slot which owns too many records. */
-void
-page_dir_split_slot(
-/*================*/
- page_t* page, /*!< in/out: index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page whose
- uncompressed part will be written, or NULL */
- ulint slot_no)/*!< in: the directory slot */
-{
- rec_t* rec;
- page_dir_slot_t* new_slot;
- page_dir_slot_t* prev_slot;
- page_dir_slot_t* slot;
- ulint i;
- ulint n_owned;
-
- ut_ad(!page_zip || page_is_comp(page));
- ut_ad(slot_no > 0);
-
- slot = page_dir_get_nth_slot(page, slot_no);
-
- n_owned = page_dir_slot_get_n_owned(slot);
- ut_ad(n_owned == PAGE_DIR_SLOT_MAX_N_OWNED + 1);
-
- /* 1. We loop to find a record approximately in the middle of the
- records owned by the slot. */
-
- prev_slot = page_dir_get_nth_slot(page, slot_no - 1);
- rec = (rec_t*) page_dir_slot_get_rec(prev_slot);
-
- for (i = 0; i < n_owned / 2; i++) {
- rec = page_rec_get_next(rec);
- }
-
- ut_ad(n_owned / 2 >= PAGE_DIR_SLOT_MIN_N_OWNED);
-
- /* 2. We add one directory slot immediately below the slot to be
- split. */
-
- page_dir_add_slot(page, page_zip, slot_no - 1);
-
- /* The added slot is now number slot_no, and the old slot is
- now number slot_no + 1 */
-
- new_slot = page_dir_get_nth_slot(page, slot_no);
- slot = page_dir_get_nth_slot(page, slot_no + 1);
-
- /* 3. We store the appropriate values to the new slot. */
-
- page_dir_slot_set_rec(new_slot, rec);
- page_dir_slot_set_n_owned(new_slot, page_zip, n_owned / 2);
-
- /* 4. Finally, we update the number of records field of the
- original slot */
-
- page_dir_slot_set_n_owned(slot, page_zip, n_owned - (n_owned / 2));
-}
-
-/*************************************************************//**
-Tries to balance the given directory slot with too few records with the upper
-neighbor, so that there are at least the minimum number of records owned by
-the slot; this may result in the merging of two slots. */
-void
-page_dir_balance_slot(
-/*==================*/
- page_t* page, /*!< in/out: index page */
- page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
- ulint slot_no)/*!< in: the directory slot */
-{
- page_dir_slot_t* slot;
- page_dir_slot_t* up_slot;
- ulint n_owned;
- ulint up_n_owned;
- rec_t* old_rec;
- rec_t* new_rec;
-
- ut_ad(!page_zip || page_is_comp(page));
- ut_ad(slot_no > 0);
-
- slot = page_dir_get_nth_slot(page, slot_no);
-
- /* The last directory slot cannot be balanced with the upper
- neighbor, as there is none. */
-
- if (UNIV_UNLIKELY(slot_no + 1 == page_dir_get_n_slots(page))) {
-
- return;
- }
-
- up_slot = page_dir_get_nth_slot(page, slot_no + 1);
-
- n_owned = page_dir_slot_get_n_owned(slot);
- up_n_owned = page_dir_slot_get_n_owned(up_slot);
-
- ut_ad(n_owned == PAGE_DIR_SLOT_MIN_N_OWNED - 1);
-
- /* If the upper slot has the minimum value of n_owned, we will merge
- the two slots, therefore we assert: */
- ut_ad(2 * PAGE_DIR_SLOT_MIN_N_OWNED - 1 <= PAGE_DIR_SLOT_MAX_N_OWNED);
-
- if (up_n_owned > PAGE_DIR_SLOT_MIN_N_OWNED) {
-
- /* In this case we can just transfer one record owned
- by the upper slot to the property of the lower slot */
- old_rec = (rec_t*) page_dir_slot_get_rec(slot);
-
- if (page_is_comp(page)) {
- new_rec = rec_get_next_ptr(old_rec, TRUE);
-
- rec_set_n_owned_new(old_rec, page_zip, 0);
- rec_set_n_owned_new(new_rec, page_zip, n_owned + 1);
- } else {
- new_rec = rec_get_next_ptr(old_rec, FALSE);
-
- rec_set_n_owned_old(old_rec, 0);
- rec_set_n_owned_old(new_rec, n_owned + 1);
- }
-
- page_dir_slot_set_rec(slot, new_rec);
-
- page_dir_slot_set_n_owned(up_slot, page_zip, up_n_owned -1);
- } else {
- /* In this case we may merge the two slots */
- page_dir_delete_slot(page, page_zip, slot_no);
- }
-}
-
/************************************************************//**
Returns the nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before().