mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
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.
This commit is contained in:
parent
2eeac53715
commit
71e856e152
4 changed files with 147 additions and 293 deletions
|
@ -680,7 +680,7 @@ void
|
||||||
page_dir_slot_set_rec(
|
page_dir_slot_set_rec(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
page_dir_slot_t*slot, /*!< in: directory slot */
|
page_dir_slot_t*slot, /*!< in: directory slot */
|
||||||
rec_t* rec); /*!< in: record on the page */
|
const rec_t* rec); /*!< in: record on the page */
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
Gets the number of records owned by a directory slot.
|
Gets the number of records owned by a directory slot.
|
||||||
@return number of records */
|
@return number of records */
|
||||||
|
@ -957,20 +957,6 @@ page_mem_alloc_heap(
|
||||||
ulint* heap_no);/*!< out: this contains the heap number
|
ulint* heap_no);/*!< out: this contains the heap number
|
||||||
of the allocated record
|
of the allocated record
|
||||||
if allocation succeeds */
|
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.
|
/** Read the PAGE_DIRECTION field from a byte.
|
||||||
@param[in] ptr pointer to PAGE_DIRECTION_B
|
@param[in] ptr pointer to PAGE_DIRECTION_B
|
||||||
|
@ -1164,28 +1150,6 @@ page_move_rec_list_start(
|
||||||
dict_index_t* index, /*!< in: record descriptor */
|
dict_index_t* index, /*!< in: record descriptor */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in: mtr */
|
||||||
MY_ATTRIBUTE((nonnull(1, 2, 4, 5)));
|
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.
|
Parses a log record of a record list end or start deletion.
|
||||||
@return end of log record or NULL */
|
@return end of log record or NULL */
|
||||||
|
|
|
@ -560,7 +560,7 @@ void
|
||||||
page_dir_slot_set_rec(
|
page_dir_slot_set_rec(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
page_dir_slot_t*slot, /*!< in: directory slot */
|
page_dir_slot_t*slot, /*!< in: directory slot */
|
||||||
rec_t* rec) /*!< in: record on the page */
|
const rec_t* rec) /*!< in: record on the page */
|
||||||
{
|
{
|
||||||
ut_ad(page_rec_check(rec));
|
ut_ad(page_rec_check(rec));
|
||||||
|
|
||||||
|
@ -1001,48 +1001,6 @@ page_get_max_insert_size_after_reorganize(
|
||||||
return(free_space - occupied);
|
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.
|
/** Read the PAGE_DIRECTION field from a byte.
|
||||||
@param[in] ptr pointer to PAGE_DIRECTION_B
|
@param[in] ptr pointer to PAGE_DIRECTION_B
|
||||||
@return the value of the PAGE_DIRECTION field */
|
@return the value of the PAGE_DIRECTION field */
|
||||||
|
|
|
@ -1243,6 +1243,118 @@ page_direction_increment(
|
||||||
1U + page_header_get_field(page, PAGE_N_DIRECTION));
|
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.
|
Inserts a record next to page cursor on an uncompressed page.
|
||||||
Returns pointer to inserted record if succeed, i.e., enough
|
Returns pointer to inserted record if succeed, i.e., enough
|
||||||
|
@ -2280,6 +2392,36 @@ page_cur_parse_delete_rec(
|
||||||
return(ptr);
|
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
|
Deletes a record at the page cursor. The cursor is moved to the next
|
||||||
record after the deleted one. */
|
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_dir_slot = page_dir_get_nth_slot(page, cur_slot_no);
|
||||||
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
|
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
|
/* 1. Reset the last insert info in the page header and increment
|
||||||
the modify clock for the frame */
|
the modify clock for the frame */
|
||||||
|
|
||||||
|
@ -2368,6 +2505,7 @@ page_cur_delete_rec(
|
||||||
|
|
||||||
if (mtr != 0) {
|
if (mtr != 0) {
|
||||||
buf_block_modify_clock_inc(page_cur_get_block(cursor));
|
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
|
/* 2. Find the next and the previous record. Note that the cursor is
|
||||||
|
|
|
@ -1386,212 +1386,6 @@ page_move_rec_list_start(
|
||||||
return(TRUE);
|
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.
|
Returns the nth record of the record list.
|
||||||
This is the inverse function of page_rec_get_n_recs_before().
|
This is the inverse function of page_rec_get_n_recs_before().
|
||||||
|
|
Loading…
Add table
Reference in a new issue