diff options
Diffstat (limited to 'storage/innobase/fut/fut0lst.cc')
-rw-r--r-- | storage/innobase/fut/fut0lst.cc | 689 |
1 files changed, 278 insertions, 411 deletions
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index f6e83f61cbc..93249aeab54 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,434 +28,300 @@ Created 11/28/1995 Heikki Tuuri #include "buf0buf.h" #include "page0page.h" -/********************************************************************//** -Adds a node to an empty list. */ -static -void -flst_add_to_empty( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of - empty list */ - flst_node_t* node, /*!< in: node to add */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Add a node to an empty list. */ +static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { - ulint space; - fil_addr_t node_addr; - - ut_ad(mtr && base && node); - ut_ad(base != node); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_a(!flst_get_len(base)); - - buf_ptr_get_fsp_addr(node, &space, &node_addr); - - /* Update first and last fields of base node */ - flst_write_addr(base + FLST_FIRST, node_addr, mtr); - flst_write_addr(base + FLST_LAST, node_addr, mtr); - - /* Set prev and next fields of node to add */ - flst_zero_addr(node + FLST_PREV, mtr); - flst_zero_addr(node + FLST_NEXT, mtr); - - /* Update len of base node */ - mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr); + ut_ad(base != add || boffset != aoffset); + ut_ad(boffset < base->physical_size()); + ut_ad(aoffset < add->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + fil_addr_t addr= { add->page.id.page_no(), aoffset }; + + /* Update first and last fields of base node */ + flst_write_addr(*base, base->frame + boffset + FLST_FIRST, addr, mtr); + /* MDEV-12353 TODO: use MEMMOVE record */ + flst_write_addr(*base, base->frame + boffset + FLST_LAST, addr, mtr); + + /* Set prev and next fields of node to add */ + flst_zero_addr(*add, add->frame + aoffset + FLST_PREV, mtr); + flst_zero_addr(*add, add->frame + aoffset + FLST_NEXT, mtr); + + /* Update len of base node */ + ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN)); + mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U); } -/********************************************************************//** -Inserts a node after another in a list. */ -static -void -flst_insert_after( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node1, /*!< in: node to insert after */ - flst_node_t* node2, /*!< in: node to add */ - mtr_t* mtr); /*!< in: mini-transaction handle */ -/********************************************************************//** -Inserts a node before another in a list. */ -static -void -flst_insert_before( -/*===============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: node to insert */ - flst_node_t* node3, /*!< in: node to insert before */ - mtr_t* mtr); /*!< in: mini-transaction handle */ - -/********************************************************************//** -Adds a node as the last node in a list. */ -void -flst_add_last( -/*==========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node, /*!< in: node to add */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Insert a node after another one. +@param[in,out] base base node block +@param[in] boffset byte offset of the base node +@param[in,out] cur insert position block +@param[in] coffset byte offset of the insert position +@param[in,out] add block to be added +@param[in] aoffset byte offset of the block to be added +@param[in,outr] mtr mini-transaction */ +static void flst_insert_after(buf_block_t *base, uint16_t boffset, + buf_block_t *cur, uint16_t coffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { - ulint space; - fil_addr_t node_addr; - ulint len; - fil_addr_t last_addr; - - ut_ad(mtr && base && node); - ut_ad(base != node); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - len = flst_get_len(base); - last_addr = flst_get_last(base); - - buf_ptr_get_fsp_addr(node, &space, &node_addr); - - /* If the list is not empty, call flst_insert_after */ - if (len != 0) { - flst_node_t* last_node; - - if (last_addr.page == node_addr.page) { - last_node = page_align(node) + last_addr.boffset; - } else { - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - last_node = fut_get_ptr(space, zip_size, last_addr, - RW_SX_LATCH, mtr); - } - - flst_insert_after(base, last_node, node, mtr); - } else { - /* else call flst_add_to_empty */ - flst_add_to_empty(base, node, mtr); - } + ut_ad(base != cur || boffset != coffset); + ut_ad(base != add || boffset != aoffset); + ut_ad(cur != add || coffset != aoffset); + ut_ad(boffset < base->physical_size()); + ut_ad(coffset < cur->physical_size()); + ut_ad(aoffset < add->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + fil_addr_t cur_addr= { cur->page.id.page_no(), coffset }; + fil_addr_t add_addr= { add->page.id.page_no(), aoffset }; + fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); + + flst_write_addr(*add, add->frame + aoffset + FLST_PREV, cur_addr, mtr); + flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, next_addr, mtr); + + if (fil_addr_is_null(next_addr)) + flst_write_addr(*base, base->frame + boffset + FLST_LAST, add_addr, mtr); + else + { + buf_block_t *block; + flst_node_t *next= fut_get_ptr(add->page.id.space(), add->zip_size(), + next_addr, RW_SX_LATCH, mtr, &block); + flst_write_addr(*block, next + FLST_PREV, add_addr, mtr); + } + + flst_write_addr(*cur, cur->frame + coffset + FLST_NEXT, add_addr, mtr); + + byte *len= &base->frame[boffset + FLST_LEN]; + mtr->write<4>(*base, len, mach_read_from_4(len) + 1); } -/********************************************************************//** -Adds a node as the first node in a list. */ -void -flst_add_first( -/*===========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node, /*!< in: node to add */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Insert a node before another one. +@param[in,out] base base node block +@param[in] boffset byte offset of the base node +@param[in,out] cur insert position block +@param[in] coffset byte offset of the insert position +@param[in,out] add block to be added +@param[in] aoffset byte offset of the block to be added +@param[in,outr] mtr mini-transaction */ +static void flst_insert_before(buf_block_t *base, uint16_t boffset, + buf_block_t *cur, uint16_t coffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { - ulint space; - fil_addr_t node_addr; - ulint len; - fil_addr_t first_addr; - flst_node_t* first_node; - - ut_ad(mtr && base && node); - ut_ad(base != node); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - len = flst_get_len(base); - first_addr = flst_get_first(base); - - buf_ptr_get_fsp_addr(node, &space, &node_addr); - - /* If the list is not empty, call flst_insert_before */ - if (len != 0) { - if (first_addr.page == node_addr.page) { - first_node = page_align(node) + first_addr.boffset; - } else { - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - first_node = fut_get_ptr(space, zip_size, first_addr, - RW_SX_LATCH, mtr); - } - - flst_insert_before(base, node, first_node, mtr); - } else { - /* else call flst_add_to_empty */ - flst_add_to_empty(base, node, mtr); - } + ut_ad(base != cur || boffset != coffset); + ut_ad(base != add || boffset != aoffset); + ut_ad(cur != add || coffset != aoffset); + ut_ad(boffset < base->physical_size()); + ut_ad(coffset < cur->physical_size()); + ut_ad(aoffset < add->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + fil_addr_t cur_addr= { cur->page.id.page_no(), coffset }; + fil_addr_t add_addr= { add->page.id.page_no(), aoffset }; + fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); + + flst_write_addr(*add, add->frame + aoffset + FLST_PREV, prev_addr, mtr); + flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, cur_addr, mtr); + + if (fil_addr_is_null(prev_addr)) + flst_write_addr(*base, base->frame + boffset + FLST_FIRST, add_addr, mtr); + else + { + buf_block_t *block; + flst_node_t *prev= fut_get_ptr(add->page.id.space(), add->zip_size(), + prev_addr, RW_SX_LATCH, mtr, &block); + flst_write_addr(*block, prev + FLST_NEXT, add_addr, mtr); + } + + flst_write_addr(*cur, cur->frame + coffset + FLST_PREV, add_addr, mtr); + + byte *len= &base->frame[boffset + FLST_LEN]; + mtr->write<4>(*base, len, mach_read_from_4(len) + 1); } -/********************************************************************//** -Inserts a node after another in a list. */ -static -void -flst_insert_after( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node1, /*!< in: node to insert after */ - flst_node_t* node2, /*!< in: node to add */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Append a file list node to a list. +@param[in,out] base base node block +@param[in] boffset byte offset of the base node +@param[in,out] add block to be added +@param[in] aoffset byte offset of the node to be added +@param[in,outr] mtr mini-transaction */ +void flst_add_last(buf_block_t *base, uint16_t boffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { - ulint space; - fil_addr_t node1_addr; - fil_addr_t node2_addr; - flst_node_t* node3; - fil_addr_t node3_addr; - ulint len; - - ut_ad(mtr && node1 && node2 && base); - ut_ad(base != node1); - ut_ad(base != node2); - ut_ad(node2 != node1); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node1, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node2, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - buf_ptr_get_fsp_addr(node1, &space, &node1_addr); - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - node3_addr = flst_get_next_addr(node1); - - /* Set prev and next fields of node2 */ - flst_write_addr(node2 + FLST_PREV, node1_addr, mtr); - flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr); - - if (!fil_addr_is_null(node3_addr)) { - /* Update prev field of node3 */ - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - node3 = fut_get_ptr(space, zip_size, - node3_addr, RW_SX_LATCH, mtr); - flst_write_addr(node3 + FLST_PREV, node2_addr, mtr); - } else { - /* node1 was last in list: update last field in base */ - flst_write_addr(base + FLST_LAST, node2_addr, mtr); - } - - /* Set next field of node1 */ - flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base); - mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); + ut_ad(base != add || boffset != aoffset); + ut_ad(boffset < base->physical_size()); + ut_ad(aoffset < add->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + if (!flst_get_len(base->frame + boffset)) + flst_add_to_empty(base, boffset, add, aoffset, mtr); + else + { + fil_addr_t addr= flst_get_last(base->frame + boffset); + buf_block_t *cur= add; + const flst_node_t *c= addr.page == add->page.id.page_no() + ? add->frame + addr.boffset + : fut_get_ptr(add->page.id.space(), add->zip_size(), addr, + RW_SX_LATCH, mtr, &cur); + flst_insert_after(base, boffset, cur, + static_cast<uint16_t>(c - cur->frame), + add, aoffset, mtr); + } } -/********************************************************************//** -Inserts a node before another in a list. */ -static -void -flst_insert_before( -/*===============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: node to insert */ - flst_node_t* node3, /*!< in: node to insert before */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Prepend a file list node to a list. +@param[in,out] base base node block +@param[in] boffset byte offset of the base node +@param[in,out] add block to be added +@param[in] aoffset byte offset of the node to be added +@param[in,outr] mtr mini-transaction */ +void flst_add_first(buf_block_t *base, uint16_t boffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { - ulint space; - flst_node_t* node1; - fil_addr_t node1_addr; - fil_addr_t node2_addr; - fil_addr_t node3_addr; - ulint len; - - ut_ad(mtr && node2 && node3 && base); - ut_ad(base != node2); - ut_ad(base != node3); - ut_ad(node2 != node3); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node2, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node3, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - buf_ptr_get_fsp_addr(node3, &space, &node3_addr); - - node1_addr = flst_get_prev_addr(node3); - - /* Set prev and next fields of node2 */ - flst_write_addr(node2 + FLST_PREV, node1_addr, mtr); - flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr); - - if (!fil_addr_is_null(node1_addr)) { - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - /* Update next field of node1 */ - node1 = fut_get_ptr(space, zip_size, node1_addr, - RW_SX_LATCH, mtr); - flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr); - } else { - /* node3 was first in list: update first field in base */ - flst_write_addr(base + FLST_FIRST, node2_addr, mtr); - } - - /* Set prev field of node3 */ - flst_write_addr(node3 + FLST_PREV, node2_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base); - mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr); + ut_ad(base != add || boffset != aoffset); + ut_ad(boffset < base->physical_size()); + ut_ad(aoffset < add->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, add->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + if (!flst_get_len(base->frame + boffset)) + flst_add_to_empty(base, boffset, add, aoffset, mtr); + else + { + fil_addr_t addr= flst_get_first(base->frame + boffset); + buf_block_t *cur= add; + const flst_node_t *c= addr.page == add->page.id.page_no() + ? add->frame + addr.boffset + : fut_get_ptr(add->page.id.space(), add->zip_size(), addr, + RW_SX_LATCH, mtr, &cur); + flst_insert_before(base, boffset, cur, + static_cast<uint16_t>(c - cur->frame), + add, aoffset, mtr); + } } -/********************************************************************//** -Removes a node. */ -void -flst_remove( -/*========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: node to remove */ - mtr_t* mtr) /*!< in: mini-transaction handle */ +/** Remove a file list node. +@param[in,out] base base node block +@param[in] boffset byte offset of the base node +@param[in,out] cur block to be removed +@param[in] coffset byte offset of the current record to be removed +@param[in,outr] mtr mini-transaction */ +void flst_remove(buf_block_t *base, uint16_t boffset, + buf_block_t *cur, uint16_t coffset, mtr_t *mtr) { - ulint space; - flst_node_t* node1; - fil_addr_t node1_addr; - fil_addr_t node2_addr; - flst_node_t* node3; - fil_addr_t node3_addr; - ulint len; - - ut_ad(mtr && node2 && base); - ut_ad(mtr_memo_contains_page_flagged(mtr, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(mtr_memo_contains_page_flagged(mtr, node2, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - node1_addr = flst_get_prev_addr(node2); - node3_addr = flst_get_next_addr(node2); - - if (!fil_addr_is_null(node1_addr)) { - - /* Update next field of node1 */ - - if (node1_addr.page == node2_addr.page) { - - node1 = page_align(node2) + node1_addr.boffset; - } else { - node1 = fut_get_ptr(space, zip_size, - node1_addr, RW_SX_LATCH, mtr); - } - - ut_ad(node1 != node2); - - flst_write_addr(node1 + FLST_NEXT, node3_addr, mtr); - } else { - /* node2 was first in list: update first field in base */ - flst_write_addr(base + FLST_FIRST, node3_addr, mtr); - } - - if (!fil_addr_is_null(node3_addr)) { - /* Update prev field of node3 */ - - if (node3_addr.page == node2_addr.page) { - - node3 = page_align(node2) + node3_addr.boffset; - } else { - node3 = fut_get_ptr(space, zip_size, - node3_addr, RW_SX_LATCH, mtr); - } - - ut_ad(node2 != node3); - - flst_write_addr(node3 + FLST_PREV, node1_addr, mtr); - } else { - /* node2 was last in list: update last field in base */ - flst_write_addr(base + FLST_LAST, node1_addr, mtr); - } - - /* Update len of base node */ - len = flst_get_len(base); - ut_ad(len > 0); - - mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr); + ut_ad(boffset < base->physical_size()); + ut_ad(coffset < cur->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, cur->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + const fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); + const fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); + + if (fil_addr_is_null(prev_addr)) + flst_write_addr(*base, base->frame + boffset + FLST_FIRST, next_addr, mtr); + else + { + buf_block_t *block= cur; + flst_node_t *prev= prev_addr.page == cur->page.id.page_no() + ? cur->frame + prev_addr.boffset + : fut_get_ptr(cur->page.id.space(), cur->zip_size(), prev_addr, + RW_SX_LATCH, mtr, &block); + flst_write_addr(*block, prev + FLST_NEXT, next_addr, mtr); + } + + if (fil_addr_is_null(next_addr)) + flst_write_addr(*base, base->frame + boffset + FLST_LAST, prev_addr, mtr); + else + { + buf_block_t *block= cur; + flst_node_t *next= next_addr.page == cur->page.id.page_no() + ? cur->frame + next_addr.boffset + : fut_get_ptr(cur->page.id.space(), cur->zip_size(), next_addr, + RW_SX_LATCH, mtr, &block); + flst_write_addr(*block, next + FLST_PREV, prev_addr, mtr); + } + + byte *len= &base->frame[boffset + FLST_LEN]; + ut_ad(mach_read_from_4(len) > 0); + mtr->write<4>(*base, len, mach_read_from_4(len) - 1); } -/********************************************************************//** -Validates a file-based list. -@return TRUE if ok */ -ibool -flst_validate( -/*==========*/ - const flst_base_node_t* base, /*!< in: pointer to base node of list */ - mtr_t* mtr1) /*!< in: mtr */ +#ifdef UNIV_DEBUG +/** Validate a file-based list. */ +void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) { - ulint space; - const flst_node_t* node; - fil_addr_t node_addr; - fil_addr_t base_addr; - ulint len; - ulint i; - mtr_t mtr2; - - ut_ad(base); - ut_ad(mtr_memo_contains_page_flagged(mtr1, base, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - /* We use two mini-transaction handles: the first is used to - lock the base node, and prevent other threads from modifying the - list. The second is used to traverse the list. We cannot run the - second mtr without committing it at times, because if the list - is long, then the x-locked pages could fill the buffer resulting - in a deadlock. */ - - /* Find out the space id */ - buf_ptr_get_fsp_addr(base, &space, &base_addr); - - fil_space_t* s = fil_space_acquire_silent(space); - ulint zip_size = s ? s->zip_size() : 0; - if (s) s->release(); - - len = flst_get_len(base); - node_addr = flst_get_first(base); - - for (i = 0; i < len; i++) { - mtr_start(&mtr2); - - node = fut_get_ptr(space, zip_size, - node_addr, RW_SX_LATCH, &mtr2); - node_addr = flst_get_next_addr(node); - - mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer - becoming full */ - } - - ut_a(fil_addr_is_null(node_addr)); - - node_addr = flst_get_last(base); - - for (i = 0; i < len; i++) { - mtr_start(&mtr2); - - node = fut_get_ptr(space, zip_size, - node_addr, RW_SX_LATCH, &mtr2); - node_addr = flst_get_prev_addr(node); - - mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer - becoming full */ - } - - ut_a(fil_addr_is_null(node_addr)); - - return(TRUE); + ut_ad(boffset < base->physical_size()); + ut_ad(mtr_memo_contains_page_flagged(mtr, base->frame, + MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); + + /* We use two mini-transaction handles: the first is used to lock + the base node, and prevent other threads from modifying the list. + The second is used to traverse the list. We cannot run the second + mtr without committing it at times, because if the list is long, + the x-locked pages could fill the buffer, resulting in a deadlock. */ + mtr_t mtr2; + + const uint32_t len= flst_get_len(base->frame + boffset); + fil_addr_t addr= flst_get_first(base->frame + boffset); + + for (uint32_t i= len; i--; ) + { + mtr2.start(); + const flst_node_t *node= fut_get_ptr(base->page.id.space(), + base->zip_size(), addr, + RW_SX_LATCH, &mtr2); + addr= flst_get_next_addr(node); + mtr2.commit(); + } + + ut_ad(fil_addr_is_null(addr)); + + addr= flst_get_last(base->frame + boffset); + + for (uint32_t i= len; i--; ) + { + mtr2.start(); + const flst_node_t *node= fut_get_ptr(base->page.id.space(), + base->zip_size(), addr, + RW_SX_LATCH, &mtr2); + addr= flst_get_prev_addr(node); + mtr2.commit(); + } + + ut_ad(fil_addr_is_null(addr)); } +#endif |