summaryrefslogtreecommitdiff
path: root/storage/innobase/fut/fut0lst.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/fut/fut0lst.cc')
-rw-r--r--storage/innobase/fut/fut0lst.cc689
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