diff options
Diffstat (limited to 'storage/innobase/fut/fut0lst.cc')
-rw-r--r-- | storage/innobase/fut/fut0lst.cc | 232 |
1 files changed, 128 insertions, 104 deletions
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index e084f0b7935..a52027f28bc 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, 2020, MariaDB Corporation. +Copyright (c) 2019, 2022, 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 @@ -38,9 +38,8 @@ Created 11/28/1995 Heikki Tuuri static void flst_write_addr(const buf_block_t& block, byte *faddr, uint32_t page, uint16_t boffset, mtr_t* mtr) { - ut_ad(mtr->memo_contains_page_flagged(faddr, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); + ut_ad(mtr->memo_contains_page_flagged(faddr, MTR_MEMO_PAGE_X_FIX | + MTR_MEMO_PAGE_SX_FIX)); ut_a(page == FIL_NULL || boffset >= FIL_PAGE_DATA); ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA); @@ -69,12 +68,12 @@ static void flst_write_addr(const buf_block_t& block, byte *faddr, /** Write 2 null file addresses. @param[in] b file page -@param[in,out] addr file address to be zeroed out +@param[in,out] addr file address to be zeroed out @param[in,out] mtr mini-transaction */ static void flst_zero_both(const buf_block_t& b, byte *addr, mtr_t *mtr) { if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL) - mtr->memset(&b, ulint(addr - b.frame) + FIL_ADDR_PAGE, 4, 0xff); + mtr->memset(&b, ulint(addr - b.page.frame) + FIL_ADDR_PAGE, 4, 0xff); mtr->write<2,mtr_t::MAYBE_NOP>(b, addr + FIL_ADDR_BYTE, 0U); /* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source) which is 4 bytes, or less than FIL_ADDR_SIZE. */ @@ -95,12 +94,13 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - ut_ad(!mach_read_from_4(base->frame + boffset + FLST_LEN)); - mtr->write<1>(*base, base->frame + boffset + (FLST_LEN + 3), 1U); + ut_ad(!mach_read_from_4(base->page.frame + boffset + FLST_LEN)); + mtr->write<1>(*base, base->page.frame + boffset + (FLST_LEN + 3), 1U); /* Update first and last fields of base node */ - flst_write_addr(*base, base->frame + boffset + FLST_FIRST, + flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST, add->page.id().page_no(), aoffset, mtr); - memcpy(base->frame + boffset + FLST_LAST, base->frame + boffset + FLST_FIRST, + memcpy(base->page.frame + boffset + FLST_LAST, + base->page.frame + boffset + FLST_FIRST, FIL_ADDR_SIZE); /* Initialize FLST_LAST by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source) which is 4 bytes, or less than FIL_ADDR_SIZE. */ @@ -109,7 +109,7 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, /* Set prev and next fields of node to add */ static_assert(FLST_NEXT == FLST_PREV + FIL_ADDR_SIZE, "compatibility"); - flst_zero_both(*add, add->frame + aoffset + FLST_PREV, mtr); + flst_zero_both(*add, add->page.frame + aoffset + FLST_PREV, mtr); } /** Insert a node after another one. @@ -119,10 +119,11 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, @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) +@param[in,out] mtr mini-transaction */ +static dberr_t 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) { ut_ad(base != cur || boffset != coffset); ut_ad(base != add || boffset != aoffset); @@ -137,30 +138,32 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset, ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - fil_addr_t next_addr= flst_get_next_addr(cur->frame + coffset); + fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset); - flst_write_addr(*add, add->frame + aoffset + FLST_PREV, + flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV, cur->page.id().page_no(), coffset, mtr); - flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, + flst_write_addr(*add, add->page.frame + aoffset + FLST_NEXT, next_addr.page, next_addr.boffset, mtr); + dberr_t err= DB_SUCCESS; + if (next_addr.page == FIL_NULL) - flst_write_addr(*base, base->frame + boffset + FLST_LAST, + flst_write_addr(*base, base->page.frame + boffset + FLST_LAST, add->page.id().page_no(), aoffset, 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, + else if (buf_block_t *block= + buf_page_get_gen(page_id_t{add->page.id().space(), next_addr.page}, + add->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err)) + flst_write_addr(*block, block->page.frame + + next_addr.boffset + FLST_PREV, add->page.id().page_no(), aoffset, mtr); - } - flst_write_addr(*cur, cur->frame + coffset + FLST_NEXT, + flst_write_addr(*cur, cur->page.frame + coffset + FLST_NEXT, add->page.id().page_no(), aoffset, mtr); - byte *len= &base->frame[boffset + FLST_LEN]; + byte *len= &base->page.frame[boffset + FLST_LEN]; mtr->write<4>(*base, len, mach_read_from_4(len) + 1); + return err; } /** Insert a node before another one. @@ -170,10 +173,12 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset, @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) +@param[in,out] mtr mini-transaction +@return error code */ +static dberr_t 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) { ut_ad(base != cur || boffset != coffset); ut_ad(base != add || boffset != aoffset); @@ -188,30 +193,32 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset, ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - fil_addr_t prev_addr= flst_get_prev_addr(cur->frame + coffset); + fil_addr_t prev_addr= flst_get_prev_addr(cur->page.frame + coffset); - flst_write_addr(*add, add->frame + aoffset + FLST_PREV, + flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV, prev_addr.page, prev_addr.boffset, mtr); - flst_write_addr(*add, add->frame + aoffset + FLST_NEXT, - cur->page.id().page_no(), coffset, mtr); + flst_write_addr(*add, add->page.frame + aoffset + FLST_NEXT, + cur->page.id().page_no(), coffset, mtr); + + dberr_t err= DB_SUCCESS; if (prev_addr.page == FIL_NULL) - flst_write_addr(*base, base->frame + boffset + FLST_FIRST, + flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST, add->page.id().page_no(), aoffset, 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, + else if (buf_block_t *block= + buf_page_get_gen(page_id_t{add->page.id().space(), prev_addr.page}, + add->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err)) + flst_write_addr(*block, block->page.frame + + prev_addr.boffset + FLST_NEXT, add->page.id().page_no(), aoffset, mtr); - } - flst_write_addr(*cur, cur->frame + coffset + FLST_PREV, + flst_write_addr(*cur, cur->page.frame + coffset + FLST_PREV, add->page.id().page_no(), aoffset, mtr); - byte *len= &base->frame[boffset + FLST_LEN]; + byte *len= &base->page.frame[boffset + FLST_LEN]; mtr->write<4>(*base, len, mach_read_from_4(len) + 1); + return err; } /** Initialize a list base node. @@ -233,8 +240,8 @@ void flst_init(const buf_block_t& block, byte *base, mtr_t *mtr) @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) +dberr_t flst_add_last(buf_block_t *base, uint16_t boffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); @@ -243,20 +250,23 @@ void flst_add_last(buf_block_t *base, uint16_t boffset, MTR_MEMO_PAGE_SX_FIX)); ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - - if (!flst_get_len(base->frame + boffset)) + if (!flst_get_len(base->page.frame + boffset)) + { flst_add_to_empty(base, boffset, add, aoffset, mtr); + return DB_SUCCESS; + } else { - fil_addr_t addr= flst_get_last(base->frame + boffset); + fil_addr_t addr= flst_get_last(base->page.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); + dberr_t err; + if (addr.page != add->page.id().page_no() && + !(cur= buf_page_get_gen(page_id_t{add->page.id().space(), addr.page}, + add->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err))) + return err; + return flst_insert_after(base, boffset, cur, addr.boffset, + add, aoffset, mtr); } } @@ -265,9 +275,10 @@ void flst_add_last(buf_block_t *base, uint16_t boffset, @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) +@param[in,out] mtr mini-transaction +@return error code */ +dberr_t flst_add_first(buf_block_t *base, uint16_t boffset, + buf_block_t *add, uint16_t aoffset, mtr_t *mtr) { ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); @@ -277,19 +288,23 @@ void flst_add_first(buf_block_t *base, uint16_t boffset, ut_ad(mtr->memo_contains_flagged(add, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - if (!flst_get_len(base->frame + boffset)) + if (!flst_get_len(base->page.frame + boffset)) + { flst_add_to_empty(base, boffset, add, aoffset, mtr); + return DB_SUCCESS; + } else { - fil_addr_t addr= flst_get_first(base->frame + boffset); + fil_addr_t addr= flst_get_first(base->page.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); + dberr_t err; + if (addr.page != add->page.id().page_no() && + !(cur= buf_page_get_gen(page_id_t{add->page.id().space(), addr.page}, + add->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err))) + return err; + return flst_insert_before(base, boffset, cur, addr.boffset, + add, aoffset, mtr); } } @@ -298,9 +313,10 @@ void flst_add_first(buf_block_t *base, uint16_t boffset, @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) +@param[in,out] mtr mini-transaction +@return error code */ +dberr_t flst_remove(buf_block_t *base, uint16_t boffset, + buf_block_t *cur, uint16_t coffset, mtr_t *mtr) { ut_ad(boffset < base->physical_size()); ut_ad(coffset < cur->physical_size()); @@ -309,40 +325,46 @@ void flst_remove(buf_block_t *base, uint16_t boffset, ut_ad(mtr->memo_contains_flagged(cur, 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); + const fil_addr_t prev_addr= flst_get_prev_addr(cur->page.frame + coffset); + const fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset); + dberr_t err= DB_SUCCESS; if (prev_addr.page == FIL_NULL) - flst_write_addr(*base, base->frame + boffset + FLST_FIRST, + flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST, next_addr.page, next_addr.boffset, 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.page, next_addr.boffset, mtr); + buf_block_t *b= cur; + if (prev_addr.page == b->page.id().page_no() || + (b= buf_page_get_gen(page_id_t(b->page.id().space(), prev_addr.page), + b->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err))) + flst_write_addr(*b, b->page.frame + prev_addr.boffset + FLST_NEXT, + next_addr.page, next_addr.boffset, mtr); } if (next_addr.page == FIL_NULL) - flst_write_addr(*base, base->frame + boffset + FLST_LAST, + flst_write_addr(*base, base->page.frame + boffset + FLST_LAST, prev_addr.page, prev_addr.boffset, 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.page, prev_addr.boffset, mtr); + dberr_t err2; + if (next_addr.page == cur->page.id().page_no() || + (cur= buf_page_get_gen(page_id_t(cur->page.id().space(), + next_addr.page), + cur->zip_size(), RW_SX_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, mtr, &err2))) + flst_write_addr(*cur, cur->page.frame + next_addr.boffset + FLST_PREV, + prev_addr.page, prev_addr.boffset, mtr); + else if (err == DB_SUCCESS) + err= err2; } - byte *len= &base->frame[boffset + FLST_LEN]; - ut_ad(mach_read_from_4(len) > 0); + byte *len= &base->page.frame[boffset + FLST_LEN]; + if (UNIV_UNLIKELY(!mach_read_from_4(len))) + return DB_CORRUPTION; mtr->write<4>(*base, len, mach_read_from_4(len) - 1); + return err; } #ifdef UNIV_DEBUG @@ -360,30 +382,32 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) 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); + const uint32_t len= flst_get_len(base->page.frame + boffset); + fil_addr_t addr= flst_get_first(base->page.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); + const buf_block_t *b= + buf_page_get_gen(page_id_t(base->page.id().space(), addr.page), + base->zip_size(), RW_SX_LATCH, nullptr, BUF_GET, mtr); + ut_ad(b); + addr= flst_get_next_addr(b->page.frame + addr.boffset); mtr2.commit(); } ut_ad(addr.page == FIL_NULL); - addr= flst_get_last(base->frame + boffset); + addr= flst_get_last(base->page.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); + const buf_block_t *b= + buf_page_get_gen(page_id_t(base->page.id().space(), addr.page), + base->zip_size(), RW_SX_LATCH, nullptr, BUF_GET, mtr); + ut_ad(b); + addr= flst_get_prev_addr(b->page.frame + addr.boffset); mtr2.commit(); } |