diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-09-18 10:53:31 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-09-18 10:53:31 +0300 |
commit | 71e856e152c303d1beaea240a85a00fa0d447de0 (patch) | |
tree | c3b538ba33d8448a759fa65e1b715e67a6ef9dfc | |
parent | 2eeac537151058d0a695026766389ef1f867dc79 (diff) | |
download | mariadb-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.h | 40 | ||||
-rw-r--r-- | storage/innobase/include/page0page.ic | 46 | ||||
-rw-r--r-- | storage/innobase/page/page0cur.cc | 148 | ||||
-rw-r--r-- | storage/innobase/page/page0page.cc | 206 |
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(). |