summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/CMakeLists.txt1
-rw-r--r--storage/innobase/btr/btr0btr.cc429
-rw-r--r--storage/innobase/btr/btr0bulk.cc1
-rw-r--r--storage/innobase/btr/btr0cur.cc679
-rw-r--r--storage/innobase/btr/btr0defragment.cc11
-rw-r--r--storage/innobase/btr/btr0pcur.cc73
-rw-r--r--storage/innobase/btr/btr0sea.cc168
-rw-r--r--storage/innobase/dict/dict0crea.cc7
-rw-r--r--storage/innobase/dict/dict0dict.cc6
-rw-r--r--storage/innobase/dict/dict0load.cc30
-rw-r--r--storage/innobase/dict/dict0stats.cc132
-rw-r--r--storage/innobase/fil/fil0crypt.cc1
-rw-r--r--storage/innobase/fts/fts0fts.cc7
-rw-r--r--storage/innobase/gis/gis0rtree.cc158
-rw-r--r--storage/innobase/gis/gis0sea.cc65
-rw-r--r--storage/innobase/handler/ha_innodb.cc9
-rw-r--r--storage/innobase/handler/handler0alter.cc3
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc58
-rw-r--r--storage/innobase/include/btr0btr.h29
-rw-r--r--storage/innobase/include/btr0btr.inl40
-rw-r--r--storage/innobase/include/btr0cur.h56
-rw-r--r--storage/innobase/include/btr0cur.inl12
-rw-r--r--storage/innobase/include/btr0pcur.h41
-rw-r--r--storage/innobase/include/btr0pcur.inl25
-rw-r--r--storage/innobase/include/dyn0buf.h56
-rw-r--r--storage/innobase/include/gis0rtree.h18
-rw-r--r--storage/innobase/include/mtr0mtr.h257
-rw-r--r--storage/innobase/include/mtr0mtr.inl185
-rw-r--r--storage/innobase/include/page0cur.h22
-rw-r--r--storage/innobase/include/page0cur.inl19
-rw-r--r--storage/innobase/include/row0row.h1
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc1110
-rw-r--r--storage/innobase/page/page0cur.cc32
-rw-r--r--storage/innobase/page/page0page.cc17
-rw-r--r--storage/innobase/que/que0que.cc8
-rw-r--r--storage/innobase/row/row0import.cc16
-rw-r--r--storage/innobase/row/row0ins.cc114
-rw-r--r--storage/innobase/row/row0log.cc35
-rw-r--r--storage/innobase/row/row0merge.cc14
-rw-r--r--storage/innobase/row/row0mysql.cc16
-rw-r--r--storage/innobase/row/row0purge.cc10
-rw-r--r--storage/innobase/row/row0row.cc14
-rw-r--r--storage/innobase/row/row0sel.cc36
-rw-r--r--storage/innobase/row/row0uins.cc5
-rw-r--r--storage/innobase/row/row0umod.cc12
-rw-r--r--storage/innobase/row/row0upd.cc4
-rw-r--r--storage/innobase/trx/trx0trx.cc2
47 files changed, 1515 insertions, 2529 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index c1d73b1b9d4..d655cf81231 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -299,7 +299,6 @@ SET(INNOBASE_SOURCES
include/mem0mem.inl
include/mtr0log.h
include/mtr0mtr.h
- include/mtr0mtr.inl
include/mtr0types.h
include/os0file.h
include/os0file.inl
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index e5befe2cddd..24de98f8590 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -748,7 +748,7 @@ btr_page_get_father_node_ptr_func(
const rec_t* user_rec = btr_cur_get_rec(cursor);
ut_a(page_rec_is_user_rec(user_rec));
- if (btr_cur_search_to_nth_level(index, level + 1,
+ if (btr_cur_search_to_nth_level(level + 1,
dict_index_build_node_ptr(index,
user_rec, 0,
heap, level),
@@ -787,44 +787,33 @@ btr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
- dict_index_t* index, /*!< in: b-tree index */
- buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
its page x-latched */
{
- rec_t* rec
- = page_rec_get_next(page_get_infimum_rec(buf_block_get_frame(
- block)));
- if (UNIV_UNLIKELY(!rec)) {
- return nullptr;
- }
- btr_cur_position(index, rec, block, cursor);
- return(btr_page_get_father_node_ptr(offsets, heap, cursor, mtr));
+ rec_t *rec=
+ page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
+ if (UNIV_UNLIKELY(!rec))
+ return nullptr;
+ cursor->page_cur.rec= rec;
+ return btr_page_get_father_node_ptr(offsets, heap, cursor, mtr);
}
/** Seek to the parent page of a B-tree page.
-@param[in,out] index b-tree
-@param[in] block child page
@param[in,out] mtr mini-transaction
-@param[out] cursor cursor pointing to the x-latched parent page
+@param[in,out] cursor cursor pointing to the x-latched parent page
@return whether the cursor was successfully positioned */
-bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
- btr_cur_t* cursor)
+bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
{
- mem_heap_t* heap;
- rec_t* rec
- = page_rec_get_next(page_get_infimum_rec(buf_block_get_frame(
- block)));
- if (UNIV_UNLIKELY(!rec)) {
- return false;
- }
- btr_cur_position(index, rec, block, cursor);
-
- heap = mem_heap_create(100);
- const bool got = btr_page_get_father_node_ptr(NULL, heap, cursor, mtr);
- mem_heap_free(heap);
- return got;
+ rec_t *rec=
+ page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
+ if (UNIV_UNLIKELY(!rec))
+ return false;
+ cursor->page_cur.rec= rec;
+ mem_heap_t *heap= mem_heap_create(100);
+ const bool got= btr_page_get_father_node_ptr(nullptr, heap, cursor, mtr);
+ mem_heap_free(heap);
+ return got;
}
#ifdef UNIV_DEBUG
@@ -1278,19 +1267,18 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
/** Reorganize an index page.
@param cursor index page cursor
-@param index the index that the cursor belongs to
@param mtr mini-transaction */
-static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
- mtr_t *mtr)
+static dberr_t btr_page_reorganize_low(page_cur_t *cursor, mtr_t *mtr)
{
buf_block_t *const block= cursor->block;
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!is_buf_block_get_page_zip(block));
ut_ad(fil_page_index_page_check(block->page.frame));
- ut_ad(index->is_dummy ||
- block->page.id().space() == index->table->space->id);
- ut_ad(index->is_dummy || block->page.id().page_no() != index->page ||
+ ut_ad(cursor->index->is_dummy ||
+ block->page.id().space() == cursor->index->table->space->id);
+ ut_ad(cursor->index->is_dummy ||
+ block->page.id().page_no() != cursor->index->page ||
!page_has_siblings(block->page.frame));
/* Save the cursor position. */
@@ -1308,8 +1296,8 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NO_REDO);
- page_create(block, mtr, index->table->not_redundant());
- if (index->is_spatial())
+ page_create(block, mtr, cursor->index->table->not_redundant());
+ if (cursor->index->is_spatial())
block->page.frame[FIL_PAGE_TYPE + 1]= byte(FIL_PAGE_RTREE);
static_assert(((FIL_PAGE_INDEX & 0xff00) | byte(FIL_PAGE_RTREE)) ==
@@ -1321,7 +1309,7 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
dberr_t err=
page_copy_rec_list_end_no_locks(block, old,
page_get_infimum_rec(old->page.frame),
- index, mtr);
+ cursor->index, mtr);
mtr->set_log_mode(log_mode);
if (UNIV_UNLIKELY(err != DB_SUCCESS))
@@ -1335,17 +1323,18 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
if (page_get_max_trx_id(block->page.frame))
/* PAGE_MAX_TRX_ID must be zero on non-leaf pages other than
clustered index root pages. */
- ut_ad(dict_index_is_sec_or_ibuf(index)
+ ut_ad(dict_index_is_sec_or_ibuf(cursor->index)
? page_is_leaf(block->page.frame)
- : block->page.id().page_no() == index->page);
+ : block->page.id().page_no() == cursor->index->page);
else
/* PAGE_MAX_TRX_ID is unused in clustered index pages (other than
the root where it is repurposed as PAGE_ROOT_AUTO_INC), non-leaf
pages, and in temporary tables. It was always zero-initialized in
page_create(). PAGE_MAX_TRX_ID must be nonzero on
dict_index_is_sec_or_ibuf() leaf pages. */
- ut_ad(index->table->is_temporary() || !page_is_leaf(block->page.frame) ||
- !dict_index_is_sec_or_ibuf(index));
+ ut_ad(cursor->index->table->is_temporary() ||
+ !page_is_leaf(block->page.frame) ||
+ !dict_index_is_sec_or_ibuf(cursor->index));
#endif
const uint16_t data_size1= page_get_data_size(old->page.frame);
@@ -1369,10 +1358,10 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
else if (!(cursor->rec= page_rec_get_nth(block->page.frame, pos)))
return DB_CORRUPTION;
- if (block->page.id().page_no() != index->page ||
+ if (block->page.id().page_no() != cursor->index->page ||
fil_page_get_type(old->page.frame) != FIL_PAGE_TYPE_INSTANT)
ut_ad(!memcmp(old->page.frame, block->page.frame, PAGE_HEADER));
- else if (!index->is_instant())
+ else if (!cursor->index->is_instant())
{
ut_ad(!memcmp(old->page.frame, block->page.frame, FIL_PAGE_TYPE));
ut_ad(!memcmp(old->page.frame + FIL_PAGE_TYPE + 2,
@@ -1388,7 +1377,7 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
FIL_PAGE_TYPE + old->page.frame, 2);
memcpy_aligned<2>(PAGE_HEADER + PAGE_INSTANT + block->page.frame,
PAGE_HEADER + PAGE_INSTANT + old->page.frame, 2);
- if (!index->table->instant);
+ if (!cursor->index->table->instant);
else if (page_is_comp(block->page.frame))
{
memcpy(PAGE_NEW_INFIMUM + block->page.frame,
@@ -1411,9 +1400,9 @@ static dberr_t btr_page_reorganize_low(page_cur_t *cursor, dict_index_t *index,
block->page.frame + PAGE_MAX_TRX_ID + PAGE_HEADER,
PAGE_DATA - (PAGE_MAX_TRX_ID + PAGE_HEADER)));
- if (!index->has_locking());
- else if (index->page == FIL_NULL)
- ut_ad(index->is_dummy);
+ if (!cursor->index->has_locking());
+ else if (cursor->index->page == FIL_NULL)
+ ut_ad(cursor->index->is_dummy);
else
lock_move_reorganize_page(block, old);
@@ -1568,7 +1557,8 @@ btr_page_reorganize_block(
return page_zip_reorganize(block, index, z_level, mtr, true);
page_cur_t cur;
page_cur_set_before_first(block, &cur);
- return btr_page_reorganize_low(&cur, index, mtr);
+ cur.index= index;
+ return btr_page_reorganize_low(&cur, mtr);
}
/*************************************************************//**
@@ -1580,24 +1570,21 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
+@param cursor page cursor
+@param mtr mini-transaction
@return error code
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
-dberr_t
-btr_page_reorganize(
-/*================*/
- page_cur_t* cursor, /*!< in/out: page cursor */
- dict_index_t* index, /*!< in: the index tree of the page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
{
if (!buf_block_get_page_zip(cursor->block))
- return btr_page_reorganize_low(cursor, index, mtr);
+ return btr_page_reorganize_low(cursor, mtr);
ulint pos= page_rec_get_n_recs_before(cursor->rec);
if (UNIV_UNLIKELY(pos == ULINT_UNDEFINED))
return DB_CORRUPTION;
- dberr_t err= page_zip_reorganize(cursor->block, index, page_zip_level, mtr,
- true);
+ dberr_t err= page_zip_reorganize(cursor->block, cursor->index,
+ page_zip_level, mtr, true);
if (err == DB_FAIL);
else if (!pos)
ut_ad(cursor->rec == page_get_infimum_rec(cursor->block->page.frame));
@@ -2001,7 +1988,7 @@ btr_root_raise_and_insert(
page_cur_set_before_first(root, page_cursor);
node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr,
- index, offsets, heap, 0, mtr);
+ offsets, heap, 0, mtr);
/* The root page should only contain the node pointer
to new_block at this point. Thus, the data should fit. */
@@ -2014,13 +2001,15 @@ btr_root_raise_and_insert(
ibuf_reset_free_bits(new_block);
}
+ page_cursor->block = new_block;
+ page_cursor->index = index;
+
if (tuple) {
ut_ad(dtuple_check_typed(tuple));
/* Reposition the cursor to the child node */
ulint low_match = 0, up_match = 0;
- if (page_cur_search_with_match(new_block, index, tuple,
- PAGE_CUR_LE,
+ if (page_cur_search_with_match(tuple, PAGE_CUR_LE,
&up_match, &low_match,
page_cursor, nullptr)) {
if (err) {
@@ -2029,8 +2018,7 @@ btr_root_raise_and_insert(
return nullptr;
}
} else {
- /* Set cursor to first record on child node */
- page_cur_set_before_first(new_block, page_cursor);
+ page_cursor->rec = page_get_infimum_rec(new_block->page.frame);
}
/* Split the child and insert tuple */
@@ -2061,10 +2049,10 @@ rec_t* btr_page_get_split_rec_to_left(const btr_cur_t* cursor)
So, we can only assert that when the metadata record exists,
index->is_instant() must hold. */
ut_ad(!page_is_leaf(page) || page_has_prev(page)
- || cursor->index->is_instant()
+ || cursor->index()->is_instant()
|| !(rec_get_info_bits(page_rec_get_next_const(
page_get_infimum_rec(page)),
- cursor->index->table->not_redundant())
+ cursor->index()->table->not_redundant())
& REC_INFO_MIN_REC_FLAG));
const rec_t* infimum = page_get_infimum_rec(page);
@@ -2157,14 +2145,14 @@ btr_page_get_split_rec(
page = btr_cur_get_page(cursor);
- insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
+ insert_size = rec_get_converted_size(cursor->index(), tuple, n_ext);
free_space = page_get_free_space_of_empty(page_is_comp(page));
page_zip = btr_cur_get_page_zip(cursor);
if (page_zip) {
/* Estimate the free space of an empty compressed page. */
ulint free_space_zip = page_zip_empty_size(
- cursor->index->n_fields,
+ cursor->index()->n_fields,
page_zip_get_size(page_zip));
if (free_space > (ulint) free_space_zip) {
@@ -2209,9 +2197,10 @@ btr_page_get_split_rec(
/* Include tuple */
incl_data += insert_size;
} else {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- page_is_leaf(page)
- ? cursor->index->n_core_fields
+ offsets = rec_get_offsets(rec, cursor->index(),
+ offsets, page_is_leaf(page)
+ ? cursor->index()
+ ->n_core_fields
: 0,
ULINT_UNDEFINED, &heap);
incl_data += rec_offs_size(offsets);
@@ -2262,7 +2251,7 @@ btr_page_insert_fits(
on upper half-page, or NULL if
tuple to be inserted should be first */
rec_offs** offsets,/*!< in: rec_get_offsets(
- split_rec, cursor->index); out: garbage */
+ split_rec, cursor->index()); out: garbage */
const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext, /*!< in: number of externally stored columns */
mem_heap_t** heap) /*!< in: temporary memory heap */
@@ -2280,9 +2269,9 @@ btr_page_insert_fits(
ut_ad(!split_rec
|| !page_is_comp(page) == !rec_offs_comp(*offsets));
ut_ad(!split_rec
- || rec_offs_validate(split_rec, cursor->index, *offsets));
+ || rec_offs_validate(split_rec, cursor->index(), *offsets));
- insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
+ insert_size = rec_get_converted_size(cursor->index(), tuple, n_ext);
free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */
@@ -2320,9 +2309,9 @@ got_rec:
/* In this loop we calculate the amount of reserved
space after rec is removed from page. */
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
page_is_leaf(page)
- ? cursor->index->n_core_fields
+ ? cursor->index()->n_core_fields
: 0,
ULINT_UNDEFINED, heap);
@@ -2380,8 +2369,9 @@ btr_insert_on_non_leaf_level(
flags |= BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
| BTR_NO_UNDO_LOG_FLAG;
+ cursor.page_cur.index = index;
- dberr_t err = btr_cur_search_to_nth_level(index, level, tuple, mode,
+ dberr_t err = btr_cur_search_to_nth_level(level, tuple, mode,
BTR_CONT_MODIFY_TREE,
&cursor, mtr);
ut_ad(cursor.flag == BTR_CUR_BINARY);
@@ -2437,8 +2427,8 @@ btr_attach_half_pages(
{
dtuple_t* node_ptr_upper;
mem_heap_t* heap;
- buf_block_t* prev_block = NULL;
- buf_block_t* next_block = NULL;
+ buf_block_t* prev_block = nullptr;
+ buf_block_t* next_block = nullptr;
buf_block_t* lower_block;
buf_block_t* upper_block;
@@ -2457,9 +2447,12 @@ btr_attach_half_pages(
lower_block = new_block;
upper_block = block;
+ cursor.page_cur.block = block;
+ cursor.page_cur.index = index;
+
/* Look up the index for the node pointer to page */
- offsets = btr_page_get_father_block(NULL, heap, index,
- block, mtr, &cursor);
+ offsets = btr_page_get_father_block(nullptr, heap, mtr,
+ &cursor);
/* Replace the address of the old child node (= page) with the
address of the new lower half */
@@ -2582,9 +2575,9 @@ btr_page_tuple_smaller(
return false;
}
- *offsets = rec_get_offsets(first_rec, cursor->index, *offsets,
+ *offsets = rec_get_offsets(first_rec, cursor->index(), *offsets,
page_is_leaf(block->page.frame)
- ? cursor->index->n_core_fields : 0,
+ ? cursor->index()->n_core_fields : 0,
n_uniq, heap);
return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0);
@@ -2618,7 +2611,7 @@ btr_insert_into_right_sibling(
page_t* page = buf_block_get_frame(block);
const uint32_t next_page_no = btr_page_get_next(page);
- ut_ad(mtr->memo_contains_flagged(&cursor->index->lock,
+ ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(heap);
@@ -2637,7 +2630,7 @@ btr_insert_into_right_sibling(
rec_t* rec = nullptr;
ulint max_size;
- next_block = btr_block_get(*cursor->index, next_page_no, RW_X_LATCH,
+ next_block = btr_block_get(*cursor->index(), next_page_no, RW_X_LATCH,
page_is_leaf(page), mtr);
if (UNIV_UNLIKELY(!next_block)) {
return nullptr;
@@ -2645,14 +2638,17 @@ btr_insert_into_right_sibling(
next_page = buf_block_get_frame(next_block);
const bool is_leaf = page_is_leaf(next_page);
- if (!btr_page_get_father(cursor->index, next_block, mtr,
- &next_father_cursor)) {
+ next_page_cursor.index = cursor->index();
+ next_page_cursor.block = next_block;
+ next_father_cursor.page_cur = next_page_cursor;
+
+ if (!btr_page_get_father(mtr, &next_father_cursor)) {
return nullptr;
}
ulint up_match = 0, low_match = 0;
- if (page_cur_search_with_match(next_block, cursor->index, tuple,
+ if (page_cur_search_with_match(tuple,
PAGE_CUR_LE, &up_match, &low_match,
&next_page_cursor, nullptr)) {
return nullptr;
@@ -2661,19 +2657,18 @@ btr_insert_into_right_sibling(
max_size = page_get_max_insert_size_after_reorganize(next_page, 1);
/* Extends gap lock for the next page */
- if (is_leaf && cursor->index->has_locking()) {
+ if (is_leaf && cursor->index()->has_locking()) {
lock_update_node_pointer(block, next_block);
}
- rec = page_cur_tuple_insert(
- &next_page_cursor, tuple, cursor->index, offsets, &heap,
- n_ext, mtr);
+ rec = page_cur_tuple_insert(&next_page_cursor, tuple, offsets, &heap,
+ n_ext, mtr);
if (!rec) {
if (is_leaf
&& next_block->page.zip.ssize
- && !dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()) {
+ && !dict_index_is_clust(cursor->index())
+ && !cursor->index()->table->is_temporary()) {
/* Reset the IBUF_BITMAP_FREE bits, because
page_cur_tuple_insert() will have attempted page
reorganize before failing. */
@@ -2707,19 +2702,19 @@ btr_insert_into_right_sibling(
}
dtuple_t* node_ptr = dict_index_build_node_ptr(
- cursor->index, rec, next_block->page.id().page_no(),
+ cursor->index(), rec, next_block->page.id().page_no(),
heap, level);
- if (btr_insert_on_non_leaf_level(flags, cursor->index, level + 1,
+ if (btr_insert_on_non_leaf_level(flags, cursor->index(), level + 1,
node_ptr, mtr) != DB_SUCCESS) {
return nullptr;
}
- ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
if (is_leaf
- && !dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()) {
+ && !dict_index_is_clust(cursor->index())
+ && !cursor->index()->table->is_temporary()) {
/* Update the free bits of the B-tree page in the
insert buffer bitmap. */
@@ -2863,7 +2858,7 @@ btr_page_split_and_insert(
ut_ad(*err == DB_SUCCESS);
ut_ad(dtuple_check_typed(tuple));
- if (cursor->index->is_spatial()) {
+ if (cursor->index()->is_spatial()) {
/* Split rtree page and update parent */
return rtr_page_split_and_insert(flags, cursor, offsets, heap,
tuple, n_ext, mtr, err);
@@ -2872,17 +2867,18 @@ btr_page_split_and_insert(
if (!*heap) {
*heap = mem_heap_create(1024);
}
- n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
+ n_uniq = dict_index_get_n_unique_in_tree(cursor->index());
func_start:
mem_heap_empty(*heap);
*offsets = NULL;
- ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK
+ ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
+ MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
- ut_ad(!dict_index_is_online_ddl(cursor->index)
+ ut_ad(!dict_index_is_online_ddl(cursor->index())
|| (flags & BTR_CREATE_FLAG)
- || dict_index_is_clust(cursor->index));
- ut_ad(cursor->index->lock.have_u_or_x());
+ || dict_index_is_clust(cursor->index()));
+ ut_ad(cursor->index()->lock.have_u_or_x());
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
@@ -2941,7 +2937,7 @@ func_start:
got_split_rec:
/* 2. Allocate a new page to the index */
const uint16_t page_level = btr_page_get_level(page);
- new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
+ new_block = btr_page_alloc(cursor->index(), hint_page_no, direction,
page_level, mtr, mtr, err);
if (!new_block) {
@@ -2956,13 +2952,13 @@ got_split_rec:
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_page + FIL_PAGE_PREV, 0, 4);
}
- btr_page_create(new_block, new_page_zip, cursor->index,
+ btr_page_create(new_block, new_page_zip, cursor->index(),
page_level, mtr);
/* Only record the leaf level page splits. */
if (!page_level) {
- cursor->index->stat_defrag_n_page_split ++;
- cursor->index->stat_defrag_modified_counter ++;
- btr_defragment_save_defrag_stats_if_needed(cursor->index);
+ cursor->index()->stat_defrag_n_page_split ++;
+ cursor->index()->stat_defrag_modified_counter ++;
+ btr_defragment_save_defrag_stats_if_needed(cursor->index());
}
/* 3. Calculate the first record on the upper half-page, and the
@@ -2972,9 +2968,10 @@ got_split_rec:
if (split_rec) {
first_rec = move_limit = split_rec;
- *offsets = rec_get_offsets(split_rec, cursor->index, *offsets,
- page_is_leaf(page)
- ? cursor->index->n_core_fields : 0,
+ *offsets = rec_get_offsets(split_rec, cursor->index(),
+ *offsets, page_is_leaf(page)
+ ? cursor->index()->n_core_fields
+ : 0,
n_uniq, heap);
insert_left = cmp_dtuple_rec(tuple, split_rec, *offsets) < 0;
@@ -3004,9 +3001,9 @@ insert_empty:
ut_ad(!insert_left);
buf = UT_NEW_ARRAY_NOKEY(
byte,
- rec_get_converted_size(cursor->index, tuple, n_ext));
+ rec_get_converted_size(cursor->index(), tuple, n_ext));
- first_rec = rec_convert_dtuple_to_rec(buf, cursor->index,
+ first_rec = rec_convert_dtuple_to_rec(buf, cursor->index(),
tuple, n_ext);
goto insert_move_limit;
}
@@ -3014,7 +3011,7 @@ insert_empty:
/* 4. Do first the modifications in the tree structure */
/* FIXME: write FIL_PAGE_PREV,FIL_PAGE_NEXT in new_block earlier! */
- *err = btr_attach_half_pages(flags, cursor->index, block,
+ *err = btr_attach_half_pages(flags, cursor->index(), block,
first_rec, new_block, direction, mtr);
if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
@@ -3036,11 +3033,10 @@ insert_empty:
if (!srv_read_only_mode
&& insert_will_fit
&& page_is_leaf(page)
- && !dict_index_is_online_ddl(cursor->index)) {
-
- mtr->memo_release(&cursor->index->lock,
- MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
-
+ && !dict_index_is_online_ddl(cursor->index())) {
+#if 0 // FIXME: this used to be a no-op, and may cause trouble if enabled
+ mtr->release(cursor->index()->lock);
+#endif
/* NOTE: We cannot release root block latch here, because it
has segment header and already modified in most of cases.*/
}
@@ -3055,7 +3051,8 @@ insert_empty:
#endif /* UNIV_ZIP_COPY */
|| (*err = page_move_rec_list_start(new_block, block,
move_limit,
- cursor->index, mtr))) {
+ cursor->index(),
+ mtr))) {
if (*err != DB_FAIL) {
return nullptr;
}
@@ -3067,12 +3064,12 @@ insert_empty:
as appropriate. Deleting will always succeed. */
ut_a(new_page_zip);
- page_zip_copy_recs(new_block,
- page_zip, page, cursor->index, mtr);
+ page_zip_copy_recs(new_block, page_zip, page,
+ cursor->index(), mtr);
*err = page_delete_rec_list_end(move_limit
- page + new_page,
new_block,
- cursor->index,
+ cursor->index(),
ULINT_UNDEFINED,
ULINT_UNDEFINED, mtr);
if (*err != DB_SUCCESS) {
@@ -3080,7 +3077,7 @@ insert_empty:
}
/* Update the lock table and possible hash index. */
- if (cursor->index->has_locking()) {
+ if (cursor->index()->has_locking()) {
lock_move_rec_list_start(
new_block, block, move_limit,
new_page + PAGE_NEW_INFIMUM);
@@ -3092,13 +3089,13 @@ insert_empty:
/* Delete the records from the source page. */
page_delete_rec_list_start(move_limit, block,
- cursor->index, mtr);
+ cursor->index(), mtr);
}
left_block = new_block;
right_block = block;
- if (cursor->index->has_locking()) {
+ if (cursor->index()->has_locking()) {
lock_update_split_left(right_block, left_block);
}
} else {
@@ -3110,7 +3107,7 @@ insert_empty:
#endif /* UNIV_ZIP_COPY */
|| (*err = page_move_rec_list_end(new_block, block,
move_limit,
- cursor->index, mtr))) {
+ cursor->index(), mtr))) {
if (*err != DB_FAIL) {
return nullptr;
}
@@ -3122,14 +3119,14 @@ insert_empty:
as appropriate. Deleting will always succeed. */
ut_a(new_page_zip);
- page_zip_copy_recs(new_block,
- page_zip, page, cursor->index, mtr);
+ page_zip_copy_recs(new_block, page_zip, page,
+ cursor->index(), mtr);
page_delete_rec_list_start(move_limit - page
+ new_page, new_block,
- cursor->index, mtr);
+ cursor->index(), mtr);
/* Update the lock table and possible hash index. */
- if (cursor->index->has_locking()) {
+ if (cursor->index()->has_locking()) {
lock_move_rec_list_end(new_block, block,
move_limit);
}
@@ -3140,7 +3137,7 @@ insert_empty:
/* Delete the records from the source page. */
*err = page_delete_rec_list_end(move_limit, block,
- cursor->index,
+ cursor->index(),
ULINT_UNDEFINED,
ULINT_UNDEFINED, mtr);
if (*err != DB_SUCCESS) {
@@ -3151,15 +3148,16 @@ insert_empty:
left_block = block;
right_block = new_block;
- if (cursor->index->has_locking()) {
+ if (cursor->index()->has_locking()) {
lock_update_split_right(right_block, left_block);
}
}
#ifdef UNIV_ZIP_DEBUG
if (page_zip) {
- ut_a(page_zip_validate(page_zip, page, cursor->index));
- ut_a(page_zip_validate(new_page_zip, new_page, cursor->index));
+ ut_a(page_zip_validate(page_zip, page, cursor->index()));
+ ut_a(page_zip_validate(new_page_zip, new_page,
+ cursor->index()));
}
#endif /* UNIV_ZIP_DEBUG */
@@ -3174,17 +3172,18 @@ insert_empty:
/* 7. Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
+ page_cursor->block = insert_block;
ulint up_match = 0, low_match = 0;
- if (page_cur_search_with_match(insert_block, cursor->index, tuple,
+ if (page_cur_search_with_match(tuple,
PAGE_CUR_LE, &up_match, &low_match,
page_cursor, nullptr)) {
*err = DB_CORRUPTION;
return nullptr;
}
- rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
+ rec = page_cur_tuple_insert(page_cursor, tuple,
offsets, heap, n_ext, mtr);
#ifdef UNIV_ZIP_DEBUG
@@ -3214,13 +3213,13 @@ insert_empty:
goto insert_failed;
}
- *err = btr_page_reorganize(page_cursor, cursor->index, mtr);
+ *err = btr_page_reorganize(page_cursor, mtr);
if (*err != DB_SUCCESS) {
return nullptr;
}
- rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
+ rec = page_cur_tuple_insert(page_cursor, tuple,
offsets, heap, n_ext, mtr);
if (rec == NULL) {
@@ -3228,8 +3227,8 @@ insert_empty:
start of the function for a new split */
insert_failed:
/* We play safe and reset the free bits for new_page */
- if (!dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()) {
+ if (!dict_index_is_clust(page_cursor->index)
+ && !page_cursor->index->table->is_temporary()) {
ibuf_reset_free_bits(new_block);
ibuf_reset_free_bits(block);
}
@@ -3246,8 +3245,8 @@ func_exit:
/* Insert fit on the page: update the free bits for the
left and right pages in the same mtr */
- if (!dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()
+ if (!dict_index_is_clust(page_cursor->index)
+ && !page_cursor->index->table->is_temporary()
&& page_is_leaf(page)) {
ibuf_update_free_bits_for_two_pages_low(
@@ -3256,10 +3255,12 @@ func_exit:
MONITOR_INC(MONITOR_INDEX_SPLIT);
- ut_ad(page_validate(buf_block_get_frame(left_block), cursor->index));
- ut_ad(page_validate(buf_block_get_frame(right_block), cursor->index));
+ ut_ad(page_validate(buf_block_get_frame(left_block),
+ page_cursor->index));
+ ut_ad(page_validate(buf_block_get_frame(right_block),
+ page_cursor->index));
- ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(!rec || rec_offs_validate(rec, page_cursor->index, *offsets));
return(rec);
}
@@ -3358,14 +3359,14 @@ btr_lift_page_up(
* (REC_OFFS_HEADER_SIZE + 1 + 1
+ unsigned(index->n_fields)));
buf_block_t* b;
+ cursor.page_cur.index = index;
+ cursor.page_cur.block = block;
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
offsets = rtr_page_get_father_block(
- NULL, heap, index, block, mtr,
- NULL, &cursor);
+ nullptr, heap, mtr, nullptr, &cursor);
} else {
offsets = btr_page_get_father_block(offsets, heap,
- index, block,
mtr, &cursor);
}
father_block = btr_cur_get_block(&cursor);
@@ -3382,14 +3383,12 @@ btr_lift_page_up(
b->page.id().page_no() != root_page_no; ) {
ut_a(n_blocks < BTR_MAX_LEVELS);
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
offsets = rtr_page_get_father_block(
- NULL, heap, index, b, mtr,
- NULL, &cursor);
+ nullptr, heap, mtr, nullptr, &cursor);
} else {
offsets = btr_page_get_father_block(offsets,
heap,
- index, b,
mtr,
&cursor);
}
@@ -3586,10 +3585,12 @@ btr_compress(
page_is_comp(page))));
heap = mem_heap_create(100);
+ father_cursor.page_cur.index = index;
+ father_cursor.page_cur.block = block;
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
offsets = rtr_page_get_father_block(
- NULL, heap, index, block, mtr, cursor, &father_cursor);
+ NULL, heap, mtr, cursor, &father_cursor);
ut_ad(cursor->page_cur.block->page.id() == block->page.id());
rec_t* my_rec = father_cursor.page_cur.rec;
@@ -3600,18 +3601,26 @@ btr_compress(
<< page_no << "instead of "
<< block->page.id().page_no();
offsets = btr_page_get_father_block(
- NULL, heap, index, block, mtr, &father_cursor);
+ NULL, heap, mtr, &father_cursor);
}
} else {
offsets = btr_page_get_father_block(
- NULL, heap, index, block, mtr, &father_cursor);
+ NULL, heap, mtr, &father_cursor);
}
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) {
+ corrupted:
err = DB_CORRUPTION;
- goto err_exit;
+ err_exit:
+ /* We play it safe and reset the free bits. */
+ if (merge_block && merge_block->zip_size()
+ && page_is_leaf(merge_block->page.frame)
+ && !index->is_clust()) {
+ ibuf_reset_free_bits(merge_block);
+ }
+ goto func_exit;
}
}
@@ -3620,7 +3629,23 @@ btr_compress(
to the father */
merge_block = btr_lift_page_up(index, block, mtr, &err);
- goto func_exit;
+success:
+ if (adjust) {
+ ut_ad(nth_rec > 0);
+ if (rec_t* nth
+ = page_rec_get_nth(merge_block->page.frame,
+ nth_rec)) {
+ btr_cur_position(index, nth,
+ merge_block, cursor);
+ } else {
+ goto corrupted;
+ }
+ }
+
+ MONITOR_INC(MONITOR_INDEX_MERGE_SUCCESSFUL);
+func_exit:
+ mem_heap_free(heap);
+ DBUG_RETURN(err);
}
ut_d(leftmost_child =
@@ -3656,8 +3681,7 @@ cannot_merge:
: FIL_PAGE_PREV),
block->page.frame
+ FIL_PAGE_OFFSET, 4))) {
- err = DB_CORRUPTION;
- goto err_exit;
+ goto corrupted;
}
ut_ad(page_validate(merge_page, index));
@@ -3673,9 +3697,12 @@ cannot_merge:
}
#endif /* UNIV_ZIP_DEBUG */
+ btr_cur_t cursor2;
+ cursor2.page_cur.index = index;
+ cursor2.page_cur.block = merge_block;
+
/* Move records to the merge page */
if (is_left) {
- btr_cur_t cursor2;
rtr_mbr_t new_mbr;
rec_offs* offsets2 = NULL;
@@ -3685,8 +3712,7 @@ cannot_merge:
page */
if (!rtr_check_same_block(
index, &cursor2,
- btr_cur_get_block(&father_cursor),
- merge_block, heap)) {
+ btr_cur_get_block(&father_cursor), heap)) {
is_left = false;
goto retry;
}
@@ -3727,7 +3753,7 @@ cannot_merge:
const page_id_t id{block->page.id()};
- if (dict_index_is_spatial(index)) {
+ if (index->is_spatial()) {
rec_t* my_rec = father_cursor.page_cur.rec;
ulint page_no = btr_node_ptr_get_child_page_no(
@@ -3763,8 +3789,7 @@ cannot_merge:
if (adjust) {
ulint n = page_rec_get_n_recs_before(orig_pred);
if (UNIV_UNLIKELY(!n || n == ULINT_UNDEFINED)) {
- err = DB_CORRUPTION;
- goto err_exit;
+ goto corrupted;
}
nth_rec += n;
}
@@ -3772,22 +3797,16 @@ cannot_merge:
rec_t* orig_succ;
ibool compressed;
dberr_t err;
- btr_cur_t cursor2;
- /* father cursor pointing to node ptr
- of the right sibling */
byte fil_page_prev[4];
- if (dict_index_is_spatial(index)) {
- cursor2.rtr_info = NULL;
-
+ if (index->is_spatial()) {
/* For spatial index, we disallow merge of blocks
with different parents, since the merge would need
to update entry (for MBR and Primary key) in the
parent of block being merged */
if (!rtr_check_same_block(
index, &cursor2,
- btr_cur_get_block(&father_cursor),
- merge_block, heap)) {
+ btr_cur_get_block(&father_cursor), heap)) {
goto cannot_merge;
}
@@ -3795,8 +3814,7 @@ cannot_merge:
necessary in recursive page merge. */
cursor2.rtr_info = cursor->rtr_info;
cursor2.tree_height = cursor->tree_height;
- } else if (!btr_page_get_father(index, merge_block, mtr,
- &cursor2)) {
+ } else if (!btr_page_get_father(mtr, &cursor2)) {
goto cannot_merge;
}
@@ -3814,7 +3832,7 @@ cannot_merge:
orig_succ = page_copy_rec_list_end(merge_block, block,
page_get_infimum_rec(page),
- cursor->index, mtr, &err);
+ cursor->index(), mtr, &err);
if (!orig_succ) {
ut_a(merge_page_zip);
@@ -3983,33 +4001,10 @@ cannot_merge:
if (err == DB_SUCCESS) {
ut_ad(leftmost_child
|| btr_check_node_ptr(index, merge_block, mtr));
-func_exit:
- if (adjust) {
- ut_ad(nth_rec > 0);
- if (rec_t* nth
- = page_rec_get_nth(merge_block->page.frame,
- nth_rec)) {
- btr_cur_position(index, nth,
- merge_block, cursor);
- } else {
- err = DB_CORRUPTION;
- goto err_exit;
- }
- }
-
- MONITOR_INC(MONITOR_INDEX_MERGE_SUCCESSFUL);
+ goto success;
} else {
-err_exit:
- /* We play it safe and reset the free bits. */
- if (merge_block && merge_block->zip_size()
- && page_is_leaf(merge_block->page.frame)
- && !index->is_clust()) {
- ibuf_reset_free_bits(merge_block);
- }
+ goto err_exit;
}
-
- mem_heap_free(heap);
- DBUG_RETURN(err);
}
/*************************************************************//**
@@ -4051,16 +4046,17 @@ btr_discard_only_page_on_level(
ut_ad(block->page.id().space() == index->table->space->id);
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
btr_search_drop_page_hash_index(block);
+ cursor.page_cur.index = index;
+ cursor.page_cur.block = block;
if (index->is_spatial()) {
/* Check any concurrent search having this page */
rtr_check_discard_page(index, NULL, block);
- if (!rtr_page_get_father(index, block, mtr, nullptr,
- &cursor)) {
+ if (!rtr_page_get_father(mtr, nullptr, &cursor)) {
return;
}
} else {
- if (!btr_page_get_father(index, block, mtr, &cursor)) {
+ if (!btr_page_get_father(mtr, &cursor)) {
return;
}
}
@@ -4111,11 +4107,11 @@ btr_discard_only_page_on_level(
if (rec) {
page_cur_t cur;
page_cur_set_before_first(block, &cur);
+ cur.index = index;
DBUG_ASSERT(index->table->instant);
DBUG_ASSERT(rec_is_alter_metadata(rec, *index));
btr_set_instant(block, *index, mtr);
- rec = page_cur_insert_rec_low(&cur, index, rec,
- offsets, mtr);
+ rec = page_cur_insert_rec_low(&cur, rec, offsets, mtr);
ut_ad(rec);
mem_heap_free(heap);
} else if (index->is_instant()) {
@@ -4150,6 +4146,7 @@ btr_discard_page(
block = btr_cur_get_block(cursor);
index = btr_cur_get_index(cursor);
+ parent_cursor.page_cur = cursor->page_cur;
ut_ad(dict_index_get_page(index) != block->page.id().page_no());
@@ -4160,8 +4157,8 @@ btr_discard_page(
MONITOR_INC(MONITOR_INDEX_DISCARD);
if (index->is_spatial()
- ? !rtr_page_get_father(index, block, mtr, cursor, &parent_cursor)
- : !btr_page_get_father(index, block, mtr, &parent_cursor)) {
+ ? !rtr_page_get_father(mtr, cursor, &parent_cursor)
+ : !btr_page_get_father(mtr, &parent_cursor)) {
return DB_CORRUPTION;
}
@@ -4453,14 +4450,16 @@ btr_check_node_ptr(
return(TRUE);
}
+ cursor.page_cur.index = index;
+ cursor.page_cur.block = block;
+
heap = mem_heap_create(256);
if (dict_index_is_spatial(index)) {
- offsets = rtr_page_get_father_block(NULL, heap, index, block, mtr,
+ offsets = rtr_page_get_father_block(NULL, heap, mtr,
NULL, &cursor);
} else {
- offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
- &cursor);
+ offsets = btr_page_get_father_block(NULL, heap, mtr, &cursor);
}
if (page_is_leaf(page)) {
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 223d903c803..013cd13102c 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -827,7 +827,6 @@ PageBulk::storeExt(
btr_pcur_t btr_pcur;
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
btr_pcur.latch_mode = BTR_MODIFY_LEAF;
- btr_pcur.btr_cur.index = m_index;
btr_pcur.btr_cur.page_cur.index = m_index;
btr_pcur.btr_cur.page_cur.rec = m_cur_rec;
btr_pcur.btr_cur.page_cur.offsets = offsets;
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 7954c216c86..c6f11aa518f 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -204,15 +204,15 @@ btr_cur_latch_leaves(
compile_time_assert(int(MTR_MEMO_PAGE_S_FIX) == int(RW_S_LATCH));
compile_time_assert(int(MTR_MEMO_PAGE_X_FIX) == int(RW_X_LATCH));
compile_time_assert(int(MTR_MEMO_PAGE_SX_FIX) == int(RW_SX_LATCH));
- ut_ad(block->page.id().space() == cursor->index->table->space->id);
+ ut_ad(block->page.id().space() == cursor->index()->table->space->id);
ut_ad(block->page.in_file());
ut_ad(srv_read_only_mode
- || mtr->memo_contains_flagged(&cursor->index->lock,
+ || mtr->memo_contains_flagged(&cursor->index()->lock,
MTR_MEMO_S_LOCK
| MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
auto rtr_info = cursor->rtr_info;
- if (UNIV_LIKELY_NULL(rtr_info) && !cursor->index->is_spatial()) {
+ if (UNIV_LIKELY_NULL(rtr_info) && !cursor->index()->is_spatial()) {
rtr_info = nullptr;
}
@@ -249,7 +249,7 @@ latch_block:
case BTR_MODIFY_TREE:
/* It is exclusive for other operations which calls
btr_page_set_prev() */
- ut_ad(mtr->memo_contains_flagged(&cursor->index->lock,
+ ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
save = mtr->get_savepoint();
@@ -258,7 +258,7 @@ latch_block:
if (left_page_no != FIL_NULL) {
buf_block_t *b = btr_block_get(
- *cursor->index, left_page_no, RW_X_LATCH,
+ *cursor->index(), left_page_no, RW_X_LATCH,
true, mtr);
if (latch_leaves) {
@@ -299,7 +299,7 @@ latch_block:
save = mtr->get_savepoint();
buf_block_t* b = btr_block_get(
- *cursor->index, right_page_no, RW_X_LATCH,
+ *cursor->index(), right_page_no, RW_X_LATCH,
true, mtr);
if (latch_leaves) {
latch_leaves->savepoints[2] = save;
@@ -331,7 +331,8 @@ latch_block:
if (left_page_no != FIL_NULL) {
save = mtr->get_savepoint();
cursor->left_block = btr_block_get(
- *cursor->index, left_page_no, mode, true, mtr);
+ *cursor->index(), left_page_no,
+ mode, true, mtr);
if (latch_leaves) {
latch_leaves->savepoints[0] = save;
latch_leaves->blocks[0] = cursor->left_block;
@@ -340,7 +341,7 @@ latch_block:
goto latch_block;
case BTR_CONT_MODIFY_TREE:
- ut_ad(cursor->index->is_spatial());
+ ut_ad(cursor->index()->is_spatial());
return;
}
@@ -756,8 +757,8 @@ btr_cur_optimistic_latch_leaves(
case BTR_MODIFY_LEAF:
return(buf_page_optimistic_get(*latch_mode, block,
modify_clock, mtr));
- case BTR_SEARCH_PREV:
- case BTR_MODIFY_PREV:
+ case BTR_SEARCH_PREV: /* btr_pcur_move_backward_from_page() */
+ case BTR_MODIFY_PREV: /* Ditto, or ibuf_insert() */
uint32_t curr_page_no, left_page_no;
{
transactional_shared_lock_guard<block_lock> g{
@@ -779,18 +780,17 @@ btr_cur_optimistic_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_block = buf_page_get_gen(
- page_id_t(cursor->index->table->space_id,
+ page_id_t(cursor->index()->table->space_id,
left_page_no),
- cursor->index->table->space->zip_size(),
+ cursor->index()->table->space->zip_size(),
mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr);
if (cursor->left_block
&& btr_page_get_next(
cursor->left_block->page.frame)
!= curr_page_no) {
- /* release the left block */
- btr_leaf_page_release(
- cursor->left_block, mode, mtr);
+release_left_block:
+ mtr->release_last_page();
return false;
}
} else {
@@ -807,17 +807,14 @@ btr_cur_optimistic_latch_leaves(
ut_ad(2 <= block->page.buf_fix_count());
*latch_mode = btr_latch_mode(mode);
return(true);
- } else {
- /* release the block and decrement of
- buf_fix_count which was incremented
- in buf_page_optimistic_get() */
- btr_leaf_page_release(block, mode, mtr);
}
+
+ mtr->release_last_page();
}
ut_ad(block->page.buf_fix_count());
if (cursor->left_block) {
- btr_leaf_page_release(cursor->left_block, mode, mtr);
+ goto release_left_block;
}
}
@@ -1212,7 +1209,6 @@ If mode is PAGE_CUR_LE , cursor is left at the place where an insert of the
search tuple should be performed in the B-tree. InnoDB does an insert
immediately after the cursor. Thus, the cursor may end up on a user record,
or on a page infimum record.
-@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@@ -1231,7 +1227,7 @@ or on a page infimum record.
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@return DB_SUCCESS on success or error code otherwise */
TRANSACTIONAL_TARGET
-dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
+dberr_t btr_cur_search_to_nth_level(ulint level,
const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
@@ -1271,6 +1267,7 @@ dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
bool rtree_parent_modified = false;
bool mbr_adj = false;
bool found = false;
+ dict_index_t * const index = cursor->index();
DBUG_ENTER("btr_cur_search_to_nth_level");
@@ -1358,7 +1355,6 @@ dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
ut_ad(autoinc == 0 || level == 0);
cursor->flag = BTR_CUR_BINARY;
- cursor->index = index;
#ifndef BTR_CUR_ADAPT
guess = NULL;
@@ -1470,6 +1466,7 @@ x_latch_index:
latch_mode);
page_cursor = btr_cur_get_page_cur(cursor);
+ page_cursor->index = index;
const ulint zip_size = index->table->space->zip_size();
@@ -1845,6 +1842,8 @@ retry_page_get:
}
}
+ page_cursor->block = block;
+
if (dict_index_is_spatial(index) && page_mode >= PAGE_CUR_CONTAIN) {
ut_ad(need_path);
found = rtr_cur_search_with_match(
@@ -1881,7 +1880,7 @@ retry_page_get:
We only need the byte prefix comparison for the purpose
of updating the adaptive hash index. */
if (page_cur_search_with_match_bytes(
- block, index, tuple, page_mode, &up_match, &up_bytes,
+ tuple, page_mode, &up_match, &up_bytes,
&low_match, &low_bytes, page_cursor)) {
err = DB_CORRUPTION;
goto func_exit;
@@ -1891,7 +1890,7 @@ retry_page_get:
/* Search for complete index fields. */
up_bytes = low_bytes = 0;
if (page_cur_search_with_match(
- block, index, tuple, page_mode, &up_match,
+ tuple, page_mode, &up_match,
&low_match, page_cursor,
need_path ? cursor->rtr_info : nullptr)) {
err = DB_CORRUPTION;
@@ -2140,15 +2139,15 @@ need_opposite_intention:
/* we should sx-latch root page, if released already.
It contains seg_header. */
if (n_releases > 0) {
- mtr_block_sx_latch_at_savepoint(
- mtr, tree_savepoints[0],
+ mtr->sx_latch_at_savepoint(
+ tree_savepoints[0],
tree_blocks[0]);
}
/* x-latch the branch blocks not released yet. */
for (ulint i = n_releases; i <= n_blocks; i++) {
- mtr_block_x_latch_at_savepoint(
- mtr, tree_savepoints[i],
+ mtr->x_latch_at_savepoint(
+ tree_savepoints[i],
tree_blocks[i]);
}
}
@@ -2212,8 +2211,9 @@ need_opposite_intention:
? cursor->rtr_info : NULL;
for (ulint i = 0; i < n_blocks; i++) {
+ page_cursor->block = tree_blocks[i];
if (page_cur_search_with_match(
- tree_blocks[i], index, tuple,
+ tuple,
page_mode, &up_match,
&low_match, page_cursor,
rtr_info)) {
@@ -2415,10 +2415,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
{
ulint node_ptr_max_size= srv_page_size / 2;
btr_intention_t lock_intention;
- buf_block_t *tree_blocks[BTR_MAX_LEVELS]; // FIXME: just use mtr->m_memo
- ulint tree_savepoints[BTR_MAX_LEVELS];
ulint n_blocks= 0;
- ulint n_releases= 0;
mem_heap_t *heap= nullptr;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs *offsets= offsets_;
@@ -2453,7 +2450,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
/* Most of delete-intended operations are purging. Free blocks
and read IO bandwidth should be prioritized for them, when the
history list is growing huge. */
- savepoint+= sizeof(mtr_memo_slot_t);
+ savepoint++;
if (lock_intention == BTR_INTENTION_DELETE
&& buf_pool.n_pend_reads
&& trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
@@ -2469,7 +2466,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
if (latch_by_caller)
break;
ut_ad(latch_mode != BTR_SEARCH_TREE);
- savepoint+= sizeof(mtr_memo_slot_t);
+ savepoint++;
mtr_s_lock_index(index, mtr);
}
@@ -2478,9 +2475,9 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
const rw_lock_type_t root_leaf_rw_latch=
btr_cur_latch_for_root_leaf(latch_mode);
- this->index = index;
+ page_cur.index = index;
- page_id_t page_id(index->table->space_id, index->page);
+ uint32_t page= index->page;
const auto zip_size= index->table->space->zip_size();
if (root_leaf_rw_latch == RW_X_LATCH)
@@ -2489,19 +2486,16 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
for (ulint height= ULINT_UNDEFINED;;)
{
ut_ad(n_blocks < BTR_MAX_LEVELS);
-#if 0 // FIXME: encryption.innodb_onlinealter_encryption innodb.alter_algorithm
- ut_ad(savepoint + n_blocks * sizeof(mtr_memo_slot_t) == mtr->get_savepoint());
-#endif
- tree_savepoints[n_blocks]= mtr->get_savepoint();
+ ut_ad(savepoint + n_blocks == mtr->get_savepoint());
const rw_lock_type_t rw_latch= height && latch_mode != BTR_MODIFY_TREE
? upper_rw_latch
: RW_NO_LATCH;
- buf_block_t *block= buf_page_get_gen(page_id, zip_size, rw_latch, nullptr,
- BUF_GET, mtr, &err,
- !height && !index->is_clust());
+ buf_block_t* block=
+ btr_block_get(*index, page, rw_latch, !height && !index->is_clust(), mtr,
+ &err);
+
ut_ad(!block == (err != DB_SUCCESS));
- tree_blocks[n_blocks]= block;
if (!block)
{
@@ -2510,20 +2504,17 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
break;
}
- const page_t *page= buf_block_get_frame(block);
-
if (first)
page_cur_set_before_first(block, &page_cur);
else
page_cur_set_after_last(block, &page_cur);
- ut_ad(fil_page_index_page_check(page));
- ut_ad(index->id == btr_page_get_index_id(page));
+ const uint32_t l= btr_page_get_level(block->page.frame);
if (height == ULINT_UNDEFINED)
{
/* We are in the root node */
- height= btr_page_get_level(page);
+ height= l;
if (height);
else if (upper_rw_latch != root_leaf_rw_latch)
{
@@ -2538,6 +2529,9 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
else
{
reached_leaf:
+ const auto leaf_savepoint= mtr->get_savepoint();
+ ut_ad(leaf_savepoint);
+
if (rw_latch == RW_NO_LATCH)
btr_cur_latch_leaves(block, latch_mode, this, mtr);
@@ -2547,28 +2541,14 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
case BTR_CONT_SEARCH_TREE:
break;
default:
- if (UNIV_UNLIKELY(srv_read_only_mode))
- break;
- if (!latch_by_caller)
- /* Release the tree s-latch */
- mtr->release_s_latch_at_savepoint(savepoint -
- sizeof(mtr_memo_slot_t),
- &index->lock);
-
- /* release upper blocks */
- for (; n_releases < n_blocks; n_releases++)
- mtr_release_block_at_savepoint(mtr,
-#if 0
- savepoint + n_releases,
-#else
- tree_savepoints[n_releases],
-#endif
- tree_blocks[n_releases]);
+ /* Release index->lock if needed, and the non-leaf pages. */
+ mtr->rollback_to_savepoint(savepoint - !latch_by_caller,
+ leaf_savepoint - 1);
}
break;
}
}
- else if (UNIV_UNLIKELY(height != btr_page_get_level(page)))
+ else if (UNIV_UNLIKELY(height != l))
{
corrupted:
err= DB_CORRUPTION;
@@ -2592,7 +2572,8 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH);
if (latch_mode != BTR_MODIFY_TREE);
- else if (btr_cur_need_opposite_intention(page, lock_intention, node_ptr))
+ else if (btr_cur_need_opposite_intention(block->page.frame,
+ lock_intention, node_ptr))
{
/* If the rec is the first or last in the page for pessimistic
delete intention, it might cause node_ptr insert for the upper
@@ -2600,40 +2581,45 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
mtr->rollback_to_savepoint(savepoint);
lock_intention= BTR_INTENTION_BOTH;
- page_id.set_page_no(index->page);
+ page= index->page;
height= ULINT_UNDEFINED;
n_blocks= 0;
- n_releases= 0;
continue;
}
- else if (!btr_cur_will_modify_tree(index, page, lock_intention, node_ptr,
- node_ptr_max_size, zip_size, mtr))
- {
- ut_ad(n_releases <= n_blocks);
- /* release non-leaf pages (except the root) */
- for (; n_releases < n_blocks; n_releases++)
- if (n_releases)
- mtr_release_block_at_savepoint(mtr, tree_savepoints[n_releases],
- tree_blocks[n_releases]);
- }
-
- if (latch_mode == BTR_MODIFY_TREE && !height)
+ else
{
- ut_ad(upper_rw_latch == RW_X_LATCH);
- /* we should U-latch root page, if released already.
- It contains seg_header. */
- if (n_releases)
- mtr_block_sx_latch_at_savepoint(mtr, tree_savepoints[0],
- tree_blocks[0]);
+ if (!btr_cur_will_modify_tree(index, block->page.frame,
+ lock_intention, node_ptr,
+ node_ptr_max_size, zip_size, mtr))
+ {
+ ut_ad(n_blocks);
+ /* release buffer-fixes on pages that will not be modified
+ (except the root) */
+ if (n_blocks > 1)
+ {
+ mtr->rollback_to_savepoint(savepoint + 1, savepoint + n_blocks - 1);
+ n_blocks= 1;
+ }
+ }
- /* x-latch the branch blocks not released yet. */
- for (ulint i= n_releases; i <= n_blocks; i++)
- mtr_block_x_latch_at_savepoint(mtr,
- tree_savepoints[i], tree_blocks[i]);
+ if (!height)
+ {
+ if (page == index->page)
+ mtr->upgrade_buffer_fix(savepoint, RW_X_LATCH);
+ else
+ {
+ /* The U-latch protects BTR_SEG_HEAP, BTR_SEG_TOP. */
+ mtr->upgrade_buffer_fix(savepoint, RW_SX_LATCH);
+
+ /* Upgrade buffer-fix to exclusive latches on all remaining pages. */
+ for (ulint i= 1; i <= n_blocks; i++)
+ mtr->upgrade_buffer_fix(savepoint + i, RW_X_LATCH);
+ }
+ }
}
/* Go to the child node */
- page_id.set_page_no(btr_node_ptr_get_child_page_no(node_ptr, offsets));
+ page= btr_node_ptr_get_child_page_no(node_ptr, offsets);
n_blocks++;
}
@@ -2643,326 +2629,6 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
return err;
}
-/*****************************************************************//**
-Opens a cursor at either end of an index. */
-dberr_t
-btr_cur_open_at_index_side(
- bool from_left, /*!< in: true if open to the low end,
- false if to the high end */
- dict_index_t* index, /*!< in: index */
- btr_latch_mode latch_mode, /*!< in: latch mode */
- btr_cur_t* cursor, /*!< in/out: cursor */
- ulint level, /*!< in: level to search for
- (0=leaf). */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- page_cur_t* page_cursor;
- ulint node_ptr_max_size = srv_page_size / 2;
- ulint height;
- rec_t* node_ptr;
- btr_intention_t lock_intention;
- buf_block_t* tree_blocks[BTR_MAX_LEVELS];
- ulint tree_savepoints[BTR_MAX_LEVELS];
- ulint n_blocks = 0;
- ulint n_releases = 0;
- mem_heap_t* heap = NULL;
- rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
- rec_offs* offsets = offsets_;
- dberr_t err;
-
- rec_offs_init(offsets_);
-
- ut_ad(level != ULINT_UNDEFINED);
-
- const bool latch_by_caller = latch_mode & BTR_ALREADY_S_LATCHED;
- latch_mode = btr_latch_mode(latch_mode & ~BTR_ALREADY_S_LATCHED);
-
- lock_intention = btr_cur_get_and_clear_intention(&latch_mode);
-
- /* This function doesn't need to lock left page of the leaf page */
- if (latch_mode == BTR_SEARCH_PREV) {
- latch_mode = BTR_SEARCH_LEAF;
- } else if (latch_mode == BTR_MODIFY_PREV) {
- latch_mode = BTR_MODIFY_LEAF;
- }
-
- /* Store the position of the tree latch we push to mtr so that we
- know how to release it when we have latched the leaf node */
-
- ulint savepoint = mtr_set_savepoint(mtr);
-
- rw_lock_type_t upper_rw_latch;
-
- switch (latch_mode) {
- case BTR_CONT_MODIFY_TREE:
- case BTR_CONT_SEARCH_TREE:
- upper_rw_latch = RW_NO_LATCH;
- break;
- case BTR_MODIFY_TREE:
- /* Most of delete-intended operations are purging.
- Free blocks and read IO bandwidth should be prior
- for them, when the history list is glowing huge. */
- if (lock_intention == BTR_INTENTION_DELETE
- && buf_pool.n_pend_reads
- && trx_sys.history_size_approx()
- > BTR_CUR_FINE_HISTORY_LENGTH) {
- mtr_x_lock_index(index, mtr);
- } else {
- mtr_sx_lock_index(index, mtr);
- }
- upper_rw_latch = RW_X_LATCH;
- break;
- default:
- ut_ad(!latch_by_caller
- || mtr->memo_contains_flagged(&index->lock,
- MTR_MEMO_SX_LOCK
- | MTR_MEMO_S_LOCK));
- if (!srv_read_only_mode) {
- if (!latch_by_caller) {
- ut_ad(latch_mode != BTR_SEARCH_TREE);
- mtr_s_lock_index(index, mtr);
- }
- upper_rw_latch = RW_S_LATCH;
- } else {
- upper_rw_latch = RW_NO_LATCH;
- }
- }
-
- const rw_lock_type_t root_leaf_rw_latch = btr_cur_latch_for_root_leaf(
- latch_mode);
-
- page_cursor = btr_cur_get_page_cur(cursor);
- cursor->index = index;
-
- page_id_t page_id(index->table->space_id, index->page);
- const ulint zip_size = index->table->space->zip_size();
-
- if (root_leaf_rw_latch == RW_X_LATCH) {
- node_ptr_max_size = btr_node_ptr_max_size(index);
- }
-
- height = ULINT_UNDEFINED;
-
- for (;;) {
- ut_ad(n_blocks < BTR_MAX_LEVELS);
- tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
-
- const ulint rw_latch = height
- && (latch_mode != BTR_MODIFY_TREE || height == level)
- ? upper_rw_latch : RW_NO_LATCH;
- buf_block_t* block = buf_page_get_gen(page_id, zip_size,
- rw_latch, NULL, BUF_GET,
- mtr, &err,
- height == 0
- && !index->is_clust());
- ut_ad((block != NULL) == (err == DB_SUCCESS));
- tree_blocks[n_blocks] = block;
-
- if (!block) {
- if (err == DB_DECRYPTION_FAILED) {
- btr_decryption_failed(*index);
- }
-
- goto exit_loop;
- }
-
- const page_t* page = buf_block_get_frame(block);
-
- if (height == ULINT_UNDEFINED
- && page_is_leaf(page)
- && rw_latch != RW_NO_LATCH
- && rw_latch != root_leaf_rw_latch) {
- /* We should retry to get the page, because the root page
- is latched with different level as a leaf page. */
- ut_ad(root_leaf_rw_latch != RW_NO_LATCH);
- ut_ad(rw_latch == RW_S_LATCH);
-
- ut_ad(n_blocks == 0);
- mtr_release_block_at_savepoint(
- mtr, tree_savepoints[n_blocks],
- tree_blocks[n_blocks]);
-
- upper_rw_latch = root_leaf_rw_latch;
- continue;
- }
-
- ut_ad(fil_page_index_page_check(page));
- ut_ad(index->id == btr_page_get_index_id(page));
-
- if (height == ULINT_UNDEFINED) {
- /* We are in the root node */
-
- height = btr_page_get_level(page);
- ut_a(height >= level);
- } else {
- /* TODO: flag the index corrupted if this fails */
- ut_ad(height == btr_page_get_level(page));
- }
-
- if (height == 0) {
- if (rw_latch == RW_NO_LATCH) {
- btr_cur_latch_leaves(block, latch_mode,
- cursor, mtr);
- }
-
- /* In versions <= 3.23.52 we had forgotten to
- release the tree latch here. If in an index
- scan we had to scan far to find a record
- visible to the current transaction, that could
- starve others waiting for the tree latch. */
-
- switch (latch_mode) {
- case BTR_MODIFY_TREE:
- case BTR_CONT_MODIFY_TREE:
- case BTR_CONT_SEARCH_TREE:
- break;
- default:
- if (UNIV_UNLIKELY(srv_read_only_mode)) {
- break;
- }
- if (!latch_by_caller) {
- /* Release the tree s-latch */
- mtr_release_s_latch_at_savepoint(
- mtr, savepoint, &index->lock);
- }
-
- /* release upper blocks */
- for (; n_releases < n_blocks; n_releases++) {
- mtr_release_block_at_savepoint(
- mtr,
- tree_savepoints[n_releases],
- tree_blocks[n_releases]);
- }
- }
- } else if (height == level /* height != 0 */
- && UNIV_LIKELY(!srv_read_only_mode)) {
- /* We already have the block latched. */
- ut_ad(latch_mode == BTR_SEARCH_TREE);
- ut_ad(latch_by_caller);
- ut_ad(upper_rw_latch == RW_S_LATCH);
- ut_ad(mtr->memo_contains_flagged(block,
- MTR_MEMO_PAGE_S_FIX));
- ut_ad(mtr->memo_contains(index->lock,
- MTR_MEMO_SX_LOCK));
- /* because has sx-latch of index,
- can release upper blocks. */
- for (; n_releases < n_blocks; n_releases++) {
- mtr_release_block_at_savepoint(
- mtr,
- tree_savepoints[n_releases],
- tree_blocks[n_releases]);
- }
- }
-
- if (from_left) {
- page_cur_set_before_first(block, page_cursor);
- } else {
- page_cur_set_after_last(block, page_cursor);
- }
-
- if (height == level) {
- break;
- }
-
- ut_ad(height > 0);
-
- if (from_left
- ? !page_cur_move_to_next(page_cursor)
- : !page_cur_move_to_prev(page_cursor)) {
- err = DB_CORRUPTION;
- goto exit_loop;
- }
-
- height--;
-
- node_ptr = page_cur_get_rec(page_cursor);
- offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
- 0, ULINT_UNDEFINED, &heap);
-
- /* If the rec is the first or last in the page for
- pessimistic delete intention, it might cause node_ptr insert
- for the upper level. We should change the intention and retry.
- */
- if (latch_mode == BTR_MODIFY_TREE
- && btr_cur_need_opposite_intention(
- page, lock_intention, node_ptr)) {
-
- ut_ad(upper_rw_latch == RW_X_LATCH);
- /* release all blocks */
- for (; n_releases <= n_blocks; n_releases++) {
- mtr_release_block_at_savepoint(
- mtr, tree_savepoints[n_releases],
- tree_blocks[n_releases]);
- }
-
- lock_intention = BTR_INTENTION_BOTH;
-
- page_id.set_page_no(dict_index_get_page(index));
-
- height = ULINT_UNDEFINED;
-
- n_blocks = 0;
- n_releases = 0;
-
- continue;
- }
-
- if (latch_mode == BTR_MODIFY_TREE
- && !btr_cur_will_modify_tree(
- cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, zip_size, mtr)) {
- ut_ad(upper_rw_latch == RW_X_LATCH);
- ut_ad(n_releases <= n_blocks);
-
- /* we can release upper blocks */
- for (; n_releases < n_blocks; n_releases++) {
- if (n_releases == 0) {
- /* we should not release root page
- to pin to same block. */
- continue;
- }
-
- /* release unused blocks to unpin */
- mtr_release_block_at_savepoint(
- mtr, tree_savepoints[n_releases],
- tree_blocks[n_releases]);
- }
- }
-
- if (height == level
- && latch_mode == BTR_MODIFY_TREE) {
- ut_ad(upper_rw_latch == RW_X_LATCH);
- /* we should sx-latch root page, if released already.
- It contains seg_header. */
- if (n_releases > 0) {
- mtr_block_sx_latch_at_savepoint(
- mtr, tree_savepoints[0],
- tree_blocks[0]);
- }
-
- /* x-latch the branch blocks not released yet. */
- for (ulint i = n_releases; i <= n_blocks; i++) {
- mtr_block_x_latch_at_savepoint(
- mtr, tree_savepoints[i],
- tree_blocks[i]);
- }
- }
-
- /* Go to the child node */
- page_id.set_page_no(
- btr_node_ptr_get_child_page_no(node_ptr, offsets));
-
- n_blocks++;
- }
-
- exit_loop:
- if (UNIV_LIKELY_NULL(heap)) {
- mem_heap_free(heap);
- }
-
- return err;
-}
-
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree.
@return true if the index is available and we have put the cursor, false
@@ -3046,7 +2712,7 @@ btr_cur_open_at_rnd_pos(
latch_mode);
page_cursor = btr_cur_get_page_cur(cursor);
- cursor->index = index;
+ page_cursor->index = index;
page_id_t page_id(index->table->space_id, index->page);
const ulint zip_size = index->table->space->zip_size();
@@ -3146,7 +2812,8 @@ btr_cur_open_at_rnd_pos(
}
}
- page_cur_open_on_rnd_user_rec(block, page_cursor);
+ page_cursor->block = block;
+ page_cur_open_on_rnd_user_rec(page_cursor);
if (height == 0) {
@@ -3158,8 +2825,8 @@ btr_cur_open_at_rnd_pos(
height--;
node_ptr = page_cur_get_rec(page_cursor);
- offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
- 0, ULINT_UNDEFINED, &heap);
+ offsets = rec_get_offsets(node_ptr, page_cursor->index,
+ offsets, 0, ULINT_UNDEFINED, &heap);
/* If the rec is the first or last in the page for
pessimistic delete intention, it might cause node_ptr insert
@@ -3191,8 +2858,8 @@ btr_cur_open_at_rnd_pos(
if (latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
- cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, zip_size, mtr)) {
+ page_cursor->index, page, lock_intention,
+ node_ptr, node_ptr_max_size, zip_size, mtr)) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -3217,15 +2884,15 @@ btr_cur_open_at_rnd_pos(
/* we should sx-latch root page, if released already.
It contains seg_header. */
if (n_releases > 0) {
- mtr_block_sx_latch_at_savepoint(
- mtr, tree_savepoints[0],
+ mtr->sx_latch_at_savepoint(
+ tree_savepoints[0],
tree_blocks[0]);
}
/* x-latch the branch blocks not released yet. */
for (ulint i = n_releases; i <= n_blocks; i++) {
- mtr_block_x_latch_at_savepoint(
- mtr, tree_savepoints[i],
+ mtr->x_latch_at_savepoint(
+ tree_savepoints[i],
tree_blocks[i]);
}
}
@@ -3281,21 +2948,19 @@ btr_cur_insert_if_possible(
page_cursor = btr_cur_get_page_cur(cursor);
/* Now, try the insert */
- rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
- offsets, heap, n_ext, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple, offsets, heap, n_ext,
+ mtr);
/* If the record did not fit, reorganize.
For compressed pages, page_cur_tuple_insert()
attempted this already. */
if (!rec && !page_cur_get_page_zip(page_cursor)
- && btr_page_reorganize(page_cursor, cursor->index, mtr)
- == DB_SUCCESS) {
- rec = page_cur_tuple_insert(
- page_cursor, tuple, cursor->index,
- offsets, heap, n_ext, mtr);
+ && btr_page_reorganize(page_cursor, mtr) == DB_SUCCESS) {
+ rec = page_cur_tuple_insert(page_cursor, tuple, offsets, heap,
+ n_ext, mtr);
}
- ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(!rec || rec_offs_validate(rec, page_cursor->index, *offsets));
return(rec);
}
@@ -3325,7 +2990,7 @@ btr_cur_ins_lock_and_undo(
request if yes */
rec_t* rec = btr_cur_get_rec(cursor);
- dict_index_t* index = cursor->index;
+ dict_index_t* index = cursor->index();
ut_ad(!dict_index_is_online_ddl(index)
|| dict_index_is_clust(index)
@@ -3497,7 +3162,7 @@ btr_cur_optimistic_insert(
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
- index = cursor->index;
+ index = cursor->index();
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!dict_index_is_online_ddl(index)
@@ -3613,8 +3278,7 @@ fail_err:
<< ib::hex(thr ? thr->graph->trx->id : 0)
<< ' ' << rec_printer(entry).str());
DBUG_EXECUTE_IF("do_page_reorganize",
- if (n_recs)
- ut_a(btr_page_reorganize(page_cursor, index, mtr)
+ ut_a(!n_recs || btr_page_reorganize(page_cursor, mtr)
== DB_SUCCESS););
/* Now, try the insert */
@@ -3657,9 +3321,8 @@ fail_err:
}
#endif
- *rec = page_cur_tuple_insert(
- page_cursor, entry, index, offsets, heap,
- n_ext, mtr);
+ *rec = page_cur_tuple_insert(page_cursor, entry, offsets, heap,
+ n_ext, mtr);
reorg = page_cursor_rec != page_cur_get_rec(page_cursor);
}
@@ -3681,10 +3344,10 @@ fail_err:
reorg = true;
/* If the record did not fit, reorganize */
- err = btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, mtr);
if (err != DB_SUCCESS
|| page_get_max_insert_size(page, 1) != max_size
- || !(*rec = page_cur_tuple_insert(page_cursor, entry, index,
+ || !(*rec = page_cur_tuple_insert(page_cursor, entry,
offsets, heap, n_ext,
mtr))) {
err = DB_CORRUPTION;
@@ -3780,7 +3443,7 @@ btr_cur_pessimistic_insert(
| BTR_NO_UNDO_LOG_FLAG)) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- dict_index_t* index = cursor->index;
+ dict_index_t* index = cursor->index();
big_rec_t* big_rec_vec = NULL;
bool inherit = false;
uint32_t n_reserved = 0;
@@ -3943,7 +3606,7 @@ btr_cur_upd_lock_and_undo(
ut_ad((thr != NULL) || (flags & BTR_NO_LOCKING_FLAG));
rec = btr_cur_get_rec(cursor);
- index = cursor->index;
+ index = cursor->index();
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr->is_named_space(index->table->space));
@@ -4111,7 +3774,6 @@ btr_cur_update_alloc_zip_func(
/*==========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
- dict_index_t* index, /*!< in: the index corresponding to cursor */
#ifdef UNIV_DEBUG
rec_offs* offsets,/*!< in/out: offsets of the cursor record */
#endif /* UNIV_DEBUG */
@@ -4120,6 +3782,7 @@ btr_cur_update_alloc_zip_func(
false=update-in-place */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
+ dict_index_t* index = cursor->index;
/* Have a local copy of the variables as these can change
dynamically. */
@@ -4146,7 +3809,7 @@ btr_cur_update_alloc_zip_func(
return(false);
}
- if (btr_page_reorganize(cursor, index, mtr) == DB_SUCCESS) {
+ if (btr_page_reorganize(cursor, mtr) == DB_SUCCESS) {
rec_offs_make_valid(page_cur_get_rec(cursor), index,
page_is_leaf(page), offsets);
@@ -4345,7 +4008,7 @@ btr_cur_update_in_place(
ut_ad(page_is_leaf(cursor->page_cur.block->page.frame));
rec = btr_cur_get_rec(cursor);
- index = cursor->index;
+ index = cursor->index();
ut_ad(!index->is_ibuf());
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
@@ -4377,7 +4040,7 @@ btr_cur_update_in_place(
if (!btr_cur_update_alloc_zip(
page_zip, btr_cur_get_page_cur(cursor),
- index, offsets, rec_offs_size(offsets),
+ offsets, rec_offs_size(offsets),
false, mtr)) {
return(DB_ZIP_OVERFLOW);
}
@@ -4654,7 +4317,7 @@ btr_cur_optimistic_update(
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
rec = btr_cur_get_rec(cursor);
- index = cursor->index;
+ index = cursor->index();
ut_ad(index->has_locking());
ut_ad(trx_id > 0 || (flags & BTR_KEEP_SYS_FLAG)
|| index->table->is_temporary());
@@ -4758,7 +4421,7 @@ any_extern:
}
if (!btr_cur_update_alloc_zip(
- page_zip, page_cursor, index, *offsets,
+ page_zip, page_cursor, *offsets,
new_rec_size, true, mtr)) {
return(DB_ZIP_OVERFLOW);
}
@@ -4853,7 +4516,7 @@ any_extern:
btr_search_update_hash_on_delete(cursor);
}
- page_cur_delete_rec(page_cursor, index, *offsets, mtr);
+ page_cur_delete_rec(page_cursor, *offsets, mtr);
if (!page_cur_move_to_prev(page_cursor)) {
return DB_CORRUPTION;
@@ -4874,7 +4537,7 @@ any_extern:
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- err = btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, mtr);
if (err != DB_SUCCESS) {
goto func_exit;
}
@@ -5013,7 +4676,7 @@ btr_cur_pessimistic_update(
block = btr_cur_get_block(cursor);
page_zip = buf_block_get_page_zip(block);
- index = cursor->index;
+ index = cursor->index();
ut_ad(index->has_locking());
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK |
@@ -5219,7 +4882,7 @@ btr_cur_pessimistic_update(
#endif /* UNIV_ZIP_DEBUG */
page_cursor = btr_cur_get_page_cur(cursor);
- page_cur_delete_rec(page_cursor, index, *offsets, mtr);
+ page_cur_delete_rec(page_cursor, *offsets, mtr);
if (!page_cur_move_to_prev(page_cursor)) {
err = DB_CORRUPTION;
@@ -5237,7 +4900,7 @@ btr_cur_pessimistic_update(
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- err = btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, mtr);
if (err != DB_SUCCESS) {
goto return_after_reservations;
}
@@ -5292,10 +4955,9 @@ btr_cur_pessimistic_update(
&& !big_rec_vec
&& page_is_leaf(block->page.frame)
&& !dict_index_is_online_ddl(index)) {
-
- mtr_memo_release(mtr, &index->lock,
- MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
-
+#if 0 // FIXME: this used to be a no-op, and will cause trouble if enabled
+ mtr->release(index->lock);
+#endif
/* NOTE: We cannot release root block latch here, because it
has segment header and already modified in most of cases.*/
}
@@ -5327,7 +4989,7 @@ btr_cur_pessimistic_update(
/* btr_page_split_and_insert() in
btr_cur_pessimistic_insert() invokes
- mtr_memo_release(mtr, index->lock, MTR_MEMO_SX_LOCK).
+ mtr->release(index->lock).
We must keep the index->lock when we created a
big_rec, so that row_upd_clust_rec() can store the
big_rec in the same mini-transaction. */
@@ -5355,7 +5017,7 @@ btr_cur_pessimistic_update(
ut_a(err == DB_SUCCESS);
ut_a(rec);
ut_a(dummy_big_rec == NULL);
- ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
page_cursor->rec = rec;
/* Multiple transactions cannot simultaneously operate on the
@@ -5392,7 +5054,7 @@ btr_cur_pessimistic_update(
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
know the size of the freed record. */
- err = btr_page_reorganize(page_cursor, index, mtr);
+ err = btr_page_reorganize(page_cursor, mtr);
if (err != DB_SUCCESS) {
goto return_after_reservations;
}
@@ -5545,12 +5207,12 @@ btr_cur_compress_if_useful(
adjusted even when compression occurs */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ut_ad(mtr->memo_contains_flagged(&cursor->index->lock,
+ ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
- if (cursor->index->is_spatial()) {
+ if (cursor->index()->is_spatial()) {
const trx_t* trx = cursor->rtr_info->thr
? thr_get_trx(cursor->rtr_info->thr)
: NULL;
@@ -5595,23 +5257,23 @@ btr_cur_optimistic_delete(
ut_ad(flags == 0 || flags == BTR_CREATE_FLAG);
ut_ad(mtr->memo_contains_flagged(btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
- ut_ad(mtr->is_named_space(cursor->index->table->space));
- ut_ad(!cursor->index->is_dummy);
+ ut_ad(mtr->is_named_space(cursor->index()->table->space));
+ ut_ad(!cursor->index()->is_dummy);
/* This is intended only for leaf page deletions */
block = btr_cur_get_block(cursor);
- ut_ad(block->page.id().space() == cursor->index->table->space->id);
+ ut_ad(block->page.id().space() == cursor->index()->table->space->id);
ut_ad(page_is_leaf(buf_block_get_frame(block)));
- ut_ad(!dict_index_is_online_ddl(cursor->index)
- || dict_index_is_clust(cursor->index)
+ ut_ad(!dict_index_is_online_ddl(cursor->index())
+ || cursor->index()->is_clust()
|| (flags & BTR_CREATE_FLAG));
rec = btr_cur_get_rec(cursor);
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(rec, cursor->index(), offsets,
+ cursor->index()->n_core_fields,
ULINT_UNDEFINED, &heap);
dberr_t err = DB_SUCCESS;
@@ -5621,23 +5283,24 @@ btr_cur_optimistic_delete(
mtr)) {
/* prefetch siblings of the leaf for the pessimistic
operation. */
- btr_cur_prefetch_siblings(block, cursor->index);
+ btr_cur_prefetch_siblings(block, cursor->index());
err = DB_FAIL;
goto func_exit;
}
- if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index->page
+ if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index()->page
&& page_get_n_recs(block->page.frame) == 1
- + (cursor->index->is_instant()
- && !rec_is_metadata(rec, *cursor->index))
- && !cursor->index->must_avoid_clear_instant_add())) {
+ + (cursor->index()->is_instant()
+ && !rec_is_metadata(rec, *cursor->index()))
+ && !cursor->index()
+ ->must_avoid_clear_instant_add())) {
/* The whole index (and table) becomes logically empty.
Empty the whole page. That is, if we are deleting the
only user record, also delete the metadata record
if one exists for instant ADD COLUMN (not generic ALTER TABLE).
If we are deleting the metadata record and the
table becomes empty, clean up the whole page. */
- dict_index_t* index = cursor->index;
+ dict_index_t* index = cursor->index();
const rec_t* first_rec = page_rec_get_next_const(
page_get_infimum_rec(block->page.frame));
if (UNIV_UNLIKELY(!first_rec)) {
@@ -5682,17 +5345,17 @@ btr_cur_optimistic_delete(
If this is a recovered transaction, then
index->is_instant() will hold until the
insert into SYS_COLUMNS is rolled back. */
- ut_ad(cursor->index->table->supports_instant());
- ut_ad(cursor->index->is_primary());
+ ut_ad(cursor->index()->table->supports_instant());
+ ut_ad(cursor->index()->is_primary());
ut_ad(!page_zip);
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
- cursor->index, offsets, mtr);
+ offsets, mtr);
/* We must empty the PAGE_FREE list, because
after rollback, this deleted metadata record
would have too many fields, and we would be
unable to know the size of the freed record. */
err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
- cursor->index, mtr);
+ mtr);
goto func_exit;
} else {
if (!flags) {
@@ -5704,12 +5367,14 @@ btr_cur_optimistic_delete(
if (page_zip) {
#ifdef UNIV_ZIP_DEBUG
- ut_a(page_zip_validate(page_zip, page, cursor->index));
+ ut_a(page_zip_validate(page_zip, page,
+ cursor->index()));
#endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
- cursor->index, offsets, mtr);
+ offsets, mtr);
#ifdef UNIV_ZIP_DEBUG
- ut_a(page_zip_validate(page_zip, page, cursor->index));
+ ut_a(page_zip_validate(page_zip, page,
+ cursor->index()));
#endif /* UNIV_ZIP_DEBUG */
/* On compressed pages, the IBUF_BITMAP_FREE
@@ -5723,14 +5388,14 @@ btr_cur_optimistic_delete(
page, 1);
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
- cursor->index, offsets, mtr);
+ offsets, mtr);
/* The change buffer does not handle inserts
into non-leaf pages, into clustered indexes,
or into the change buffer. */
- if (!dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()
- && !dict_index_is_ibuf(cursor->index)) {
+ if (!cursor->index()->is_clust()
+ && !cursor->index()->table->is_temporary()
+ && !dict_index_is_ibuf(cursor->index())) {
ibuf_update_free_bits_low(block, max_ins, mtr);
}
}
@@ -5900,13 +5565,13 @@ btr_cur_pessimistic_delete(
btr_search_update_hash_on_delete(cursor);
} else {
page_cur_delete_rec(btr_cur_get_page_cur(cursor),
- index, offsets, mtr);
+ offsets, mtr);
/* We must empty the PAGE_FREE list, because
after rollback, this deleted metadata record
would carry too many fields, and we would be
unable to know the size of the freed record. */
*err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
- index, mtr);
+ mtr);
ut_ad(!ret);
goto err_exit;
}
@@ -5929,6 +5594,10 @@ discard_page:
goto err_exit;
}
+ btr_cur_t cursor;
+ cursor.page_cur.index = index;
+ cursor.page_cur.block = block;
+
if (!page_has_prev(page)) {
/* If we delete the leftmost node pointer on a
non-leaf level, we must mark the new leftmost node
@@ -5940,22 +5609,19 @@ discard_page:
we need to update parent page. */
rtr_mbr_t father_mbr;
rec_t* father_rec;
- btr_cur_t father_cursor;
rec_offs* offsets;
ulint len;
- rtr_page_get_father_block(NULL, heap, index,
- block, mtr, NULL,
- &father_cursor);
- offsets = rec_get_offsets(
- btr_cur_get_rec(&father_cursor), index, NULL,
- 0, ULINT_UNDEFINED, &heap);
+ rtr_page_get_father_block(NULL, heap, mtr, NULL,
+ &cursor);
+ father_rec = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(father_rec, index, NULL,
+ 0, ULINT_UNDEFINED, &heap);
- father_rec = btr_cur_get_rec(&father_cursor);
rtr_read_mbr(rec_get_nth_field(
father_rec, offsets, 0, &len), &father_mbr);
- rtr_update_mbr_field(&father_cursor, offsets, NULL,
+ rtr_update_mbr_field(&cursor, offsets, NULL,
page, &father_mbr, next_rec, mtr);
ut_d(parent_latched = true);
} else {
@@ -5963,8 +5629,7 @@ discard_page:
on a page, we have to change the parent node pointer
so that it is equal to the new leftmost node pointer
on the page */
- btr_cur_t cursor;
- ret = btr_page_get_father(index, block, mtr, &cursor);
+ ret = btr_page_get_father(mtr, &cursor);
if (!ret) {
*err = DB_CORRUPTION;
goto err_exit;
@@ -6004,7 +5669,7 @@ got_err:
index, page, BTR_INTENTION_DELETE, rec,
btr_node_ptr_max_size(index),
block->zip_size(), mtr);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), index,
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor),
offsets, mtr);
if (min_mark_next_rec) {
@@ -6040,10 +5705,9 @@ err_exit:
if (!srv_read_only_mode
&& page_is_leaf(page)
&& !dict_index_is_online_ddl(index)) {
-
- mtr_memo_release(mtr, &index->lock,
- MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
-
+#if 0 // FIXME: this used to be a no-op, and will cause trouble if enabled
+ mtr->release(index->lock);
+#endif
/* NOTE: We cannot release root block latch here, because it
has segment header and already modified in most of cases.*/
}
@@ -6194,7 +5858,8 @@ public:
if (dtuple_get_n_fields(&m_tuple) > 0)
{
m_up_bytes= m_low_bytes= 0;
- if (page_cur_search_with_match(m_block, index(), &m_tuple, m_page_mode,
+ m_page_cur.block= m_block;
+ if (page_cur_search_with_match(&m_tuple, m_page_mode,
&m_up_match, &m_low_match, &m_page_cur,
nullptr))
return false;
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 37219210883..3009f04021f 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -169,7 +169,7 @@ btr_defragment_find_index(
@return whether the operation was interrupted */
bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd)
{
- dict_stats_empty_defrag_summary(pcur->btr_cur.index);
+ dict_stats_empty_defrag_summary(pcur->index());
pthread_cond_t cond;
pthread_cond_init(&cond, nullptr);
btr_defragment_item_t item(pcur, &cond);
@@ -209,7 +209,7 @@ btr_defragment_remove_table(
mysql_mutex_lock(&btr_defragment_mutex);
for (auto item : btr_defragment_wq)
{
- if (item->cond && table == item->pcur->btr_cur.index->table)
+ if (item->cond && table == item->pcur->index()->table)
{
pthread_cond_signal(item->cond);
item->cond= nullptr;
@@ -405,7 +405,10 @@ btr_defragment_merge_pages(
}
}
btr_cur_t parent;
- if (!btr_page_get_father(index, from_block, mtr, &parent)) {
+ parent.page_cur.index = index;
+ parent.page_cur.block = from_block;
+
+ if (!btr_page_get_father(mtr, &parent)) {
to_block = nullptr;
} else if (n_recs_to_move == n_recs) {
/* The whole page is merged with the previous page,
@@ -690,7 +693,7 @@ processed:
}
log_free_check();
mtr_start(&mtr);
- dict_index_t *index = item->pcur->btr_cur.index;
+ dict_index_t *index = item->pcur->index();
index->set_modified(mtr);
/* To follow the latching order defined in WL#6326,
acquire index->lock X-latch. This entitles us to
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index eaecc300c90..d731bcbb893 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -30,25 +30,6 @@ Created 2/23/1996 Heikki Tuuri
#include "trx0trx.h"
/**************************************************************//**
-Allocates memory for a persistent cursor object and initializes the cursor.
-@return own: persistent cursor */
-btr_pcur_t*
-btr_pcur_create_for_mysql(void)
-/*============================*/
-{
- btr_pcur_t* pcur;
- DBUG_ENTER("btr_pcur_create_for_mysql");
-
- pcur = (btr_pcur_t*) ut_malloc_nokey(sizeof(btr_pcur_t));
-
- pcur->btr_cur.index = NULL;
- btr_pcur_init(pcur);
-
- DBUG_PRINT("btr_pcur_create_for_mysql", ("pcur: %p", pcur));
- DBUG_RETURN(pcur);
-}
-
-/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
void
@@ -56,10 +37,9 @@ btr_pcur_reset(
/*===========*/
btr_pcur_t* cursor) /*!< in, out: persistent cursor */
{
- btr_pcur_free(cursor);
+ ut_free(cursor->old_rec_buf);
+ memset(&cursor->btr_cur.page_cur, 0, sizeof(page_cur_t));
cursor->old_rec_buf = NULL;
- cursor->btr_cur.index = NULL;
- cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
cursor->old_n_core_fields = 0;
cursor->old_n_fields = 0;
@@ -69,21 +49,6 @@ btr_pcur_reset(
}
/**************************************************************//**
-Frees the memory for a persistent cursor object. */
-void
-btr_pcur_free_for_mysql(
-/*====================*/
- btr_pcur_t* cursor) /*!< in, own: persistent cursor */
-{
- DBUG_ENTER("btr_pcur_free_for_mysql");
- DBUG_PRINT("btr_pcur_free_for_mysql", ("pcur: %p", cursor));
-
- btr_pcur_free(cursor);
- ut_free(cursor);
- DBUG_VOID_RETURN;
-}
-
-/**************************************************************//**
The position of the cursor is stored by taking an initial segment of the
record the cursor is positioned on, before, or after, and copying it to the
cursor data structure, or just setting a flag if the cursor id before the
@@ -329,11 +294,10 @@ btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr)
ut_a(old_n_core_fields <= index->n_core_fields);
ut_a(old_n_fields);
- switch (restore_latch_mode) {
- default:
- break;
- case BTR_SEARCH_LEAF:
- case BTR_MODIFY_LEAF:
+ static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), "");
+ static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), "");
+
+ switch (restore_latch_mode | 4) {
case BTR_SEARCH_PREV:
case BTR_MODIFY_PREV:
/* Try optimistic restoration. */
@@ -418,7 +382,7 @@ btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr)
mode = PAGE_CUR_UNSUPP;
}
- if (btr_pcur_open_with_no_init(index, tuple, mode, restore_latch_mode,
+ if (btr_pcur_open_with_no_init(tuple, mode, restore_latch_mode,
this, mtr) != DB_SUCCESS) {
mem_heap_free(heap);
return restore_status::CORRUPTED;
@@ -512,7 +476,7 @@ btr_pcur_move_to_next_page(
dberr_t err;
buf_block_t* next_block = btr_block_get(
- *btr_pcur_get_btr_cur(cursor)->index, next_page_no, mode,
+ *cursor->index(), next_page_no, mode,
page_is_leaf(page), mtr, &err);
if (UNIV_UNLIKELY(!next_block)) {
@@ -526,12 +490,13 @@ btr_pcur_move_to_next_page(
return DB_CORRUPTION;
}
- btr_leaf_page_release(btr_pcur_get_block(cursor), mode, mtr);
-
page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
ut_d(page_check_dir(next_page));
- return err;
+
+ const auto s = mtr->get_savepoint();
+ mtr->rollback_to_savepoint(s - 2, s - 1);
+ return DB_SUCCESS;
}
MY_ATTRIBUTE((nonnull,warn_unused_result))
@@ -573,26 +538,26 @@ btr_pcur_move_backward_from_page(
return true;
}
- buf_block_t* prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
+ buf_block_t* release_block = nullptr;
if (!page_has_prev(btr_pcur_get_page(cursor))) {
} else if (btr_pcur_is_before_first_on_page(cursor)) {
- btr_leaf_page_release(btr_pcur_get_block(cursor),
- latch_mode, mtr);
-
- page_cur_set_after_last(prev_block,
+ release_block = btr_pcur_get_block(cursor);
+ page_cur_set_after_last(cursor->btr_cur.left_block,
btr_pcur_get_page_cur(cursor));
} else {
/* The repositioned cursor did not end on an infimum
record on a page. Cursor repositioning acquired a latch
also on the previous page, but we do not need the latch:
release it. */
- prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
- btr_leaf_page_release(prev_block, latch_mode, mtr);
+ release_block = cursor->btr_cur.left_block;
}
cursor->latch_mode = latch_mode;
cursor->old_rec = nullptr;
+ if (release_block) {
+ mtr->release(*release_block);
+ }
return false;
}
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 29345cf0104..140fac851de 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -302,7 +302,7 @@ are consistent.
@param[in] cursor cursor which was just positioned */
static void btr_search_info_update_hash(btr_search_t *info, btr_cur_t *cursor)
{
- dict_index_t* index = cursor->index;
+ dict_index_t* index = cursor->index();
int cmp;
if (dict_index_is_ibuf(index)) {
@@ -704,14 +704,14 @@ btr_search_update_hash_ref(
return;
}
- if (index != cursor->index) {
- ut_ad(index->id == cursor->index->id);
+ if (index != cursor->index()) {
+ ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id().space() == index->table->space_id);
- ut_ad(index == cursor->index);
+ ut_ad(index == cursor->index());
ut_ad(!dict_index_is_ibuf(index));
auto part = btr_search_sys.get_part(*index);
part->latch.wr_lock(SRW_LOCK_CALL);
@@ -784,7 +784,7 @@ btr_search_check_guess(
bool success = false;
rec_offs_init(offsets_);
- n_unique = dict_index_get_n_unique_in_tree(cursor->index);
+ n_unique = dict_index_get_n_unique_in_tree(cursor->index());
rec = btr_cur_get_rec(cursor);
@@ -792,7 +792,7 @@ btr_search_check_guess(
|| !page_rec_is_leaf(rec))) {
ut_ad("corrupted index" == 0);
return false;
- } else if (cursor->index->table->not_redundant()) {
+ } else if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -805,8 +805,8 @@ btr_search_check_guess(
match = 0;
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(rec, cursor->index(), offsets,
+ cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(tuple, rec, offsets, &match);
@@ -859,7 +859,7 @@ btr_search_check_guess(
goto exit_func;
}
- if (cursor->index->table->not_redundant()) {
+ if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(prev_rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -870,8 +870,8 @@ btr_search_check_guess(
}
}
- offsets = rec_get_offsets(prev_rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(prev_rec, cursor->index(), offsets,
+ cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(
tuple, prev_rec, offsets, &match);
@@ -899,7 +899,7 @@ btr_search_check_guess(
goto exit_func;
}
- if (cursor->index->table->not_redundant()) {
+ if (cursor->index()->table->not_redundant()) {
switch (rec_get_status(next_rec)) {
case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
@@ -910,8 +910,8 @@ btr_search_check_guess(
}
}
- offsets = rec_get_offsets(next_rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(next_rec, cursor->index(), offsets,
+ cursor->index()->n_core_fields,
n_unique, &heap);
cmp = cmp_dtuple_rec_with_match(
tuple, next_rec, offsets, &match);
@@ -1098,16 +1098,16 @@ btr_search_guess_on_hash(
part->latch.rd_lock(SRW_LOCK_CALL);
if (!btr_search_enabled) {
- goto fail;
+ goto ahi_release_and_fail;
}
rec = static_cast<const rec_t*>(
ha_search_and_get_data(&part->table, fold));
if (!rec) {
-fail:
+ahi_release_and_fail:
part->latch.rd_unlock();
-
+fail:
btr_search_failure(info, cursor);
return false;
}
@@ -1116,66 +1116,52 @@ fail:
buf_pool_t::hash_chain& chain = buf_pool.page_hash.cell_get(
block->page.id().fold());
- bool fail, got_latch;
+ bool got_latch;
{
transactional_shared_lock_guard<page_hash_latch> g{
buf_pool.page_hash.lock_get(chain)};
-
- const auto state = block->page.state();
- if (state == buf_page_t::REMOVE_HASH) {
- /* Another thread is just freeing the block
- from the LRU list of the buffer pool: do not
- try to access this page. */
- goto fail;
- }
- if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
-#ifndef NO_ELISION
- xend();
-#endif
- ut_error;
- }
-
- fail = index != block->index && index_id == block->index->id;
got_latch = (latch_mode == BTR_SEARCH_LEAF)
? block->page.lock.s_lock_try()
: block->page.lock.x_lock_try();
}
- ut_a(!fail || block->index->freed());
if (!got_latch) {
- goto fail;
+ goto ahi_release_and_fail;
+ }
+
+ const auto state = block->page.state();
+ if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
+ ut_ad(state == buf_page_t::REMOVE_HASH);
+block_and_ahi_release_and_fail:
+ if (latch_mode == BTR_SEARCH_LEAF) {
+ block->page.lock.s_unlock();
+ } else {
+ block->page.lock.x_unlock();
+ }
+ goto ahi_release_and_fail;
+ }
+
+ ut_ad(state < buf_page_t::READ_FIX || state >= buf_page_t::WRITE_FIX);
+ ut_ad(state < buf_page_t::READ_FIX || latch_mode == BTR_SEARCH_LEAF);
+
+ if (index != block->index && index_id == block->index->id) {
+ ut_a(block->index->freed());
+ goto block_and_ahi_release_and_fail;
}
block->page.fix();
block->page.set_accessed();
buf_page_make_young_if_needed(&block->page);
- ut_ad(!block->page.is_read_fixed());
- ut_ad(latch_mode == BTR_SEARCH_LEAF || !block->page.is_io_fixed());
static_assert(ulint{MTR_MEMO_PAGE_S_FIX} == ulint{BTR_SEARCH_LEAF},
"");
static_assert(ulint{MTR_MEMO_PAGE_X_FIX} == ulint{BTR_MODIFY_LEAF},
"");
- mtr->memo_push(block, mtr_memo_type_t(latch_mode));
-
- ++buf_pool.stat.n_page_gets;
part->latch.rd_unlock();
- if (UNIV_UNLIKELY(fail)) {
- goto fail_and_release_page;
- }
-
- DBUG_ASSERT(!block->page.is_freed());
-
- if (!block->page.in_file()) {
- ut_ad(block->page.state() == buf_page_t::REMOVE_HASH);
-
-fail_and_release_page:
- btr_leaf_page_release(block, latch_mode, mtr);
+ ++buf_pool.stat.n_page_gets;
- btr_search_failure(info, cursor);
- return false;
- }
+ mtr->memo_push(block, mtr_memo_type_t(latch_mode));
ut_ad(page_rec_is_user_rec(rec));
@@ -1190,7 +1176,8 @@ fail_and_release_page:
right. */
if (index_id != btr_page_get_index_id(block->page.frame)
|| !btr_search_check_guess(cursor, false, tuple, mode)) {
- goto fail_and_release_page;
+ mtr->release_last_page();
+ goto fail;
}
if (info->n_hash_potential < BTR_SEARCH_BUILD_LIMIT + 5) {
@@ -1198,41 +1185,6 @@ fail_and_release_page:
info->n_hash_potential++;
}
-#ifdef notdefined
- /* These lines of code can be used in a debug version to check
- the correctness of the searched cursor position: */
-
- info->last_hash_succ = FALSE;
-
- /* Currently, does not work if the following fails: */
- ut_ad(!ahi_latch);
-
- btr_leaf_page_release(block, latch_mode, mtr);
-
- btr_cur_search_to_nth_level(
- index, 0, tuple, mode, latch_mode, &cursor2, 0, mtr);
-
- if (mode == PAGE_CUR_GE
- && page_rec_is_supremum(btr_cur_get_rec(&cursor2))) {
-
- /* If mode is PAGE_CUR_GE, then the binary search
- in the index tree may actually take us to the supremum
- of the previous page */
-
- info->last_hash_succ = FALSE;
-
- btr_pcur_open_on_user_rec(
- index, tuple, mode, latch_mode, &pcur, mtr);
-
- ut_ad(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor));
- } else {
- ut_ad(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor));
- }
-
- /* NOTE that it is theoretically possible that the above assertions
- fail if the page of the cursor gets removed from the buffer pool
- meanwhile! Thus it might not be a bug. */
-#endif
info->last_hash_succ = TRUE;
#ifdef UNIV_SEARCH_PERF_STAT
@@ -1690,7 +1642,7 @@ exit_func:
@param[in,out] cursor cursor which was just positioned */
void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
{
- srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index)
+ srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index())
->latch;
buf_block_t* block = btr_cur_get_block(cursor);
@@ -1705,7 +1657,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
- btr_search_check_free_space_in_heap(cursor->index);
+ btr_search_check_free_space_in_heap(cursor->index());
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
@@ -1722,7 +1674,7 @@ void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
- btr_search_build_page_hash_index(cursor->index, block,
+ btr_search_build_page_hash_index(cursor->index(), block,
ahi_latch,
block->n_fields,
block->n_bytes,
@@ -1834,15 +1786,15 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
return;
}
- ut_ad(!cursor->index->table->is_temporary());
+ ut_ad(!cursor->index()->table->is_temporary());
- if (index != cursor->index) {
+ if (index != cursor->index()) {
btr_search_drop_page_hash_index(block);
return;
}
ut_ad(block->page.id().space() == index->table->space_id);
- ut_a(index == cursor->index);
+ ut_a(index == cursor->index());
ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0);
ut_ad(!dict_index_is_ibuf(index));
@@ -1889,7 +1841,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
dict_index_t* index;
rec_t* rec;
- ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
+ ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
if (!btr_search_enabled) {
return;
@@ -1908,15 +1860,15 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
return;
}
- ut_ad(!cursor->index->table->is_temporary());
+ ut_ad(!cursor->index()->table->is_temporary());
- if (index != cursor->index) {
- ut_ad(index->id == cursor->index->id);
+ if (index != cursor->index()) {
+ ut_ad(index->id == cursor->index()->id);
btr_search_drop_page_hash_index(block);
return;
}
- ut_a(cursor->index == index);
+ ut_a(cursor->index() == index);
ut_ad(!dict_index_is_ibuf(index));
ahi_latch->wr_lock(SRW_LOCK_CALL);
@@ -1933,7 +1885,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
&& !block->curr_left_side) {
if (const rec_t *new_rec = page_rec_get_next_const(rec)) {
if (ha_search_and_update_if_found(
- &btr_search_sys.get_part(*cursor->index)
+ &btr_search_sys.get_part(*cursor->index())
->table,
cursor->fold, rec, block, new_rec)) {
MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_UPDATED);
@@ -1976,7 +1928,7 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
- ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index)->latch);
+ ut_ad(ahi_latch == &btr_search_sys.get_part(*cursor->index())->latch);
ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
if (!btr_search_enabled) {
@@ -2000,16 +1952,16 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor,
rec = btr_cur_get_rec(cursor);
- ut_ad(!cursor->index->table->is_temporary());
+ ut_ad(!cursor->index()->table->is_temporary());
- if (index != cursor->index) {
- ut_ad(index->id == cursor->index->id);
+ if (index != cursor->index()) {
+ ut_ad(index->id == cursor->index()->id);
drop:
btr_search_drop_page_hash_index(block);
return;
}
- ut_a(index == cursor->index);
+ ut_a(index == cursor->index());
ut_ad(!dict_index_is_ibuf(index));
n_fields = block->curr_n_fields;
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 88eff936c27..daf3bc9a664 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -752,11 +752,12 @@ dict_create_index_tree_step(
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
node->page_no = FIL_NULL;
+ pcur.btr_cur.page_cur.index =
+ UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
dberr_t err =
- btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes),
- search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
- &pcur, &mtr);
+ btr_pcur_open(search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
+ &pcur, 0, &mtr);
if (err != DB_SUCCESS) {
func_exit:
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 362b949e10f..21efb525fa8 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -4141,8 +4141,9 @@ void dict_set_corrupted(dict_index_t *index, const char *ctx)
dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2);
+ cursor.page_cur.index = sys_index;
- if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
+ if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) {
goto fail;
@@ -4216,8 +4217,9 @@ dict_index_set_merge_threshold(
dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2);
+ cursor.page_cur.index = sys_index;
- if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
+ if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &cursor, &mtr)
!= DB_SUCCESS) {
goto func_exit;
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index b7f245a3787..004b00615e8 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -1319,8 +1319,9 @@ static dberr_t dict_load_columns(dict_table_t *table, unsigned use_uncommitted,
mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
- dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -1449,9 +1450,9 @@ dict_load_virtual_col(dict_table_t *table, bool uncommitted, ulint nth_v_col)
dfield_set_data(&dfield[1], vcol_pos, 4);
dict_index_copy_types(&tuple, sys_virtual_index, 2);
+ pcur.btr_cur.page_cur.index = sys_virtual_index;
- dberr_t err = btr_pcur_open_on_user_rec(sys_virtual_index, &tuple,
- PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -1685,8 +1686,9 @@ static dberr_t dict_load_fields(dict_index_t *index, bool uncommitted,
mach_write_to_8(index_id, index->id);
dfield_set_data(&dfield, index_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
- dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
+ dberr_t error = btr_pcur_open_on_user_rec(&tuple,
PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr);
if (error != DB_SUCCESS) {
@@ -1943,8 +1945,9 @@ dberr_t dict_load_indexes(dict_table_t *table, bool uncommitted,
mach_write_to_8(table_id, table->id);
dfield_set_data(&dfield, table_id, 8);
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
- dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple,
+ dberr_t error = btr_pcur_open_on_user_rec(&tuple,
PAGE_CUR_GE, BTR_SEARCH_LEAF,
&pcur, &mtr);
if (error != DB_SUCCESS) {
@@ -2341,11 +2344,12 @@ static dict_table_t *dict_load_table_one(const span<const char> &name,
};
dfield_set_data(&dfield, name.data(), name.size());
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
bool uncommitted = false;
reload:
mtr.start();
- dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS || !btr_pcur_is_on_user_rec(&pcur)) {
@@ -2599,10 +2603,11 @@ dict_load_table_on_id(
mach_write_to_8(id_buf, table_id);
dfield_set_data(&dfield, id_buf, 8);
dict_index_copy_types(&tuple, sys_table_ids, 1);
+ pcur.btr_cur.page_cur.index = sys_table_ids;
dict_table_t* table = nullptr;
- if (btr_pcur_open_on_user_rec(sys_table_ids, &tuple, PAGE_CUR_GE,
+ if (btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr)
== DB_SUCCESS
&& btr_pcur_is_on_user_rec(&pcur)) {
@@ -2706,9 +2711,10 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id)
dfield_set_data(&dfield, foreign->id, id_len);
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
mem_heap_t* heap = nullptr;
- dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -2880,11 +2886,12 @@ dict_load_foreign(
};
dfield_set_data(&dfield, id.data(), id.size());
dict_index_copy_types(&tuple, sys_index, 1);
+ pcur.btr_cur.page_cur.index = sys_index;
mtr.start();
mem_heap_t* heap = nullptr;
- dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto err_exit;
@@ -3093,8 +3100,9 @@ start_load:
mtr.start();
dfield_set_data(&dfield, table_name, strlen(table_name));
dict_index_copy_types(&tuple, sec_index, 1);
+ pcur.btr_cur.page_cur.index = sec_index;
- dberr_t err = btr_pcur_open_on_user_rec(sec_index, &tuple, PAGE_CUR_GE,
+ dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS) {
DBUG_RETURN(err);
@@ -3195,7 +3203,6 @@ next_rec:
load_next_index:
mtr.commit();
- ut_free(pcur.old_rec_buf);
if ((sec_index = dict_table_get_next_index(sec_index))) {
/* Switch to scan index on REF_NAME, fk_max_recusive_level
@@ -3205,5 +3212,6 @@ load_next_index:
goto start_load;
}
+ ut_free(pcur.old_rec_buf);
DBUG_RETURN(DB_SUCCESS);
}
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index a5806de7b6a..dcd604cfb74 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1560,25 +1560,96 @@ empty_table:
return err;
}
-/** Open persistent cursor at the first page in a tree level.
-@param index B-tree index
-@param pcur persistent cursor
-@param level level to search for (0=leaf)
-@param mtr mini-transaction */
-static dberr_t btr_pcur_open_level(dict_index_t *index, btr_pcur_t *pcur,
- ulint level, mtr_t *mtr)
+/** Open a cursor at the first page in a tree level.
+@param page_cur cursor
+@param level level to search for (0=leaf)
+@param mtr mini-transaction */
+static dberr_t page_cur_open_level(page_cur_t *page_cur, ulint level,
+ mtr_t *mtr)
+{
+ mem_heap_t *heap= nullptr;
+ rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_offs *offsets= offsets_;
+ dberr_t err;
+
+ dict_index_t *const index= page_cur->index;
+
+ rec_offs_init(offsets_);
+ ut_ad(level != ULINT_UNDEFINED);
+ ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_SX_LOCK));
+ ut_ad(mtr->get_savepoint() == 1);
+
+ uint32_t page= index->page;
+
+ for (ulint height = ULINT_UNDEFINED;; height--)
+ {
+ buf_block_t* block=
+ btr_block_get(*index, page, RW_S_LATCH,
+ !height && !index->is_clust(), mtr, &err);
+ if (!block)
+ break;
+
+ const uint32_t l= btr_page_get_level(block->page.frame);
+
+ if (height == ULINT_UNDEFINED)
+ {
+ ut_ad(!heap);
+ /* We are in the root node */
+ height= l;
+ if (UNIV_UNLIKELY(height < level))
+ return DB_CORRUPTION;
+ }
+ else if (UNIV_UNLIKELY(height != l) || page_has_prev(block->page.frame))
+ {
+ err= DB_CORRUPTION;
+ break;
+ }
+
+ page_cur_set_before_first(block, page_cur);
+
+ if (height == level)
+ break;
+
+ ut_ad(height);
+
+ if (!page_cur_move_to_next(page_cur))
+ {
+ err= DB_CORRUPTION;
+ break;
+ }
+
+ offsets= rec_get_offsets(page_cur->rec, index, offsets, 0, ULINT_UNDEFINED,
+ &heap);
+ page= btr_node_ptr_get_child_page_no(page_cur->rec, offsets);
+ }
+
+ if (UNIV_LIKELY_NULL(heap))
+ mem_heap_free(heap);
+
+ /* Release all page latches except the one on the desired page. */
+ const auto end= mtr->get_savepoint();
+ if (end > 1)
+ mtr->rollback_to_savepoint(1, end - 1);
+
+ return err;
+}
+
+/** Open a cursor at the first page in a tree level.
+@param page_cur cursor
+@param level level to search for (0=leaf)
+@param mtr mini-transaction
+@param index index tree */
+static dberr_t btr_pcur_open_level(btr_pcur_t *pcur, ulint level, mtr_t *mtr,
+ dict_index_t *index)
{
- btr_pcur_init(pcur);
- pcur->trx_if_known= nullptr;
pcur->latch_mode= BTR_SEARCH_TREE;
pcur->search_mode= PAGE_CUR_G;
pcur->pos_state= BTR_PCUR_IS_POSITIONED;
-
- return btr_cur_open_at_index_side(true, index,
- BTR_SEARCH_TREE_ALREADY_S_LATCHED,
- btr_pcur_get_btr_cur(pcur), level, mtr);
+ pcur->btr_cur.page_cur.index= index;
+ return page_cur_open_level(&pcur->btr_cur.page_cur, level, mtr);
}
+
/* @{ Pseudo code about the relation between the following functions
let N = N_SAMPLE_PAGES(index)
@@ -1635,7 +1706,8 @@ dict_stats_analyze_index_level(
DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n",
__func__, index->table->name, index->name, level);
- ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
+ *total_recs = 0;
+ *total_pages = 0;
n_uniq = dict_index_get_n_unique(index);
@@ -1668,7 +1740,7 @@ dict_stats_analyze_index_level(
/* Position pcur on the leftmost record on the leftmost page
on the desired level. */
- if (btr_pcur_open_level(index, &pcur, level, mtr) != DB_SUCCESS
+ if (btr_pcur_open_level(&pcur, level, mtr, index) != DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) {
goto func_exit;
}
@@ -1678,21 +1750,10 @@ dict_stats_analyze_index_level(
/* The page must not be empty, except when
it is the root page (and the whole index is empty). */
ut_ad(btr_pcur_is_on_user_rec(&pcur) || page_is_leaf(page));
- ut_ad(btr_pcur_get_rec(&pcur)
- == page_rec_get_next_const(page_get_infimum_rec(page)));
prev_rec = NULL;
prev_rec_is_copied = false;
- /* no records by default */
- *total_recs = 0;
-
- *total_pages = 0;
-
- if (page_has_prev(page) || btr_page_get_level(page) != level) {
- goto func_exit;
- }
-
if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
btr_pcur_get_rec(&pcur), page_is_comp(page))) {
ut_ad(btr_pcur_is_on_user_rec(&pcur));
@@ -1745,10 +1806,7 @@ dict_stats_analyze_index_level(
if (level == 0
&& !srv_stats_include_delete_marked
- && rec_get_deleted_flag(
- rec,
- page_is_comp(btr_pcur_get_page(&pcur)))) {
-
+ && rec_get_deleted_flag(rec, page_rec_is_comp(rec))) {
if (rec_is_last_on_page
&& !prev_rec_is_copied
&& prev_rec != NULL) {
@@ -1828,7 +1886,7 @@ dict_stats_analyze_index_level(
records on this level at some point we will jump from
one page to the next and then rec and prev_rec will
be on different pages and
- btr_pcur_move_to_next_user_rec() will release the
+ btr_cur_move_to_next_user_rec() will release the
latch on the page that prev_rec is on */
prev_rec = rec_copy_prefix_to_buf(
rec, index, n_uniq,
@@ -1837,7 +1895,7 @@ dict_stats_analyze_index_level(
} else {
/* still on the same page, the next call to
- btr_pcur_move_to_next_user_rec() will not jump
+ btr_cur_move_to_next_user_rec() will not jump
on the next page, we can simply assign pointers
instead of copying the records like above */
@@ -1908,7 +1966,6 @@ dict_stats_analyze_index_level(
}
#endif /* UNIV_STATS_DEBUG */
- btr_leaf_page_release(btr_pcur_get_block(&pcur), BTR_SEARCH_LEAF, mtr);
func_exit:
ut_free(prev_rec_buf);
mem_heap_free(heap);
@@ -2297,7 +2354,6 @@ dict_stats_analyze_index_for_n_prefix(
n_prefix, n_diff_data->n_diff_on_level);
#endif
- ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK));
ut_ad(n_diff_data->level);
/* Position pcur on the leftmost record on the leftmost page
@@ -2306,7 +2362,7 @@ dict_stats_analyze_index_for_n_prefix(
n_diff_data->n_diff_all_analyzed_pages = 0;
n_diff_data->n_external_pages_sum = 0;
- if (btr_pcur_open_level(index, &pcur, n_diff_data->level, mtr)
+ if (btr_pcur_open_level(&pcur, n_diff_data->level, mtr, index)
!= DB_SUCCESS
|| !btr_pcur_move_to_next_on_page(&pcur)) {
return;
@@ -2696,6 +2752,7 @@ empty_index:
mtr.commit();
mtr.start();
mtr_sx_lock_index(index, &mtr);
+ ut_ad(mtr.get_savepoint() == 1);
buf_block_t *root = btr_root_block_get(index, RW_S_LATCH,
&mtr, &err);
if (!root || root_level != btr_page_get_level(root->page.frame)
@@ -2711,7 +2768,7 @@ empty_index:
break;
}
- mtr.memo_release(root, MTR_MEMO_PAGE_S_FIX);
+ mtr.rollback_to_savepoint(1);
/* check whether we should pick the current level;
we pick level 1 even if it does not have enough
@@ -2773,6 +2830,7 @@ empty_index:
break;
}
+ mtr.rollback_to_savepoint(1);
dict_stats_analyze_index_level(index,
level,
n_diff_on_level,
@@ -2780,7 +2838,7 @@ empty_index:
&total_pages,
n_diff_boundaries,
&mtr);
-
+ mtr.rollback_to_savepoint(1);
level_is_analyzed = true;
if (level == 1
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 616d5764181..7410986c441 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -1830,7 +1830,6 @@ fil_crypt_rotate_page(
} else {
/* If block read failed mtr memo and log should be empty. */
ut_ad(!mtr.has_modifications());
- ut_ad(!mtr.is_dirty());
ut_ad(mtr.is_empty());
mtr.commit();
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 9adc01d9cf5..689fb58d7dc 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -3357,9 +3357,10 @@ fts_add_doc_by_id(
mach_write_to_8((byte*) &temp_doc_id, doc_id);
dfield_set_data(dfield, &temp_doc_id, sizeof(temp_doc_id));
+ pcur.btr_cur.page_cur.index = fts_id_index;
/* If we have a match, add the data to doc structure */
- if (btr_pcur_open_with_no_init(fts_id_index, tuple, PAGE_CUR_LE,
+ if (btr_pcur_open_with_no_init(tuple, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &pcur, &mtr)
== DB_SUCCESS
&& btr_pcur_get_low_match(&pcur) == 1) {
@@ -3386,7 +3387,6 @@ fts_add_doc_by_id(
dtuple_t* clust_ref;
ulint n_fields;
- btr_pcur_init(&clust_pcur);
n_fields = dict_index_get_n_unique(clust_index);
clust_ref = dtuple_create(heap, n_fields);
@@ -3394,8 +3394,9 @@ fts_add_doc_by_id(
row_build_row_ref_in_tuple(
clust_ref, rec, fts_id_index, NULL);
+ clust_pcur.btr_cur.page_cur.index = clust_index;
- if (btr_pcur_open_with_no_init(clust_index, clust_ref,
+ if (btr_pcur_open_with_no_init(clust_ref,
PAGE_CUR_LE,
BTR_SEARCH_LEAF,
&clust_pcur, &mtr)
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index 88723ce5e8a..59d77c9c5fc 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -70,7 +70,7 @@ rtr_page_split_initialize_nodes(
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
- n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
+ n_uniq = dict_index_get_n_unique_in_tree(cursor->index());
n_recs = ulint(page_get_n_recs(page)) + 1;
@@ -88,8 +88,8 @@ rtr_page_split_initialize_nodes(
rec = page_rec_get_next(page_get_infimum_rec(page));
const ulint n_core = page_is_leaf(page)
- ? cursor->index->n_core_fields : 0;
- *offsets = rec_get_offsets(rec, cursor->index, *offsets, n_core,
+ ? cursor->index()->n_core_fields : 0;
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets, n_core,
n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
@@ -101,7 +101,7 @@ rtr_page_split_initialize_nodes(
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
rec = page_rec_get_next(rec);
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
n_core, n_uniq, &heap);
source_cur = rec_get_nth_field(rec, *offsets, 0, &len);
}
@@ -111,9 +111,9 @@ rtr_page_split_initialize_nodes(
dtuple_get_nth_field(tuple, 0)));
cur->coords = reserve_coords(buf_pos, SPDIMS);
rec = (byte*) mem_heap_alloc(
- heap, rec_get_converted_size(cursor->index, tuple, 0));
+ heap, rec_get_converted_size(cursor->index(), tuple, 0));
- rec = rec_convert_dtuple_to_rec(rec, cursor->index, tuple, 0);
+ rec = rec_convert_dtuple_to_rec(rec, cursor->index(), tuple, 0);
cur->key = rec;
memcpy(cur->coords, source_cur, DATA_MBR_LEN);
@@ -200,7 +200,7 @@ rtr_update_mbr_field(
rec_t* new_rec, /*!< in: rec to use */
mtr_t* mtr) /*!< in: mtr */
{
- dict_index_t* index = cursor->index;
+ dict_index_t* index = cursor->index();
mem_heap_t* heap;
page_t* page;
rec_t* rec;
@@ -245,6 +245,7 @@ rtr_update_mbr_field(
/* We need to remember the child page no of cursor2, since page could be
reorganized or insert a new rec before it. */
if (cursor2) {
+ ut_ad(cursor2->index() == index);
rec_t* del_rec = btr_cur_get_rec(cursor2);
offsets2 = rec_get_offsets(btr_cur_get_rec(cursor2),
index, NULL, 0,
@@ -268,7 +269,7 @@ rtr_update_mbr_field(
if (!btr_cur_update_alloc_zip(
page_zip,
btr_cur_get_page_cur(cursor),
- index, offsets,
+ offsets,
rec_offs_size(offsets),
false, mtr)) {
@@ -321,7 +322,7 @@ rtr_update_mbr_field(
offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
- index, offsets2, mtr);
+ offsets2, mtr);
}
} else if (page_get_n_recs(page) == 1) {
/* When there's only one rec in the page, we do insert/delete to
@@ -352,9 +353,10 @@ rtr_update_mbr_field(
ut_ad(old_rec != insert_rec);
page_cur_position(old_rec, block, &page_cur);
+ page_cur.index = index;
offsets2 = rec_get_offsets(old_rec, index, NULL, n_core,
ULINT_UNDEFINED, &heap);
- page_cur_delete_rec(&page_cur, index, offsets2, mtr);
+ page_cur_delete_rec(&page_cur, offsets2, mtr);
} else {
update_mbr:
@@ -366,8 +368,7 @@ update_mbr:
/* Delete the rec which cursor point to. */
next_rec = page_rec_get_next(rec);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor),
- index, offsets, mtr);
+ page_cur_delete_rec(&cursor->page_cur, offsets, mtr);
if (!ins_suc) {
ut_ad(rec_info & REC_INFO_MIN_REC_FLAG);
@@ -400,13 +401,12 @@ update_mbr:
== btr_node_ptr_get_child_page_no(cur2_rec,
offsets2));
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
- index, offsets2, mtr);
+ offsets2, mtr);
cursor2 = NULL;
}
/* Insert the new rec. */
- if (page_cur_search_with_match(block, index, node_ptr,
- PAGE_CUR_LE,
+ if (page_cur_search_with_match(node_ptr, PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(cursor),
NULL)) {
@@ -424,7 +424,7 @@ update_mbr:
} else if (ins_suc) {
ut_ad(err == DB_FAIL);
err = btr_page_reorganize(btr_cur_get_page_cur(cursor),
- index, mtr);
+ mtr);
if (err == DB_SUCCESS) {
err = btr_cur_optimistic_insert(
flags, cursor, &insert_offsets, &heap,
@@ -505,7 +505,7 @@ update_mbr:
ut_ad(cur2_pno == del_page_no && cur2_rec != insert_rec);
page_cur_delete_rec(btr_cur_get_page_cur(cursor2),
- index, offsets2, mtr);
+ offsets2, mtr);
}
if (!ins_suc) {
@@ -556,7 +556,6 @@ rtr_adjust_upper_level(
{
ulint page_no;
ulint new_page_no;
- dict_index_t* index = sea_cur->index;
btr_cur_t cursor;
rec_offs* offsets;
mem_heap_t* heap;
@@ -570,9 +569,10 @@ rtr_adjust_upper_level(
/* Create a memory heap where the data tuple is stored */
heap = mem_heap_create(1024);
- cursor.init();
cursor.thr = sea_cur->thr;
+ cursor.page_cur.index = sea_cur->index();
+ cursor.page_cur.block = block;
/* Get the level of the split pages */
level = btr_page_get_level(buf_block_get_frame(block));
@@ -584,8 +584,7 @@ rtr_adjust_upper_level(
/* Set new mbr for the old page on the upper level. */
/* Look up the index for the node pointer to page */
- offsets = rtr_page_get_father_block(
- NULL, heap, index, block, mtr, sea_cur, &cursor);
+ offsets = rtr_page_get_father_block(NULL, heap, mtr, sea_cur, &cursor);
page_cursor = btr_cur_get_page_cur(&cursor);
@@ -607,10 +606,9 @@ rtr_adjust_upper_level(
page_get_infimum_rec(new_block->page.frame))) {
/* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr(
- index, new_mbr, first, new_page_no, heap);
+ sea_cur->index(), new_mbr, first, new_page_no, heap);
ulint up_match = 0, low_match = 0;
- err = page_cur_search_with_match(btr_cur_get_block(&cursor),
- index, node_ptr_upper,
+ err = page_cur_search_with_match(node_ptr_upper,
PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(&cursor),
@@ -660,7 +658,7 @@ rtr_adjust_upper_level(
mem_heap_free(heap);
- ut_ad(block->zip_size() == index->table->space->zip_size());
+ ut_ad(block->zip_size() == sea_cur->index()->table->space->zip_size());
if (err != DB_SUCCESS) {
return err;
@@ -670,7 +668,7 @@ rtr_adjust_upper_level(
if (next_page_no == FIL_NULL) {
} else if (buf_block_t* next_block =
- btr_block_get(*index, next_page_no, RW_X_LATCH,
+ btr_block_get(*sea_cur->index(), next_page_no, RW_X_LATCH,
false, mtr, &err)) {
if (UNIV_UNLIKELY(memcmp_aligned<4>(next_block->page.frame
+ FIL_PAGE_PREV,
@@ -740,6 +738,7 @@ rtr_split_page_move_rec_list(
page_cur_set_before_first(block, &page_cursor);
page_cur_set_before_first(new_block, &new_page_cursor);
+ page_cursor.index = new_page_cursor.index = index;
page = buf_block_get_frame(block);
new_page = buf_block_get_frame(new_block);
@@ -774,7 +773,7 @@ rtr_split_page_move_rec_list(
rec = page_cur_insert_rec_low(
&new_page_cursor,
- index, cur_split_node->key, offsets, mtr);
+ cur_split_node->key, offsets, mtr);
if (UNIV_UNLIKELY
(!rec
@@ -841,8 +840,7 @@ rtr_split_page_move_rec_list(
page_cur_get_rec(&page_cursor), index,
offsets, n_core, ULINT_UNDEFINED,
&heap);
- page_cur_delete_rec(&page_cursor,
- index, offsets, mtr);
+ page_cur_delete_rec(&page_cursor, offsets, mtr);
}
}
@@ -877,7 +875,6 @@ rtr_page_split_and_insert(
buf_block_t* new_block;
page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip;
- buf_block_t* insert_block;
page_cur_t* page_cursor;
rec_t* rec = 0;
ulint n_recs;
@@ -906,12 +903,10 @@ func_start:
mem_heap_empty(*heap);
*offsets = NULL;
- ut_ad(mtr->memo_contains_flagged(&cursor->index->lock, MTR_MEMO_X_LOCK
- | MTR_MEMO_SX_LOCK));
- ut_ad(!dict_index_is_online_ddl(cursor->index)
- || (flags & BTR_CREATE_FLAG)
- || dict_index_is_clust(cursor->index));
- ut_ad(cursor->index->lock.have_u_or_x());
+ ut_ad(mtr->memo_contains_flagged(&cursor->index()->lock,
+ MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
+ ut_ad(!dict_index_is_online_ddl(cursor->index()));
+ ut_ad(cursor->index()->lock.have_u_or_x());
block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
@@ -954,7 +949,7 @@ corrupted:
}
#endif
- insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
+ insert_size = rec_get_converted_size(cursor->index(), tuple, n_ext);
total_data = page_get_data_size(page) + insert_size;
first_rec_group = split_rtree_node(rtr_split_node_array,
static_cast<int>(n_recs),
@@ -965,7 +960,7 @@ corrupted:
/* Allocate a new page to the index */
const uint16_t page_level = btr_page_get_level(page);
- new_block = btr_page_alloc(cursor->index, page_id.page_no() + 1,
+ new_block = btr_page_alloc(cursor->index(), page_id.page_no() + 1,
FSP_UP, page_level, mtr, mtr, err);
if (UNIV_UNLIKELY(!new_block)) {
return nullptr;
@@ -977,7 +972,7 @@ corrupted:
to contain FIL_NULL in FIL_PAGE_PREV at this stage. */
memset_aligned<4>(new_block->page.frame + FIL_PAGE_PREV, 0, 4);
}
- btr_page_create(new_block, new_page_zip, cursor->index,
+ btr_page_create(new_block, new_page_zip, cursor->index(),
page_level, mtr);
new_page = buf_block_get_frame(new_block);
@@ -985,7 +980,7 @@ corrupted:
/* Set new ssn to the new page and page. */
page_set_ssn_id(new_block, new_page_zip, current_ssn, mtr);
- next_ssn = rtr_get_new_ssn_id(cursor->index);
+ next_ssn = rtr_get_new_ssn_id(cursor->index());
page_set_ssn_id(block, page_zip, next_ssn, mtr);
@@ -998,7 +993,7 @@ corrupted:
|| (*err = rtr_split_page_move_rec_list(rtr_split_node_array,
first_rec_group,
new_block, block,
- first_rec, cursor->index,
+ first_rec, cursor->index(),
*heap, mtr))) {
if (*err != DB_FAIL) {
return nullptr;
@@ -1021,7 +1016,7 @@ corrupted:
ut_a(new_page_zip);
page_zip_copy_recs(new_block,
- page_zip, page, cursor->index, mtr);
+ page_zip, page, cursor->index(), mtr);
page_cursor = btr_cur_get_page_cur(cursor);
@@ -1056,7 +1051,7 @@ corrupted:
lock_rtr_move_rec_list(new_block, block, rec_move, moved);
const ulint n_core = page_level
- ? 0 : cursor->index->n_core_fields;
+ ? 0 : cursor->index()->n_core_fields;
/* Delete recs in first group from the new page. */
for (cur_split_node = rtr_split_node_array;
@@ -1076,11 +1071,11 @@ corrupted:
*offsets = rec_get_offsets(
page_cur_get_rec(page_cursor),
- cursor->index, *offsets, n_core,
+ cursor->index(), *offsets, n_core,
ULINT_UNDEFINED, heap);
page_cur_delete_rec(page_cursor,
- cursor->index, *offsets, mtr);
+ *offsets, mtr);
n++;
}
}
@@ -1093,32 +1088,30 @@ corrupted:
block, page_cursor);
*offsets = rec_get_offsets(
page_cur_get_rec(page_cursor),
- cursor->index, *offsets, n_core,
+ page_cursor->index, *offsets, n_core,
ULINT_UNDEFINED, heap);
- page_cur_delete_rec(page_cursor,
- cursor->index, *offsets, mtr);
+ page_cur_delete_rec(page_cursor, *offsets,
+ mtr);
}
}
#ifdef UNIV_GIS_DEBUG
- ut_ad(page_validate(new_page, cursor->index));
- ut_ad(page_validate(page, cursor->index));
+ ut_ad(page_validate(new_page, cursor->index()));
+ ut_ad(page_validate(page, cursor->index()));
#endif
}
/* Insert the new rec to the proper page. */
cur_split_node = end_split_node - 1;
- if (cur_split_node->n_node != first_rec_group) {
- insert_block = new_block;
- } else {
- insert_block = block;
- }
/* Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
+ page_cursor->block = cur_split_node->n_node != first_rec_group
+ ? new_block : block;
+
ulint up_match = 0, low_match = 0;
- if (page_cur_search_with_match(insert_block, cursor->index, tuple,
+ if (page_cur_search_with_match(tuple,
PAGE_CUR_LE, &up_match, &low_match,
page_cursor, nullptr)) {
goto corrupted;
@@ -1133,7 +1126,7 @@ corrupted:
goto after_insert; }
);
- rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
+ rec = page_cur_tuple_insert(page_cursor, tuple,
offsets, heap, n_ext, mtr);
/* If insert did not fit, try page reorganization.
@@ -1141,14 +1134,13 @@ corrupted:
attempted this already. */
if (rec == NULL) {
if (!is_page_cur_get_page_zip(page_cursor)
- && btr_page_reorganize(page_cursor, cursor->index, mtr)) {
+ && btr_page_reorganize(page_cursor, mtr)) {
rec = page_cur_tuple_insert(page_cursor, tuple,
- cursor->index, offsets,
+ offsets,
heap, n_ext, mtr);
}
- /* If insert fail, we will try to split the insert_block
- again. */
+ /* If insert fail, we will try to split the block again. */
}
#ifdef UNIV_DEBUG
@@ -1156,8 +1148,8 @@ after_insert:
#endif
/* Calculate the mbr on the upper half-page, and the mbr on
original page. */
- rtr_page_cal_mbr(cursor->index, block, &mbr, *heap);
- rtr_page_cal_mbr(cursor->index, new_block, &new_mbr, *heap);
+ rtr_page_cal_mbr(cursor->index(), block, &mbr, *heap);
+ rtr_page_cal_mbr(cursor->index(), new_block, &new_mbr, *heap);
prdt.data = &mbr;
new_prdt.data = &new_mbr;
@@ -1175,7 +1167,8 @@ after_insert:
/* Save the new ssn to the root page, since we need to reinit
the first ssn value from it after restart server. */
- root_block = btr_root_block_get(cursor->index, RW_SX_LATCH, mtr, err);
+ root_block = btr_root_block_get(cursor->index(), RW_SX_LATCH,
+ mtr, err);
if (UNIV_UNLIKELY(!root_block)) {
return nullptr;
}
@@ -1187,8 +1180,8 @@ after_insert:
again. */
if (!rec) {
/* We play safe and reset the free bits for new_page */
- if (!dict_index_is_clust(cursor->index)
- && !cursor->index->table->is_temporary()) {
+ if (!dict_index_is_clust(cursor->index())
+ && !cursor->index()->table->is_temporary()) {
ibuf_reset_free_bits(new_block);
ibuf_reset_free_bits(block);
}
@@ -1205,16 +1198,16 @@ after_insert:
if (UNIV_UNLIKELY(!i_rec)) {
goto corrupted;
}
- btr_cur_position(cursor->index, i_rec, block, cursor);
+ btr_cur_position(cursor->index(), i_rec, block, cursor);
goto func_start;
}
#ifdef UNIV_GIS_DEBUG
- ut_ad(page_validate(buf_block_get_frame(block), cursor->index));
- ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index));
+ ut_ad(page_validate(buf_block_get_frame(block), cursor->index()));
+ ut_ad(page_validate(buf_block_get_frame(new_block), cursor->index()));
- ut_ad(!rec || rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets));
#endif
MONITOR_INC(MONITOR_INDEX_SPLIT);
@@ -1234,14 +1227,13 @@ rtr_ins_enlarge_mbr(
rtr_mbr_t new_mbr;
buf_block_t* block;
mem_heap_t* heap;
- dict_index_t* index = btr_cur->index;
page_cur_t* page_cursor;
rec_offs* offsets;
node_visit_t* node_visit;
btr_cur_t cursor;
page_t* page;
- ut_ad(dict_index_is_spatial(index));
+ ut_ad(btr_cur->index()->is_spatial());
/* If no rtr_info or rtree is one level tree, return. */
if (!btr_cur->rtr_info || btr_cur->tree_height == 1) {
@@ -1269,20 +1261,20 @@ rtr_ins_enlarge_mbr(
}
/* Calculate the mbr of the child page. */
- rtr_page_cal_mbr(index, block, &new_mbr, heap);
+ rtr_page_cal_mbr(page_cursor->index, block, &new_mbr, heap);
/* Get father block. */
- cursor.init();
+ cursor.page_cur.index = page_cursor->index;
+ cursor.page_cur.block = block;
offsets = rtr_page_get_father_block(
- NULL, heap, index, block, mtr, btr_cur, &cursor);
+ NULL, heap, mtr, btr_cur, &cursor);
page = buf_block_get_frame(block);
/* Update the mbr field of the rec. */
rtr_update_mbr_field(&cursor, offsets, NULL, page,
&new_mbr, NULL, mtr);
- page_cursor = btr_cur_get_page_cur(&cursor);
- block = page_cur_get_block(page_cursor);
+ block = btr_cur_get_block(&cursor);
}
mem_heap_free(heap);
@@ -1338,6 +1330,7 @@ rtr_page_copy_rec_list_end_no_locks(
return DB_CORRUPTION;
}
page_cur_position(cur_rec, new_block, &page_cur);
+ page_cur.index = index;
/* Copy records from the original page to the new page */
while (!page_cur_is_after_last(&cur1)) {
@@ -1399,7 +1392,7 @@ move_to_prev:
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap);
- ins_rec = page_cur_insert_rec_low(&page_cur, index,
+ ins_rec = page_cur_insert_rec_low(&page_cur,
cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION;
@@ -1461,6 +1454,7 @@ rtr_page_copy_rec_list_start_no_locks(
return DB_CORRUPTION;
}
page_cur_position(cur_rec, new_block, &page_cur);
+ page_cur.index = index;
while (page_cur_get_rec(&cur1) != rec) {
rec_t* cur1_rec = page_cur_get_rec(&cur1);
@@ -1522,7 +1516,7 @@ move_to_prev:
offsets1 = rec_get_offsets(cur1_rec, index, offsets1, n_core,
ULINT_UNDEFINED, &heap);
- ins_rec = page_cur_insert_rec_low(&page_cur, index,
+ ins_rec = page_cur_insert_rec_low(&page_cur,
cur1_rec, offsets1, mtr);
if (UNIV_UNLIKELY(!ins_rec || moved >= max_move)) {
return DB_CORRUPTION;
@@ -1560,7 +1554,7 @@ rtr_merge_mbr_changed(
ulint len;
bool changed = false;
- ut_ad(dict_index_is_spatial(cursor->index));
+ ut_ad(cursor->index()->is_spatial());
rec = btr_cur_get_rec(cursor);
@@ -1640,11 +1634,11 @@ rtr_check_same_block(
btr_cur_t* cursor, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
- buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap) /*!< in: memory heap */
{
- ulint page_no = childb->page.id().page_no();
+ const uint32_t page_no =
+ btr_cur_get_block(cursor)->page.id().page_no();
rec_offs* offsets;
rec_t* rec = page_get_infimum_rec(parentb->page.frame);
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index 03e386a6736..207d49abeba 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -95,7 +95,7 @@ rtr_pcur_getnext_from_path(
/*!< in: index tree locked */
mtr_t* mtr) /*!< in: mtr */
{
- dict_index_t* index = btr_cur->index;
+ dict_index_t* index = btr_cur->index();
bool found = false;
page_cur_t* page_cursor;
ulint level = 0;
@@ -298,6 +298,7 @@ rtr_pcur_getnext_from_path(
page_cursor = btr_cur_get_page_cur(btr_cur);
page_cursor->rec = NULL;
+ page_cursor->block = block;
if (mode == PAGE_CUR_RTREE_LOCATE) {
if (target_level == 0 && level == 0) {
@@ -306,7 +307,7 @@ rtr_pcur_getnext_from_path(
found = false;
if (!page_cur_search_with_match(
- block, index, tuple, PAGE_CUR_LE,
+ tuple, PAGE_CUR_LE,
&up_match, &low_match,
btr_cur_get_page_cur(btr_cur), nullptr)
&& low_match
@@ -437,11 +438,11 @@ rtr_pcur_getnext_from_path(
const rec_t* rec = btr_cur_get_rec(btr_cur);
- if (page_rec_is_infimum(rec) || page_rec_is_supremum(rec)) {
- mtr_commit(mtr);
- mtr_start(mtr);
+ if (!page_rec_is_user_rec(rec)) {
+ mtr->commit();
+ mtr->start();
} else if (!index_locked) {
- mtr_memo_release(mtr, &index->lock, MTR_MEMO_X_LOCK);
+ mtr->release(index->lock);
}
return(found);
@@ -533,6 +534,7 @@ rtr_pcur_open(
/* Search with the tree cursor */
btr_cur_t* btr_cursor = btr_pcur_get_btr_cur(cursor);
+ btr_cursor->page_cur.index = index;
btr_cursor->rtr_info = rtr_create_rtr_info(false, false,
btr_cursor, index);
@@ -548,7 +550,7 @@ rtr_pcur_open(
mtr->lock_upgrade(index->lock);
}
- if (btr_cur_search_to_nth_level(index, 0, tuple, PAGE_CUR_RTREE_LOCATE,
+ if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_RTREE_LOCATE,
latch_mode,
btr_cursor, mtr) != DB_SUCCESS) {
return true;
@@ -600,24 +602,16 @@ rtr_pcur_open(
}
/* Get the rtree page father.
-@param[in] index rtree index
-@param[in] block child page in the index
@param[in,out] mtr mtr
@param[in] sea_cur search cursor, contains information
about parent nodes in search
@param[out] cursor cursor on node pointer record,
its page x-latched
@return whether the cursor was successfully positioned */
-bool
-rtr_page_get_father(
- dict_index_t* index,
- buf_block_t* block,
- mtr_t* mtr,
- btr_cur_t* sea_cur,
- btr_cur_t* cursor)
+bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
{
mem_heap_t *heap = mem_heap_create(100);
- rec_offs *offsets= rtr_page_get_father_block(nullptr, heap, index, block,
+ rec_offs *offsets= rtr_page_get_father_block(nullptr, heap,
mtr, sea_cur, cursor);
mem_heap_free(heap);
return offsets != nullptr;
@@ -628,7 +622,6 @@ MY_ATTRIBUTE((warn_unused_result))
Returns the upper level node pointer to a R-Tree page. It is assumed
that mtr holds an x-latch on the tree. */
static const rec_t* rtr_get_father_node(
- dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
tuple must be set so that it cannot get
@@ -641,6 +634,7 @@ static const rec_t* rtr_get_father_node(
{
const rec_t* rec = nullptr;
auto had_rtr = btr_cur->rtr_info;
+ dict_index_t* const index = btr_cur->index();
/* Try to optimally locate the parent node. Level should always
less than sea_cur->tree_height unless the root is splitting */
@@ -674,7 +668,7 @@ static const rec_t* rtr_get_father_node(
btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index);
- if (btr_cur_search_to_nth_level(index, level, tuple,
+ if (btr_cur_search_to_nth_level(level, tuple,
PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, mtr)
!= DB_SUCCESS) {
@@ -758,7 +752,7 @@ rtr_page_get_father_node_ptr(
sea_cur = NULL;
}
- const rec_t* node_ptr = rtr_get_father_node(index, level + 1, tuple,
+ const rec_t* node_ptr = rtr_get_father_node(level + 1, tuple,
sea_cur, cursor,
page_no, mtr);
if (!node_ptr) {
@@ -786,23 +780,18 @@ rtr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
- dict_index_t* index, /*!< in: b-tree index */
- buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
its page x-latched */
{
- rec_t* rec = page_rec_get_next(
- page_get_infimum_rec(buf_block_get_frame(block)));
- if (!rec) {
- return nullptr;
- }
- btr_cur_position(index, rec, block, cursor);
-
- return(rtr_page_get_father_node_ptr(offsets, heap, sea_cur,
- cursor, mtr));
+ rec_t *rec=
+ page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
+ if (!rec)
+ return nullptr;
+ cursor->page_cur.rec= rec;
+ return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
}
/*******************************************************************//**
@@ -820,7 +809,7 @@ rtr_create_rtr_info(
{
rtr_info_t* rtr_info;
- index = index ? index : cursor->index;
+ index = index ? index : cursor->index();
ut_ad(index);
rtr_info = static_cast<rtr_info_t*>(ut_zalloc_nokey(sizeof(*rtr_info)));
@@ -1157,6 +1146,7 @@ rtr_cur_restore_position(
ut_ad(mtr->is_active());
index = btr_cur_get_index(btr_cur);
+ ut_ad(r_cursor->index() == btr_cur->index());
if (r_cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|| r_cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
@@ -1216,7 +1206,6 @@ rtr_cur_restore_position(
/* Page has changed, for R-Tree, the page cannot be shrunk away,
so we search the page and its right siblings */
- buf_block_t* block;
node_seq_t page_ssn;
const page_t* page;
page_cur_t* page_cursor;
@@ -1236,21 +1225,21 @@ rtr_cur_restore_position(
search_again:
ulint up_match = 0, low_match = 0;
- block = buf_page_get_gen(
+ page_cursor->block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
zip_size, RW_X_LATCH, NULL, BUF_GET, mtr);
- if (!block) {
+ if (!page_cursor->block) {
corrupted:
ret = false;
goto func_exit;
}
/* Get the page SSN */
- page = buf_block_get_frame(block);
+ page = buf_block_get_frame(page_cursor->block);
page_ssn = page_get_ssn_id(page);
- if (page_cur_search_with_match(block, index, tuple, PAGE_CUR_LE,
+ if (page_cur_search_with_match(tuple, PAGE_CUR_LE,
&up_match, &low_match, page_cursor,
nullptr)) {
goto corrupted;
@@ -1405,7 +1394,7 @@ rtr_non_leaf_insert_stack_push(
page_cur_position(rec, block, btr_pcur_get_page_cur(my_cursor));
- (btr_pcur_get_btr_cur(my_cursor))->index = index;
+ btr_pcur_get_page_cur(my_cursor)->index = index;
new_seq = rtr_get_current_ssn_id(index);
rtr_non_leaf_stack_push(path, block->page.id().page_no(),
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 304e8990075..9b81aa9307c 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1548,7 +1548,8 @@ static void innodb_drop_database(handlerton*, char *path)
std::vector<pfs_os_file_t> to_close;
mtr_t mtr;
mtr.start();
- err= btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE,
+ pcur.btr_cur.page_cur.index = sys_index;
+ err= btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
if (err != DB_SUCCESS)
goto err_exit;
@@ -15055,8 +15056,6 @@ inline int ha_innobase::defragment_table()
}
btr_pcur_t pcur;
- pcur.btr_cur.index = nullptr;
- btr_pcur_init(&pcur);
mtr_t mtr;
mtr.start();
@@ -15074,9 +15073,9 @@ inline int ha_innobase::defragment_table()
btr_pcur_move_to_next(&pcur, &mtr);
btr_pcur_store_position(&pcur, &mtr);
mtr.commit();
- ut_ad(pcur.btr_cur.index == index);
+ ut_ad(pcur.index() == index);
const bool interrupted= btr_defragment_add_index(&pcur, m_user_thd);
- btr_pcur_free(&pcur);
+ ut_free(pcur.old_rec_buf);
if (interrupted)
return ER_QUERY_INTERRUPTED;
}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index f477355acae..fbb640e7c62 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -2158,10 +2158,11 @@ next_page:
&mtr);
if (!block)
goto non_empty;
- btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr);
page_cur_set_before_first(block, cur);
if (UNIV_UNLIKELY(!page_cur_move_to_next(cur)))
goto non_empty;
+ const auto s= mtr.get_savepoint();
+ mtr.rollback_to_savepoint(s - 2, s - 1);
}
rec= page_cur_get_rec(cur);
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 36dfb99701d..80e2993055b 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -2335,9 +2335,11 @@ work_around:
space_id, page_nos[i], heap);
loop:
btr_pcur_t pcur;
+ pcur.btr_cur.page_cur.index = ibuf.index;
+
ibuf_mtr_start(&mtr);
- if (btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
- BTR_MODIFY_LEAF, &pcur, &mtr)
+ if (btr_pcur_open(tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF, &pcur, 0, &mtr)
!= DB_SUCCESS) {
goto done;
}
@@ -2462,8 +2464,9 @@ ibuf_merge_space(
/* Position the cursor on the first matching record. */
- dberr_t err = btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.btr_cur.page_cur.index = ibuf.index;
+ dberr_t err = btr_pcur_open(tuple, PAGE_CUR_GE,
+ BTR_SEARCH_LEAF, &pcur, 0, &mtr);
ut_ad(err != DB_SUCCESS || page_validate(btr_pcur_get_page(&pcur),
ibuf.index));
@@ -3207,9 +3210,9 @@ ibuf_insert_low(
}
ibuf_mtr_start(&mtr);
+ pcur.btr_cur.page_cur.index = ibuf.index;
- err = btr_pcur_open(ibuf.index, ibuf_entry, PAGE_CUR_LE, mode, &pcur,
- &mtr);
+ err = btr_pcur_open(ibuf_entry, PAGE_CUR_LE, mode, &pcur, 0, &mtr);
if (err != DB_SUCCESS) {
func_exit:
ibuf_mtr_commit(&mtr);
@@ -3575,30 +3578,27 @@ dberr_t
ibuf_insert_to_index_page_low(
/*==========================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */
- buf_block_t* block, /*!< in/out: index page where the buffered
- entry should be placed */
- dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t* heap, /*!< in/out: memory heap */
mtr_t* mtr, /*!< in/out: mtr */
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */
{
- if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
+ if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
return DB_SUCCESS;
/* Page reorganization or recompression should already have been
attempted by page_cur_tuple_insert(). Besides, per
ibuf_index_page_calc_free_zip() the page should not have been
recompressed or reorganized. */
- ut_ad(!is_buf_block_get_page_zip(block));
+ ut_ad(!is_buf_block_get_page_zip(page_cur->block));
/* If the record did not fit, reorganize */
- if (dberr_t err= btr_page_reorganize(page_cur, index, mtr))
+ if (dberr_t err= btr_page_reorganize(page_cur, mtr))
return err;
/* This time the record must fit */
- if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
+ if (page_cur_tuple_insert(page_cur, entry, offsets, &heap, 0, mtr))
return DB_SUCCESS;
return DB_CORRUPTION;
@@ -3655,8 +3655,10 @@ ibuf_insert_to_index_page(
}
ulint up_match = 0, low_match = 0;
+ page_cur.index = index;
+ page_cur.block = block;
- if (page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
+ if (page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)) {
return DB_CORRUPTION;
@@ -3703,7 +3705,7 @@ ibuf_insert_to_index_page(
if (!row_upd_changes_field_size_or_external(index, offsets,
update)
&& (!page_zip || btr_cur_update_alloc_zip(
- page_zip, &page_cur, index, offsets,
+ page_zip, &page_cur, offsets,
rec_offs_size(offsets), false, mtr))) {
/* This is the easy case. Do something similar
to btr_cur_update_in_place(). */
@@ -3744,7 +3746,7 @@ ibuf_insert_to_index_page(
/* Delete the different-length record, and insert the
buffered one. */
- page_cur_delete_rec(&page_cur, index, offsets, mtr);
+ page_cur_delete_rec(&page_cur, offsets, mtr);
if (!(page_cur_move_to_prev(&page_cur))) {
err = DB_CORRUPTION;
goto updated_in_place;
@@ -3753,8 +3755,8 @@ ibuf_insert_to_index_page(
offsets = NULL;
}
- err = ibuf_insert_to_index_page_low(entry, block, index,
- &offsets, heap, mtr, &page_cur);
+ err = ibuf_insert_to_index_page_low(entry, &offsets, heap, mtr,
+ &page_cur);
updated_in_place:
mem_heap_free(heap);
@@ -3770,16 +3772,18 @@ ibuf_set_del_mark(
/*==============*/
const dtuple_t* entry, /*!< in: entry */
buf_block_t* block, /*!< in/out: block */
- const dict_index_t* index, /*!< in: record descriptor */
+ dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t page_cur;
+ page_cur.block = block;
+ page_cur.index = index;
ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
- if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
+ if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)
&& low_match == dtuple_get_n_fields(entry)) {
@@ -3831,6 +3835,8 @@ ibuf_delete(
before latching any further pages */
{
page_cur_t page_cur;
+ page_cur.block = block;
+ page_cur.index = index;
ulint up_match = 0, low_match = 0;
ut_ad(ibuf_inside(mtr));
@@ -3838,7 +3844,7 @@ ibuf_delete(
ut_ad(!index->is_spatial());
ut_ad(!index->is_clust());
- if (!page_cur_search_with_match(block, index, entry, PAGE_CUR_LE,
+ if (!page_cur_search_with_match(entry, PAGE_CUR_LE,
&up_match, &low_match, &page_cur,
nullptr)
&& low_match == dtuple_get_n_fields(entry)) {
@@ -3891,7 +3897,7 @@ ibuf_delete(
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
- page_cur_delete_rec(&page_cur, index, offsets, mtr);
+ page_cur_delete_rec(&page_cur, offsets, mtr);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
@@ -4193,13 +4199,14 @@ dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block,
memset(mops, 0, sizeof(mops));
memset(dops, 0, sizeof(dops));
+ pcur.btr_cur.page_cur.index = ibuf.index;
loop:
ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for this
index page */
- if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
+ if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) {
err = DB_CORRUPTION;
@@ -4352,7 +4359,6 @@ loop:
goto loop;
} else if (btr_pcur_is_after_last_on_page(&pcur)) {
ibuf_mtr_commit(&mtr);
- ut_free(pcur.old_rec_buf);
goto loop;
}
}
@@ -4400,13 +4406,15 @@ void ibuf_delete_for_discarded_space(ulint space)
search_tuple = ibuf_search_tuple_build(space, 0, heap);
memset(dops, 0, sizeof(dops));
+ pcur.btr_cur.page_cur.index = ibuf.index;
+
loop:
log_free_check();
ibuf_mtr_start(&mtr);
/* Position pcur in the insert buffer at the first entry for the
space */
- if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
+ if (btr_pcur_open_on_user_rec(search_tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF, &pcur, &mtr)
!= DB_SUCCESS) {
goto leave_loop;
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 0fd1f6aeee6..a2aa46b62da 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -132,17 +132,6 @@ inline uint32_t btr_page_get_prev(const page_t* page)
}
/**************************************************************//**
-Releases the latch on a leaf page and bufferunfixes it. */
-UNIV_INLINE
-void
-btr_leaf_page_release(
-/*==================*/
- buf_block_t* block, /*!< in: buffer block */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
- BTR_MODIFY_LEAF */
- mtr_t* mtr) /*!< in: mtr */
- MY_ATTRIBUTE((nonnull));
-/**************************************************************//**
Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since
we read the last field according to offsets and assume that it contains
@@ -262,15 +251,12 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
+@param cursor page cursor
+@param mtr mini-transaction
@return error code
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
-dberr_t
-btr_page_reorganize(
-/*================*/
- page_cur_t* cursor, /*!< in/out: page cursor */
- dict_index_t* index, /*!< in: the index tree of the page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Decide if the page should be split at the convergence point of inserts
converging to the left.
@param[in] cursor insert position
@@ -348,13 +334,10 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
}
/** Seek to the parent page of a B-tree page.
-@param[in,out] index b-tree
-@param[in] block child page
@param[in,out] mtr mini-transaction
-@param[out] cursor cursor pointing to the x-latched parent page
+@param[in,out] cursor cursor pointing to the x-latched parent page
@return whether the cursor was successfully positioned */
-bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
- btr_cur_t* cursor)
+bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
MY_ATTRIBUTE((nonnull,warn_unused_result));
#ifdef UNIV_DEBUG
/************************************************************//**
diff --git a/storage/innobase/include/btr0btr.inl b/storage/innobase/include/btr0btr.inl
index f92622cc400..9a9e39b6b4c 100644
--- a/storage/innobase/include/btr0btr.inl
+++ b/storage/innobase/include/btr0btr.inl
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2021, MariaDB Corporation.
+Copyright (c) 2015, 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
@@ -24,10 +24,7 @@ The B-tree
Created 6/2/1994 Heikki Tuuri
*******************************************************/
-#include "mach0data.h"
-#include "mtr0mtr.h"
#include "mtr0log.h"
-#include "page0zip.h"
/**************************************************************//**
Gets the index id field of a page.
@@ -112,38 +109,3 @@ btr_node_ptr_get_child_page_no(
return(page_no);
}
-
-/**************************************************************//**
-Releases the latches on a leaf page and bufferunfixes it. */
-UNIV_INLINE
-void
-btr_leaf_page_release(
-/*==================*/
- buf_block_t* block, /*!< in: buffer block */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
- BTR_MODIFY_LEAF */
- mtr_t* mtr) /*!< in: mtr */
-{
- ut_ad(latch_mode == BTR_SEARCH_LEAF
- || latch_mode == BTR_MODIFY_LEAF
- || latch_mode == BTR_NO_LATCHES);
-
- ut_ad(!mtr->memo_contains_flagged(block, MTR_MEMO_MODIFY));
-
- mtr_memo_type_t mode;
- switch (latch_mode) {
- case BTR_SEARCH_LEAF:
- mode = MTR_MEMO_PAGE_S_FIX;
- break;
- case BTR_MODIFY_LEAF:
- mode = MTR_MEMO_PAGE_X_FIX;
- break;
- case BTR_NO_LATCHES:
- mode = MTR_MEMO_BUF_FIX;
- break;
- default:
- ut_a(0);
- }
-
- mtr->memo_release(block, mode);
-}
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 5158b125404..aa890be9936 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -96,7 +96,7 @@ btr_cur_get_page(
Returns the index of a cursor.
@param cursor b-tree cursor
@return index */
-#define btr_cur_get_index(cursor) ((cursor)->index)
+#define btr_cur_get_index(cursor) ((cursor)->index())
/*********************************************************//**
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -148,7 +148,6 @@ to node pointer page number fields on the upper levels of the tree!
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
-@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@@ -166,28 +165,13 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
@param mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@return DB_SUCCESS on success or error code otherwise */
-dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
+dberr_t btr_cur_search_to_nth_level(ulint level,
const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_cur_t *cursor, mtr_t *mtr,
ib_uint64_t autoinc= 0);
-/*****************************************************************//**
-Opens a cursor at either end of an index.
-@return DB_SUCCESS or error code */
-dberr_t
-btr_cur_open_at_index_side(
- bool from_left, /*!< in: true if open to the low end,
- false if to the high end */
- dict_index_t* index, /*!< in: index */
- btr_latch_mode latch_mode, /*!< in: latch mode */
- btr_cur_t* cursor, /*!< in/out: cursor */
- ulint level, /*!< in: level to search for
- (0=leaf) */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
-
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree.
@return true if the index is available and we have put the cursor, false
@@ -282,7 +266,6 @@ btr_cur_update_alloc_zip_func(
/*==========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
- dict_index_t* index, /*!< in: the index corresponding to cursor */
#ifdef UNIV_DEBUG
rec_offs* offsets,/*!< in/out: offsets of the cursor record */
#endif /* UNIV_DEBUG */
@@ -292,11 +275,11 @@ btr_cur_update_alloc_zip_func(
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_DEBUG
-# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
- btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
+# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
+ btr_cur_update_alloc_zip_func(page_zip,cursor,offsets,len,cr,mtr)
#else /* UNIV_DEBUG */
-# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
- btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
+# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
+ btr_cur_update_alloc_zip_func(page_zip,cursor,len,cr,mtr)
#endif /* UNIV_DEBUG */
/** Apply an update vector to a record. No field size changes are allowed.
@@ -753,7 +736,6 @@ enum btr_cur_method {
/** The tree cursor: the definition appears here only for the compiler
to know struct size! */
struct btr_cur_t {
- dict_index_t* index; /*!< index where positioned */
page_cur_t page_cur; /*!< page cursor */
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
buf_block_t* left_block; /*!< this field is used to store
@@ -818,28 +800,10 @@ struct btr_cur_t {
information of the path through
the tree */
rtr_info_t* rtr_info; /*!< rtree search info */
- btr_cur_t():thr(NULL), rtr_info(NULL) {}
- /* default values */
- /** Zero-initialize all fields */
- void init()
- {
- index = NULL;
- memset(&page_cur, 0, sizeof page_cur);
- purge_node = NULL;
- left_block = NULL;
- thr = NULL;
- flag = btr_cur_method(0);
- tree_height = 0;
- up_match = 0;
- up_bytes = 0;
- low_match = 0;
- low_bytes = 0;
- n_fields = 0;
- n_bytes = 0;
- fold = 0;
- path_arr = NULL;
- rtr_info = NULL;
- }
+ btr_cur_t() { memset((void*) this, 0, sizeof *this); }
+
+ dict_index_t *index() const { return page_cur.index; }
+ buf_block_t *block() const { return page_cur.block; }
/** Open the cursor on the first or last record.
@param first true=first record, false=last record
diff --git a/storage/innobase/include/btr0cur.inl b/storage/innobase/include/btr0cur.inl
index 76a2d3be49c..955cf34288e 100644
--- a/storage/innobase/include/btr0cur.inl
+++ b/storage/innobase/include/btr0cur.inl
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2021, MariaDB Corporation.
+Copyright (c) 2018, 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
@@ -72,7 +72,7 @@ btr_cur_position(
btr_cur_t* cursor) /*!< out: cursor */
{
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
- cursor->index = index;
+ cursor->page_cur.index = index;
}
/*********************************************************************//**
@@ -98,14 +98,14 @@ btr_cur_compress_recommendation(
if (!page_has_siblings(page)
|| page_get_data_size(page)
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just
one page: we recommend compression if this is not the
root page. */
- return cursor->index->page
+ return cursor->index()->page
!= btr_cur_get_block(cursor)->page.id().page_no();
}
@@ -133,14 +133,14 @@ btr_cur_can_delete_without_compress(
if (!page_has_siblings(page) || page_get_n_recs(page) < 2
|| page_get_data_size(page) - rec_size
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend
compression if this is not the root page. */
- return cursor->index->page
+ return cursor->index()->page
== btr_cur_get_block(cursor)->page.id().page_no();
}
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index ba4c49c2f9b..cd8eacdc212 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -46,13 +46,6 @@ of a scroll cursor easier */
};
/**************************************************************//**
-Allocates memory for a persistent cursor object and initializes the cursor.
-@return own: persistent cursor */
-btr_pcur_t*
-btr_pcur_create_for_mysql(void);
-/*============================*/
-
-/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
void
@@ -61,12 +54,6 @@ btr_pcur_reset(
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
/**************************************************************//**
-Frees the memory for a persistent cursor object. */
-void
-btr_pcur_free_for_mysql(
-/*====================*/
- btr_pcur_t* cursor); /*!< in, own: persistent cursor */
-/**************************************************************//**
Copies the stored position of a pcur to another pcur. */
void
btr_pcur_copy_stored_position(
@@ -83,21 +70,11 @@ btr_pcur_init(
/*==========*/
btr_pcur_t* pcur); /*!< in: persistent cursor */
-/** Free old_rec_buf.
-@param[in] pcur Persistent cursor holding old_rec to be freed. */
-UNIV_INLINE
-void
-btr_pcur_free(
- btr_pcur_t* pcur);
-
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
-btr_pcur_open_low(
-/*==============*/
- dict_index_t* index, /*!< in: index */
- ulint level, /*!< in: level in the btree */
+btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -111,11 +88,8 @@ btr_pcur_open_low(
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-#define btr_pcur_open(i,t,md,l,c,m) \
- btr_pcur_open_low(i,0,t,md,l,c,0,m)
/** Opens an persistent cursor to an index tree without initializing the
cursor.
-@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -126,7 +100,7 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
-dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
+dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr);
@@ -370,7 +344,7 @@ struct btr_pcur_t
/** if cursor position is stored, contains an initial segment of the
latest record cursor was positioned either on, before or after */
rec_t *old_rec= nullptr;
- /** btr_cur.index->n_core_fields when old_rec was copied */
+ /** btr_cur.index()->n_core_fields when old_rec was copied */
uint16 old_n_core_fields= 0;
/** number of fields in old_rec */
uint16 old_n_fields= 0;
@@ -390,13 +364,11 @@ struct btr_pcur_t
trx_t *trx_if_known= nullptr;
/** a dynamically allocated buffer for old_rec */
byte *old_rec_buf= nullptr;
- /** old_rec_buf size if old_rec_buf is not nullptr */
+ /** old_rec_buf size if old_rec_buf is not NULL */
ulint buf_size= 0;
- btr_pcur_t() : btr_cur() { btr_cur.init(); }
-
/** Return the index of this persistent cursor */
- dict_index_t *index() const { return(btr_cur.index); }
+ dict_index_t *index() const { return(btr_cur.index()); }
MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Restores the stored position of a persistent cursor bufferfixing
the page and obtaining the specified latches. If the cursor position
@@ -467,7 +439,6 @@ MY_ATTRIBUTE((nonnull, warn_unused_result))
inline
dberr_t
btr_pcur_open_on_user_rec(
- dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */
btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF or
@@ -478,7 +449,7 @@ btr_pcur_open_on_user_rec(
{
ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G);
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
- if (dberr_t err= btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr))
+ if (dberr_t err= btr_pcur_open(tuple, mode, latch_mode, cursor, 0, mtr))
return err;
if (!btr_pcur_is_after_last_on_page(cursor) ||
btr_pcur_is_after_last_in_tree(cursor))
diff --git a/storage/innobase/include/btr0pcur.inl b/storage/innobase/include/btr0pcur.inl
index 1f7605e96a8..551f8f20fca 100644
--- a/storage/innobase/include/btr0pcur.inl
+++ b/storage/innobase/include/btr0pcur.inl
@@ -299,24 +299,11 @@ btr_pcur_init(
pcur->btr_cur.rtr_info = NULL;
}
-/** Free old_rec_buf.
-@param[in] pcur Persistent cursor holding old_rec to be freed. */
-UNIV_INLINE
-void
-btr_pcur_free(
- btr_pcur_t* pcur)
-{
- ut_free(pcur->old_rec_buf);
-}
-
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
-btr_pcur_open_low(
-/*==============*/
- dict_index_t* index, /*!< in: index */
- ulint level, /*!< in: level in the btree */
+btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -330,20 +317,18 @@ btr_pcur_open_low(
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
{
- ut_ad(!index->is_spatial());
- btr_pcur_init(cursor);
+ ut_ad(!cursor->index()->is_spatial());
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known= nullptr;
- return btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
+ return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor),
mtr, autoinc);
}
/** Opens an persistent cursor to an index tree without initializing the
cursor.
-@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -354,7 +339,7 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
-dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
+dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
page_cur_mode_t mode,
btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr)
@@ -365,7 +350,7 @@ dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
cursor->trx_if_known= nullptr;
/* Search with the tree cursor */
- return btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
+ return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
}
diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h
index cb8b998f0ea..208e49c34a7 100644
--- a/storage/innobase/include/dyn0buf.h
+++ b/storage/innobase/include/dyn0buf.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 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
@@ -331,60 +331,6 @@ public:
}
/**
- Iterate over each block and call the functor.
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block(const Functor& functor) const
- {
- for (typename list_t::iterator it = m_list.begin(),
- end = m_list.end();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
- Iterate over all the blocks in reverse and call the iterator
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block_in_reverse(Functor& functor) const
- {
- for (list_t::reverse_iterator it = m_list.rbegin(),
- end = m_list.rend();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
- Iterate over all the blocks in reverse and call the iterator
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block_in_reverse(const Functor& functor) const
- {
- for (list_t::reverse_iterator it = m_list.rbegin(),
- end = m_list.rend();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
@return the first block */
block_t* front()
MY_ATTRIBUTE((warn_unused_result))
diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h
index 05b59b295c4..777f2432c93 100644
--- a/storage/innobase/include/gis0rtree.h
+++ b/storage/innobase/include/gis0rtree.h
@@ -256,23 +256,14 @@ rtr_get_mbr_from_tuple(
rtr_mbr* mbr); /*!< out: mbr to fill */
/* Get the rtree page father.
-@param[in] offsets work area for the return value
-@param[in] index rtree index
-@param[in] block child page in the index
@param[in,out] mtr mtr
@param[in] sea_cur search cursor, contains information
about parent nodes in search
-@param[out] cursor cursor on node pointer record,
+@param[in,out] cursor cursor on node pointer record,
its page x-latched
@return whether the cursor was successfully positioned */
-bool
-rtr_page_get_father(
- dict_index_t* index,
- buf_block_t* block,
- mtr_t* mtr,
- btr_cur_t* sea_cur,
- btr_cur_t* cursor)
- MY_ATTRIBUTE((nonnull(1,2,3,5), warn_unused_result));
+bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
+ MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
/************************************************************//**
Returns the father block to a page. It is assumed that mtr holds
@@ -283,8 +274,6 @@ rtr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
- dict_index_t* index, /*!< in: b-tree index */
- buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */
@@ -432,7 +421,6 @@ rtr_check_same_block(
btr_cur_t* cur, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
- buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap); /*!< in: memory heap */
/*********************************************************************//**
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index be613675e91..1b7455c046b 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -28,6 +28,8 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h"
#include "dyn0buf.h"
+#include "buf0buf.h"
+#include <vector>
/** Start a mini-transaction. */
#define mtr_start(m) (m)->start()
@@ -48,11 +50,6 @@ savepoint. */
@return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
-/** Release an object in the memo stack.
-@return true if released */
-#define mtr_memo_release(m, o, t) \
- (m)->memo_release((o), (t))
-
#ifdef UNIV_PFS_RWLOCK
# define mtr_s_lock_index(i,m) (m)->s_lock(__FILE__, __LINE__, &(i)->lock)
# define mtr_x_lock_index(i,m) (m)->x_lock(__FILE__, __LINE__, &(i)->lock)
@@ -66,19 +63,16 @@ savepoint. */
#define mtr_release_block_at_savepoint(m, s, b) \
(m)->release_block_at_savepoint((s), (b))
-#define mtr_block_sx_latch_at_savepoint(m, s, b) \
- (m)->sx_latch_at_savepoint((s), (b))
-
-#define mtr_block_x_latch_at_savepoint(m, s, b) \
- (m)->x_latch_at_savepoint((s), (b))
-
/** Mini-transaction memo stack slot. */
-struct mtr_memo_slot_t {
- /** pointer to the object */
- void* object;
-
- /** type of the stored object */
- mtr_memo_type_t type;
+struct mtr_memo_slot_t
+{
+ /** pointer to the object, or nullptr if released */
+ void *object;
+ /** type of the stored object */
+ mtr_memo_type_t type;
+
+ /** Release the object */
+ void release() const;
};
/** Mini-transaction handle and buffer */
@@ -89,14 +83,19 @@ struct mtr_t {
/** Commit the mini-transaction. */
void commit();
- /** Release latches till savepoint. To simplify the code only
- MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be
- released, otherwise it would be neccesary to add one more argument in the
- function to point out what slot types are allowed for rollback, and this
- would be overengineering as currently the function is used only in one place
- in the code.
- @param savepoint savepoint, can be obtained with get_savepoint */
- void rollback_to_savepoint(ulint savepoint);
+ /** Release latches of unmodified buffer pages.
+ @param begin first slot to release
+ @param end last slot to release, or get_savepoint() */
+ void rollback_to_savepoint(ulint begin, ulint end);
+
+ /** Release latches of unmodified buffer pages.
+ @param begin first slot to release */
+ void rollback_to_savepoint(ulint begin)
+ { rollback_to_savepoint(begin, m_memo->size()); }
+
+ /** Release the last acquired buffer page latch. */
+ void release_last_page()
+ { auto s= m_memo->size(); rollback_to_savepoint(s - 1, s); }
/** Commit a mini-transaction that is shrinking a tablespace.
@param space tablespace that is being shrunk */
@@ -117,26 +116,89 @@ struct mtr_t {
void commit_files(lsn_t checkpoint_lsn= 0);
/** @return mini-transaction savepoint (current size of m_memo) */
- ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); }
+ ulint get_savepoint() const
+ {
+ ut_ad(is_active());
+ return m_memo ? m_memo->size() : 0;
+ }
- /** Release the (index tree) s-latch stored in an mtr memo after a
- savepoint.
- @param savepoint value returned by @see set_savepoint.
- @param lock latch to release */
- inline void release_s_latch_at_savepoint(
- ulint savepoint,
- index_lock* lock);
+ /** Release the (index tree) s-latch stored in an mtr memo after a savepoint.
+ @param savepoint value returned by get_savepoint()
+ @param lock index latch to release */
+ void release_s_latch_at_savepoint(ulint savepoint, index_lock *lock)
+ {
+ ut_ad(is_active());
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.object == lock);
+ ut_ad(slot.type == MTR_MEMO_S_LOCK);
+ slot.object= nullptr;
+ lock->s_unlock();
+ }
+ /** Release the block in an mtr memo after a savepoint. */
+ void release_block_at_savepoint(ulint savepoint, buf_block_t *block)
+ {
+ ut_ad(is_active());
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.object == block);
+ ut_ad(!(slot.type & MTR_MEMO_MODIFY));
+ slot.object= nullptr;
+ block->page.unfix();
+
+ switch (slot.type) {
+ case MTR_MEMO_PAGE_S_FIX:
+ block->page.lock.s_unlock();
+ break;
+ case MTR_MEMO_PAGE_SX_FIX:
+ case MTR_MEMO_PAGE_X_FIX:
+ block->page.lock.u_or_x_unlock(slot.type == MTR_MEMO_PAGE_SX_FIX);
+ break;
+ default:
+ break;
+ }
+ }
- /** Release the block in an mtr memo after a savepoint. */
- inline void release_block_at_savepoint(
- ulint savepoint,
- buf_block_t* block);
+ /** @return if we are about to make a clean buffer block dirty */
+ static bool is_block_dirtied(const buf_page_t &b)
+ {
+ ut_ad(b.in_file());
+ ut_ad(b.frame);
+ ut_ad(b.buf_fix_count());
+ return b.oldest_modification() <= 1 && b.id().space() < SRV_TMP_SPACE_ID;
+ }
- /** SX-latch a not yet latched block after a savepoint. */
- inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block);
+ /** X-latch a not yet latched block after a savepoint. */
+ void x_latch_at_savepoint(ulint savepoint, buf_block_t *block)
+ {
+ ut_ad(is_active());
+ ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
+ MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.object == block);
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ slot.type= MTR_MEMO_PAGE_X_FIX;
+ block->page.lock.x_lock();
+ ut_ad(!block->page.is_io_fixed());
+
+ if (!m_made_dirty)
+ m_made_dirty= is_block_dirtied(block->page);
+ }
- /** X-latch a not yet latched block after a savepoint. */
- inline void x_latch_at_savepoint(ulint savepoint, buf_block_t* block);
+ /** U-latch a not yet latched block after a savepoint. */
+ void sx_latch_at_savepoint(ulint savepoint, buf_block_t *block)
+ {
+ ut_ad(is_active());
+ ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
+ MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.object == block);
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ slot.type= MTR_MEMO_PAGE_SX_FIX;
+ block->page.lock.u_lock();
+ ut_ad(!block->page.is_io_fixed());
+
+ if (!m_made_dirty)
+ m_made_dirty= is_block_dirtied(block->page);
+ }
/** @return the logging mode */
mtr_log_t get_log_mode() const
@@ -290,15 +352,17 @@ struct mtr_t {
/** Acquire an exclusive tablespace latch.
@param space tablespace */
void x_lock_space(fil_space_t *space);
- /** Release an object in the memo stack.
- @param object object
- @param type object type
- @return bool if lock released */
- bool memo_release(const void *object, ulint type);
+
+ /** Release an index latch. */
+ void release(const index_lock &lock) { release(&lock); }
+ /** Release a latch to an unmodified page. */
+ void release(const buf_block_t &block) { release(&block); }
/** Note that the mini-transaction will modify data. */
void flag_modified() { m_modifications = true; }
private:
+ /** Release an unmodified object. */
+ void release(const void *object);
/** Mark the given latched page as modified.
@param block page that will be modified */
void modify(const buf_block_t& block);
@@ -336,82 +400,93 @@ public:
@param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */
void page_lock(buf_block_t *block, ulint rw_latch);
+ /** Acquire a latch on a buffer-fixed buffer pool block.
+ @param savepoint savepoint location of the buffer-fixed block
+ @param rw_latch latch to acquire */
+ void upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch);
+
/** Register a page latch on a buffer-fixed block was buffer-fixed.
@param latch latch type */
void u_lock_register(ulint savepoint)
{
- mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint);
- ut_ad(slot->type == MTR_MEMO_BUF_FIX);
- slot->type= MTR_MEMO_PAGE_SX_FIX;
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ slot.type= MTR_MEMO_PAGE_SX_FIX;
}
/** Register a page latch on a buffer-fixed block was buffer-fixed.
@param latch latch type */
void s_lock_register(ulint savepoint)
{
- mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint);
- ut_ad(slot->type == MTR_MEMO_BUF_FIX);
- slot->type= MTR_MEMO_PAGE_S_FIX;
+ mtr_memo_slot_t &slot= m_memo->at(savepoint);
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ slot.type= MTR_MEMO_PAGE_S_FIX;
}
/** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block);
- /** Upgrade X lock to X */
+ /** Upgrade U lock to X */
void lock_upgrade(const index_lock &lock);
/** Check if we are holding tablespace latch
@param space tablespace to search for
@param shared whether to look for shared latch, instead of exclusive
@return whether space.latch is being held */
- bool memo_contains(const fil_space_t& space, bool shared= false)
+ bool memo_contains(const fil_space_t& space, bool shared= false) const
MY_ATTRIBUTE((warn_unused_result));
#ifdef UNIV_DEBUG
/** Check if we are holding an rw-latch in this mini-transaction
@param lock latch to search for
@param type held latch type
@return whether (lock,type) is contained */
- bool memo_contains(const index_lock &lock, mtr_memo_type_t type)
+ bool memo_contains(const index_lock &lock, mtr_memo_type_t type) const
MY_ATTRIBUTE((warn_unused_result));
- /** Check if memo contains the given item.
- @param object object to search
- @param flags specify types of object (can be ORred) of
- MTR_MEMO_PAGE_S_FIX ... values
- @return true if contains */
- bool memo_contains_flagged(const void* ptr, ulint flags) const;
-
- /** Check if memo contains the given page.
- @param[in] ptr pointer to within buffer frame
- @param[in] flags specify types of object with OR of
- MTR_MEMO_PAGE_S_FIX... values
- @return the block
- @retval NULL if not found */
- buf_block_t* memo_contains_page_flagged(
- const byte* ptr,
- ulint flags) const;
-
- /** @return true if mini-transaction contains modifications. */
- bool has_modifications() const { return m_modifications; }
+ /** Check if memo contains an index or buffer block latch.
+ @param object object to search
+ @param flags specify types of object latches
+ @return true if contains */
+ bool memo_contains_flagged(const void *object, ulint flags) const
+ MY_ATTRIBUTE((warn_unused_result, nonnull));
+
+ /** Check if memo contains the given page.
+ @param ptr pointer to within page frame
+ @param flags types latch to look for
+ @return the block
+ @retval nullptr if not found */
+ buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
+
+ /** @return true if mini-transaction contains modifications. */
+ bool has_modifications() const { return m_modifications; }
#endif /* UNIV_DEBUG */
- /** @return true if a record was added to the mini-transaction */
- bool is_dirty() const { return m_made_dirty; }
-
- /** Push an object to an mtr memo stack.
- @param object object
- @param type object type: MTR_MEMO_S_LOCK, ... */
- inline void memo_push(void* object, mtr_memo_type_t type);
-
- /** Check if this mini-transaction is dirtying a clean page.
- @param block block being x-fixed
- @return true if the mtr is dirtying a clean page. */
- static inline bool is_block_dirtied(const buf_block_t* block)
- MY_ATTRIBUTE((warn_unused_result));
+ /** Push an object to an mtr memo stack.
+ @param object object
+ @param type object type: MTR_MEMO_S_LOCK, ... */
+ void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
+ {
+ ut_ad(is_active());
+ /* If this mtr has U or X latched a clean page then we set
+ the m_made_dirty flag. This tells us if we need to
+ grab log_sys.flush_order_mutex at mtr_t::commit() so that we
+ can insert the dirtied page into the buf_pool.flush_list.
+
+ FIXME: Do this only when the MTR_MEMO_MODIFY flag is set! */
+ if (!m_made_dirty &&
+ (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)))
+ m_made_dirty=
+ is_block_dirtied(*static_cast<const buf_page_t*>(object));
+
+ if (!m_memo)
+ m_memo= new std::vector<mtr_memo_slot_t>(1, {object, type});
+ else
+ m_memo->emplace_back(mtr_memo_slot_t{object, type});
+ }
/** @return the size of the log is empty */
size_t get_log_size() const { return m_log.size(); }
/** @return whether the log and memo are empty */
- bool is_empty() const { return m_memo.size() == 0 && m_log.size() == 0; }
+ bool is_empty() const { return !get_savepoint() && !get_log_size(); }
/** Write an OPT_PAGE_CHECKSUM record. */
inline void page_checksum(const buf_page_t &bpage);
@@ -662,6 +737,8 @@ private:
@return {start_lsn,flush_ahead} */
inline std::pair<lsn_t,page_flush_ahead> finish_write(ulint len);
+ /** Release all latches. */
+ void release();
/** Release the resources */
inline void release_resources();
@@ -713,7 +790,7 @@ private:
#endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
- mtr_buf_t m_memo;
+ std::vector<mtr_memo_slot_t> *m_memo= nullptr;
/** mini-transaction log */
mtr_buf_t m_log;
@@ -729,5 +806,3 @@ private:
/** set of freed page ids */
range_set *m_freed_pages= nullptr;
};
-
-#include "mtr0mtr.inl"
diff --git a/storage/innobase/include/mtr0mtr.inl b/storage/innobase/include/mtr0mtr.inl
deleted file mode 100644
index 75be7adc6a5..00000000000
--- a/storage/innobase/include/mtr0mtr.inl
+++ /dev/null
@@ -1,185 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 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
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/mtr0mtr.ic
-Mini-transaction buffer
-
-Created 11/26/1995 Heikki Tuuri
-*******************************************************/
-
-#include "buf0buf.h"
-
-/** Check if a mini-transaction is dirtying a clean page.
-@return true if the mtr is dirtying a clean page. */
-inline bool mtr_t::is_block_dirtied(const buf_block_t *block)
-{
- ut_ad(block->page.in_file());
- ut_ad(block->page.frame);
- ut_ad(block->page.buf_fix_count());
- return block->page.oldest_modification() <= 1 &&
- block->page.id().space() < SRV_TMP_SPACE_ID;
-}
-
-/**
-Pushes an object to an mtr memo stack. */
-void
-mtr_t::memo_push(void* object, mtr_memo_type_t type)
-{
- ut_ad(is_active());
- ut_ad(object != NULL);
- ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
- ut_ad(type <= MTR_MEMO_SPACE_S_LOCK);
- ut_ad(type == MTR_MEMO_PAGE_X_MODIFY || ut_is_2pow(type));
-
- /* If this mtr has U or X latched a clean page then we set
- the m_made_dirty flag. This tells us if we need to
- grab log_sys.flush_order_mutex at mtr_t::commit() so that we
- can insert the dirtied page into the buf_pool.flush_list. */
-
- if (!m_made_dirty
- && (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))) {
-
- m_made_dirty = is_block_dirtied(
- reinterpret_cast<const buf_block_t*>(object));
- }
-
- mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
-
- slot->type = type;
- slot->object = object;
-}
-
-/**
-Releases the (index tree) s-latch stored in an mtr memo after a
-savepoint. */
-void
-mtr_t::release_s_latch_at_savepoint(
- ulint savepoint,
- index_lock* lock)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == lock);
- ut_ad(slot->type == MTR_MEMO_S_LOCK);
-
- lock->s_unlock();
-
- slot->object = NULL;
-}
-
-/**
-SX-latches the not yet latched block after a savepoint. */
-
-void
-mtr_t::sx_latch_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- ut_ad(!memo_contains_flagged(
- block,
- MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == block);
-
- /* == RW_NO_LATCH */
- ut_a(slot->type == MTR_MEMO_BUF_FIX);
-
- block->page.lock.u_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty) {
- m_made_dirty = is_block_dirtied(block);
- }
-
- slot->type = MTR_MEMO_PAGE_SX_FIX;
-}
-
-/**
-X-latches the not yet latched block after a savepoint. */
-
-void
-mtr_t::x_latch_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- ut_ad(!memo_contains_flagged(
- block,
- MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == block);
-
- /* == RW_NO_LATCH */
- ut_a(slot->type == MTR_MEMO_BUF_FIX);
-
- block->page.lock.x_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty) {
- m_made_dirty = is_block_dirtied(block);
- }
-
- slot->type = MTR_MEMO_PAGE_X_FIX;
-}
-
-/**
-Releases the block in an mtr memo after a savepoint. */
-
-void
-mtr_t::release_block_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
-
- mtr_memo_slot_t *slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_a(slot->object == block);
- slot->object= nullptr;
- block->page.unfix();
-
- switch (slot->type) {
- case MTR_MEMO_PAGE_S_FIX:
- block->page.lock.s_unlock();
- break;
- case MTR_MEMO_PAGE_SX_FIX:
- case MTR_MEMO_PAGE_X_FIX:
- block->page.lock.u_or_x_unlock(slot->type == MTR_MEMO_PAGE_SX_FIX);
- break;
- default:
- break;
- }
-}
diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h
index 80542299482..28aa30565e4 100644
--- a/storage/innobase/include/page0cur.h
+++ b/storage/innobase/include/page0cur.h
@@ -129,7 +129,6 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
- dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
@@ -143,7 +142,6 @@ rec_t*
page_cur_insert_rec_low(
/*====================*/
const page_cur_t*cur, /*!< in: page cursor */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -165,7 +163,6 @@ page_cur_insert_rec_zip(
/*====================*/
page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -177,7 +174,6 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
- const dict_index_t* index, /*!< in: record descriptor */
const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -239,8 +235,6 @@ Searches the right position for a page cursor. */
bool
page_cur_search_with_match(
/*=======================*/
- const buf_block_t* block, /*!< in: buffer block */
- const dict_index_t* index, /*!< in: record descriptor */
const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or
@@ -251,13 +245,11 @@ page_cur_search_with_match(
ulint* ilow_matched_fields,
/*!< in/out: already matched
fields in lower limit record */
- page_cur_t* cursor, /*!< out: page cursor */
+ page_cur_t* cursor, /*!< in/out: page cursor */
rtr_info_t* rtr_info);/*!< in/out: rtree search stack */
#ifdef BTR_CUR_HASH_ADAPT
MY_ATTRIBUTE((warn_unused_result))
/** Search the right position for a page cursor.
-@param[in] block buffer block
-@param[in] index index tree
@param[in] tuple key to be searched for
@param[in] mode search mode
@param[in,out] iup_matched_fields already matched fields in the
@@ -268,11 +260,9 @@ first partially matched field in the upper limit record
lower limit record
@param[in,out] ilow_matched_bytes already matched bytes in the
first partially matched field in the lower limit record
-@param[out] cursor page cursor */
+@param[in,out] cursor page cursor */
bool
page_cur_search_with_match_bytes(
- const buf_block_t* block,
- const dict_index_t* index,
const dtuple_t* tuple,
page_cur_mode_t mode,
ulint* iup_matched_fields,
@@ -284,16 +274,12 @@ page_cur_search_with_match_bytes(
/***********************************************************//**
Positions a page cursor on a randomly chosen user record on a page. If there
are no user records, sets the cursor on the infimum record. */
-void
-page_cur_open_on_rnd_user_rec(
-/*==========================*/
- buf_block_t* block, /*!< in: page */
- page_cur_t* cursor);/*!< out: page cursor */
+void page_cur_open_on_rnd_user_rec(page_cur_t *cursor);
/** Index page cursor */
struct page_cur_t{
- const dict_index_t* index;
+ dict_index_t* index;
rec_t* rec; /*!< pointer to a record on page */
rec_offs* offsets;
buf_block_t* block; /*!< pointer to the block containing rec */
diff --git a/storage/innobase/include/page0cur.inl b/storage/innobase/include/page0cur.inl
index 8f69dc22878..1638b5749ff 100644
--- a/storage/innobase/include/page0cur.inl
+++ b/storage/innobase/include/page0cur.inl
@@ -167,14 +167,12 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
- dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- rec_t* rec;
- ulint size = rec_get_converted_size(index, tuple, n_ext);
+ ulint size = rec_get_converted_size(cursor->index, tuple, n_ext);
if (!*heap) {
*heap = mem_heap_create(size
@@ -183,21 +181,20 @@ page_cur_tuple_insert(
* sizeof **offsets);
}
- rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size),
- index, tuple, n_ext);
+ rec_t* rec = rec_convert_dtuple_to_rec(
+ static_cast<byte*>(mem_heap_alloc(*heap, size)),
+ cursor->index, tuple, n_ext);
- *offsets = rec_get_offsets(rec, index, *offsets,
+ *offsets = rec_get_offsets(rec, cursor->index, *offsets,
page_is_leaf(cursor->block->page.frame)
- ? index->n_core_fields : 0,
+ ? cursor->index->n_core_fields : 0,
ULINT_UNDEFINED, heap);
ut_ad(size == rec_offs_size(*offsets));
if (is_buf_block_get_page_zip(cursor->block)) {
- rec = page_cur_insert_rec_zip(
- cursor, index, rec, *offsets, mtr);
+ rec = page_cur_insert_rec_zip(cursor, rec, *offsets, mtr);
} else {
- rec = page_cur_insert_rec_low(cursor,
- index, rec, *offsets, mtr);
+ rec = page_cur_insert_rec_low(cursor, rec, *offsets, mtr);
}
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, *offsets));
diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h
index 42b00b8925c..a1350740e2a 100644
--- a/storage/innobase/include/row0row.h
+++ b/storage/innobase/include/row0row.h
@@ -363,7 +363,6 @@ Searches an index record.
enum row_search_result
row_search_index_entry(
/*===================*/
- dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index c376e15ff0f..66f8db34e73 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -38,179 +38,9 @@ Created 11/26/1995 Heikki Tuuri
#include "srv0start.h"
#include "log.h"
-/** Iterate over a memo block in reverse. */
-template <typename Functor>
-struct CIterate {
- CIterate() : functor() {}
-
- CIterate(const Functor& functor) : functor(functor) {}
-
- /** @return false if the functor returns false. */
- bool operator()(mtr_buf_t::block_t* block) const
- {
- const mtr_memo_slot_t* start =
- reinterpret_cast<const mtr_memo_slot_t*>(
- block->begin());
-
- mtr_memo_slot_t* slot =
- reinterpret_cast<mtr_memo_slot_t*>(
- block->end());
-
- ut_ad(!(block->used() % sizeof(*slot)));
-
- while (slot-- != start) {
-
- if (!functor(slot)) {
- return(false);
- }
- }
-
- return(true);
- }
-
- Functor functor;
-};
-
-template <typename Functor>
-struct Iterate {
- Iterate() : functor() {}
-
- Iterate(const Functor& functor) : functor(functor) {}
-
- /** @return false if the functor returns false. */
- bool operator()(mtr_buf_t::block_t* block)
- {
- const mtr_memo_slot_t* start =
- reinterpret_cast<const mtr_memo_slot_t*>(
- block->begin());
-
- mtr_memo_slot_t* slot =
- reinterpret_cast<mtr_memo_slot_t*>(
- block->end());
-
- ut_ad(!(block->used() % sizeof(*slot)));
-
- while (slot-- != start) {
-
- if (!functor(slot)) {
- return(false);
- }
- }
-
- return(true);
- }
-
- Functor functor;
-};
-
-/** Find specific object */
-struct Find {
-
- /** Constructor */
- Find(const void* object, ulint type)
- :
- m_slot(),
- m_type(type),
- m_object(object)
- {
- ut_a(object != NULL);
- }
-
- /** @return false if the object was found. */
- bool operator()(mtr_memo_slot_t* slot)
- {
- if (m_object == slot->object && m_type == slot->type) {
- m_slot = slot;
- return(false);
- }
-
- return(true);
- }
-
- /** Slot if found */
- mtr_memo_slot_t*m_slot;
-
- /** Type of the object to look for */
- const ulint m_type;
-
- /** The object instance to look for */
- const void* m_object;
-};
-
-/** Find a page frame */
-struct FindPage
-{
- /** Constructor
- @param[in] ptr pointer to within a page frame
- @param[in] flags MTR_MEMO flags to look for */
- FindPage(const void* ptr, ulint flags)
- : m_ptr(ptr), m_flags(flags), m_slot(NULL)
- {
- /* There must be some flags to look for. */
- ut_ad(flags);
- /* We can only look for page-related flags. */
- ut_ad(!(flags & ulint(~(MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX
- | MTR_MEMO_BUF_FIX
- | MTR_MEMO_MODIFY))));
- }
-
- /** Visit a memo entry.
- @param[in] slot memo entry to visit
- @retval false if a page was found
- @retval true if the iteration should continue */
- bool operator()(mtr_memo_slot_t* slot)
- {
- ut_ad(m_slot == NULL);
-
- if (!(m_flags & slot->type) || slot->object == NULL) {
- return(true);
- }
-
- buf_page_t* bpage = static_cast<buf_page_t*>(slot->object);
-
- if (m_ptr < bpage->frame
- || m_ptr >= bpage->frame + srv_page_size) {
- return(true);
- }
- ut_ad(!(slot->type & MTR_MEMO_PAGE_S_FIX)
- || bpage->lock.have_s());
- ut_ad(!(slot->type & MTR_MEMO_PAGE_SX_FIX)
- || bpage->lock.have_u_or_x());
- ut_ad(!(slot->type & MTR_MEMO_PAGE_X_FIX)
- || bpage->lock.have_x());
- m_slot = slot;
- return(false);
- }
-
- /** @return the slot that was found */
- mtr_memo_slot_t* get_slot() const
- {
- ut_ad(m_slot != NULL);
- return(m_slot);
- }
- /** @return the block that was found */
- buf_block_t* get_block() const
- {
- return(reinterpret_cast<buf_block_t*>(get_slot()->object));
- }
-private:
- /** Pointer inside a page frame to look for */
- const void*const m_ptr;
- /** MTR_MEMO flags to look for */
- const ulint m_flags;
- /** The slot corresponding to m_ptr */
- mtr_memo_slot_t* m_slot;
-};
-
-/** Release latches and decrement the buffer fix count.
-@param slot memo slot */
-static void memo_slot_release(mtr_memo_slot_t *slot)
+void mtr_memo_slot_t::release() const
{
- void *object= slot->object;
- slot->object= nullptr;
- switch (const auto type= slot->type) {
+ switch (type) {
case MTR_MEMO_S_LOCK:
static_cast<index_lock*>(object)->s_unlock();
break;
@@ -228,8 +58,10 @@ static void memo_slot_release(mtr_memo_slot_t *slot)
break;
default:
buf_page_t *bpage= static_cast<buf_page_t*>(object);
- bpage->unfix();
- switch (auto latch= slot->type & ~MTR_MEMO_MODIFY) {
+ ut_d(const auto s=)
+ bpage->unfix();
+ ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX);
+ switch (auto latch= type & ~MTR_MEMO_MODIFY) {
case MTR_MEMO_PAGE_S_FIX:
bpage->lock.s_unlock();
return;
@@ -244,150 +76,14 @@ static void memo_slot_release(mtr_memo_slot_t *slot)
}
}
-/** Release the latches acquired by the mini-transaction. */
-struct ReleaseLatches {
- /** @return true always. */
- bool operator()(mtr_memo_slot_t *slot) const
- {
- void *object= slot->object;
- if (!object)
- return true;
- slot->object= nullptr;
- switch (const auto type= slot->type) {
- case MTR_MEMO_S_LOCK:
- static_cast<index_lock*>(object)->s_unlock();
- break;
- case MTR_MEMO_SPACE_X_LOCK:
- static_cast<fil_space_t*>(object)->set_committed_size();
- static_cast<fil_space_t*>(object)->x_unlock();
- break;
- case MTR_MEMO_SPACE_S_LOCK:
- static_cast<fil_space_t*>(object)->s_unlock();
- break;
- case MTR_MEMO_X_LOCK:
- case MTR_MEMO_SX_LOCK:
- static_cast<index_lock*>(object)->
- u_or_x_unlock(type == MTR_MEMO_SX_LOCK);
- break;
- default:
- buf_page_t *bpage= static_cast<buf_page_t*>(object);
- bpage->unfix();
- switch (auto latch= slot->type & ~MTR_MEMO_MODIFY) {
- case MTR_MEMO_PAGE_S_FIX:
- bpage->lock.s_unlock();
- return true;
- case MTR_MEMO_PAGE_SX_FIX:
- case MTR_MEMO_PAGE_X_FIX:
- bpage->lock.u_or_x_unlock(latch == MTR_MEMO_PAGE_SX_FIX);
- /* fall through */
- case MTR_MEMO_BUF_FIX:
- return true;
- }
- ut_ad("invalid type" == 0);
- }
- return true;
- }
-};
-
-/** Release the latches and blocks acquired by the mini-transaction. */
-struct ReleaseAll {
- /** @return true always. */
- bool operator()(mtr_memo_slot_t *slot) const
- {
- if (slot->object)
- memo_slot_release(slot);
- return true;
- }
-};
-
-/** Stops iteration is savepoint is reached */
-template <typename Functor> struct TillSavepoint
-{
-
- /** Constructor
- @param[in] functor functor which is called if savepoint is not reached
- @param[in] savepoint savepoint value to rollback
- @param[in] used current position in slots container */
- TillSavepoint(const Functor &functor, ulint savepoint, ulint used)
- : functor(functor),
- m_slots_count((used - savepoint) / sizeof(mtr_memo_slot_t))
- {
- ut_ad(savepoint);
- ut_ad(used >= savepoint);
- }
-
- /** @return true if savepoint is not reached, false otherwise */
- bool operator()(mtr_memo_slot_t *slot)
- {
-#ifdef UNIV_DEBUG
- /** This check is added because the code is invoked only from
- row_search_mvcc() to release latches acquired during clustered index search
- for secondary index record. To make it more universal we could add one more
- member in this functor for debug build to pass only certain slot types,
- but this is currently not necessary. */
- switch (slot->type)
- {
- case MTR_MEMO_S_LOCK:
- case MTR_MEMO_PAGE_S_FIX:
- break;
- default:
- ut_a(false);
- }
-#endif
- return m_slots_count-- && functor(slot);
- }
-
-private:
- /** functor to invoke */
- const Functor &functor;
- /** slots count left till savepoint */
- ulint m_slots_count;
-};
-
-#ifdef UNIV_DEBUG
-/** Check that all slots have been handled. */
-struct DebugCheck {
- /** @return true always. */
- bool operator()(const mtr_memo_slot_t* slot) const
- {
- ut_ad(!slot->object);
- return(true);
- }
-};
-#endif
-
-/** Release page latches held by the mini-transaction. */
-struct ReleaseBlocks
-{
- const lsn_t start, end;
- ReleaseBlocks(lsn_t start, lsn_t end) : start(start), end(end) {}
-
- /** @return true always */
- bool operator()(mtr_memo_slot_t *slot) const
- {
- if (!slot->object)
- return true;
- switch (slot->type) {
- case MTR_MEMO_PAGE_X_MODIFY:
- case MTR_MEMO_PAGE_SX_MODIFY:
- break;
- default:
- ut_ad(!(slot->type & MTR_MEMO_MODIFY));
- return true;
- }
-
- buf_block_t *block= static_cast<buf_block_t*>(slot->object);
- buf_flush_note_modification(block, start, end);
- return true;
- }
-};
-
/** Start a mini-transaction. */
void mtr_t::start()
{
+ ut_ad(!m_memo);
ut_ad(!m_freed_pages);
ut_ad(!m_freed_space);
MEM_UNDEFINED(this, sizeof *this);
+ MEM_MAKE_DEFINED(&m_memo, sizeof m_memo);
MEM_MAKE_DEFINED(&m_freed_space, sizeof m_freed_space);
MEM_MAKE_DEFINED(&m_freed_pages, sizeof m_freed_pages);
@@ -398,7 +94,6 @@ void mtr_t::start()
m_last= nullptr;
m_last_offset= 0;
- new(&m_memo) mtr_buf_t();
new(&m_log) mtr_buf_t();
m_made_dirty= false;
@@ -415,12 +110,26 @@ void mtr_t::start()
inline void mtr_t::release_resources()
{
ut_ad(is_active());
- ut_d(m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
+ ut_ad(!m_memo);
m_log.erase();
- m_memo.erase();
ut_d(m_commit= true);
}
+void mtr_t::release()
+{
+ if (m_memo)
+ {
+ for (auto it= m_memo->rbegin(); it != m_memo->rend(); it++)
+ {
+ mtr_memo_slot_t &slot= *it;
+ if (slot.object)
+ slot.release();
+ }
+ delete m_memo;
+ m_memo= nullptr;
+ }
+}
+
/** Commit a mini-transaction. */
void mtr_t::commit()
{
@@ -481,12 +190,24 @@ void mtr_t::commit()
else
ut_ad(!m_freed_space);
- m_memo.for_each_block_in_reverse
- (CIterate<const ReleaseBlocks>(ReleaseBlocks(lsns.first, m_commit_lsn)));
+ if (m_memo)
+ {
+ for (const mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (slot.object && slot.type & MTR_MEMO_MODIFY)
+ {
+ ut_ad(slot.type == MTR_MEMO_PAGE_X_MODIFY ||
+ slot.type == MTR_MEMO_PAGE_SX_MODIFY);
+ buf_flush_note_modification(static_cast<buf_block_t*>(slot.object),
+ lsns.first, m_commit_lsn);
+ }
+ }
+ }
+
if (m_made_dirty)
mysql_mutex_unlock(&log_sys.flush_order_mutex);
- m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
+ release();
if (UNIV_UNLIKELY(lsns.second != PAGE_FLUSH_NO))
buf_flush_ahead(m_commit_lsn, lsns.second == PAGE_FLUSH_SYNC);
@@ -495,72 +216,32 @@ void mtr_t::commit()
srv_stats.log_write_requests.inc();
}
else
- m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>());
+ release();
release_resources();
}
-/** Release latches till savepoint. To simplify the code only
-MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be
-released, otherwise it would be neccesary to add one more argument in the
-function to point out what slot types are allowed for rollback, and this
-would be overengineering as corrently the function is used only in one place
-in the code.
-@param savepoint savepoint, can be obtained with get_savepoint */
-void mtr_t::rollback_to_savepoint(ulint savepoint)
-{
- Iterate<TillSavepoint<ReleaseLatches>> iteration(
- TillSavepoint<ReleaseLatches>(ReleaseLatches(), savepoint,
- get_savepoint()));
- m_memo.for_each_block_in_reverse(iteration);
-}
-
-/** Shrink a tablespace. */
-struct Shrink
+void mtr_t::rollback_to_savepoint(ulint begin, ulint end)
{
- /** the first non-existing page in the tablespace */
- const page_id_t high;
-
- Shrink(const fil_space_t &space) : high({space.id, space.size}) {}
+ ut_ad(m_memo);
+ ut_ad(end <= m_memo->size());
+ ut_ad(begin <= end);
+ ulint s= end;
- bool operator()(mtr_memo_slot_t *slot) const
+ while (s-- > begin)
{
- if (!slot->object)
- return true;
- switch (slot->type) {
- default:
- ut_ad("invalid type" == 0);
- return false;
- case MTR_MEMO_SPACE_X_LOCK:
- ut_ad(high.space() == static_cast<fil_space_t*>(slot->object)->id);
- return true;
- case MTR_MEMO_PAGE_X_MODIFY:
- case MTR_MEMO_PAGE_SX_MODIFY:
- case MTR_MEMO_PAGE_X_FIX:
- case MTR_MEMO_PAGE_SX_FIX:
- auto &bpage= static_cast<buf_block_t*>(slot->object)->page;
- const auto s= bpage.state();
- ut_ad(s >= buf_page_t::FREED);
- ut_ad(s < buf_page_t::READ_FIX);
- ut_ad(bpage.frame);
- const page_id_t id{bpage.id()};
- if (id < high)
- {
- ut_ad(id.space() == high.space() ||
- (id == page_id_t{0, TRX_SYS_PAGE_NO} &&
- srv_is_undo_tablespace(high.space())));
- break;
- }
- if (s >= buf_page_t::UNFIXED)
- bpage.set_freed(s);
- ut_ad(id.space() == high.space());
- if (bpage.oldest_modification() > 1)
- bpage.reset_oldest_modification();
- slot->type= static_cast<mtr_memo_type_t>(slot->type & ~MTR_MEMO_MODIFY);
- }
- return true;
+ const mtr_memo_slot_t &slot= (*m_memo)[s];
+ if (!slot.object)
+ continue;
+ /* This is intended for releasing latches on indexes or unmodified
+ buffer pool pages. */
+ ut_ad(slot.type <= MTR_MEMO_SX_LOCK);
+ ut_ad(!(slot.type & MTR_MEMO_MODIFY));
+ slot.release();
}
-};
+
+ m_memo->erase(m_memo->begin() + begin, m_memo->begin() + end);
+}
/** Commit a mini-transaction that is shrinking a tablespace.
@param space tablespace that is being shrunk */
@@ -571,6 +252,7 @@ void mtr_t::commit_shrink(fil_space_t &space)
ut_ad(!high_level_read_only);
ut_ad(m_modifications);
ut_ad(m_made_dirty);
+ ut_ad(m_memo);
ut_ad(!recv_recovery_is_on());
ut_ad(m_log_mode == MTR_LOG_ALL);
ut_ad(UT_LIST_GET_LEN(space.chain) == 1);
@@ -608,10 +290,49 @@ void mtr_t::commit_shrink(fil_space_t &space)
else
ut_ad(!m_freed_space);
- m_memo.for_each_block_in_reverse(CIterate<Shrink>{space});
+ const page_id_t high{space.id, space.size};
+
+ for (mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (!slot.object)
+ continue;
+ switch (slot.type) {
+ default:
+ ut_ad("invalid type" == 0);
+ break;
+ case MTR_MEMO_SPACE_X_LOCK:
+ ut_ad(high.space() == static_cast<fil_space_t*>(slot.object)->id);
+ break;
+ case MTR_MEMO_PAGE_X_MODIFY:
+ case MTR_MEMO_PAGE_SX_MODIFY:
+ case MTR_MEMO_PAGE_X_FIX:
+ case MTR_MEMO_PAGE_SX_FIX:
+ auto &block= *static_cast<buf_block_t*>(slot.object);
+ const auto s= block.page.state();
+ ut_ad(s >= buf_page_t::FREED);
+ ut_ad(s < buf_page_t::READ_FIX);
+ ut_ad(block.page.frame);
+ const page_id_t id{block.page.id()};
+ if (id < high)
+ {
+ ut_ad(id.space() == high.space() ||
+ (id == page_id_t{0, TRX_SYS_PAGE_NO} &&
+ srv_is_undo_tablespace(high.space())));
+ if (slot.type & MTR_MEMO_MODIFY)
+ buf_flush_note_modification(&block, start_lsn, m_commit_lsn);
+ }
+ else
+ {
+ ut_ad(id.space() == high.space());
+ if (s >= buf_page_t::UNFIXED)
+ block.page.set_freed(s);
+ if (block.page.oldest_modification() > 1)
+ block.page.reset_oldest_modification();
+ slot.type= mtr_memo_type_t(slot.type & ~MTR_MEMO_MODIFY);
+ }
+ }
+ }
- m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks>
- (ReleaseBlocks(start_lsn, m_commit_lsn)));
mysql_mutex_unlock(&log_sys.flush_order_mutex);
mysql_mutex_lock(&fil_system.mutex);
@@ -621,10 +342,9 @@ void mtr_t::commit_shrink(fil_space_t &space)
space.is_being_truncated= false;
mysql_mutex_unlock(&fil_system.mutex);
- m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
- srv_stats.log_write_requests.inc();
-
+ release();
release_resources();
+ srv_stats.log_write_requests.inc();
}
/** Commit a mini-transaction that is deleting or renaming a file.
@@ -706,7 +426,6 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name)
}
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- ut_d(m_log.erase());
release_resources();
srv_stats.log_write_requests.inc();
@@ -726,7 +445,6 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn)
ut_ad(!is_inside_ibuf());
ut_ad(m_log_mode == MTR_LOG_ALL);
ut_ad(!m_made_dirty);
- ut_ad(m_memo.size() == 0);
ut_ad(!srv_read_only_mode);
ut_ad(!m_freed_space);
ut_ad(!m_freed_pages);
@@ -818,25 +536,22 @@ void mtr_t::x_lock_space(fil_space_t *space)
}
}
-/** Release an object in the memo stack.
-@return true if released */
-bool
-mtr_t::memo_release(const void* object, ulint type)
+void mtr_t::release(const void *object)
{
- ut_ad(is_active());
-
- /* We cannot release a page that has been written to in the
- middle of a mini-transaction. */
- ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX);
-
- Iterate<Find> iteration(Find(object, type));
-
- if (!m_memo.for_each_block_in_reverse(iteration)) {
- memo_slot_release(iteration.functor.m_slot);
- return(true);
- }
-
- return(false);
+ ut_ad(is_active());
+ ut_ad(m_memo);
+
+ auto it=
+ std::find_if(m_memo->begin(), m_memo->end(),
+ [object](const mtr_memo_slot_t& slot)
+ { return slot.object == object; });
+ ut_ad(it != m_memo->end());
+ ut_ad(!(it->type & MTR_MEMO_MODIFY));
+ it->release();
+ m_memo->erase(it);
+ ut_ad(std::find_if(m_memo->begin(), m_memo->end(),
+ [object](const mtr_memo_slot_t& slot)
+ { return slot.object == &object; }) == m_memo->end());
}
static bool log_margin_warned;
@@ -1072,25 +787,6 @@ inline void mtr_t::page_checksum(const buf_page_t &bpage)
m_log.close(l + 4);
}
-/** Write OPT_PAGE_CHECKSUM records for modified pages */
-struct WriteOPT_PAGE_CHECKSUM
-{
- mtr_t &mtr;
- WriteOPT_PAGE_CHECKSUM(mtr_t &mtr) : mtr(mtr) {}
-
- /** @return true always */
- bool operator()(const mtr_memo_slot_t *slot) const
- {
- if (slot->type & MTR_MEMO_MODIFY)
- {
- const buf_page_t &b= static_cast<const buf_block_t*>(slot->object)->page;
- if (!b.is_freed())
- mtr.page_checksum(b);
- }
- return true;
- }
-};
-
/** Write the block contents to the REDO log */
struct mtr_write_log
{
@@ -1105,51 +801,56 @@ struct mtr_write_log
std::pair<lsn_t,mtr_t::page_flush_ahead> mtr_t::do_write()
{
- ut_ad(!recv_no_log_write);
- ut_ad(is_logged());
+ ut_ad(!recv_no_log_write);
+ ut_ad(is_logged());
- ulint len = m_log.size();
- ut_ad(len > 0);
+ ulint len= m_log.size();
+ ut_ad(len);
#ifndef DBUG_OFF
- if (m_log_mode == MTR_LOG_ALL) {
- do {
- DBUG_EXECUTE_IF("skip_page_checksum", continue;);
- m_memo.for_each_block(CIterate<WriteOPT_PAGE_CHECKSUM>
- (*this));
- len = m_log.size();
- } while (0);
- }
+ do
+ {
+ if (!m_memo || m_log_mode != MTR_LOG_ALL)
+ continue;
+ DBUG_EXECUTE_IF("skip_page_checksum", continue;);
+
+ for (const mtr_memo_slot_t& slot : *m_memo)
+ if (slot.type & MTR_MEMO_MODIFY)
+ {
+ const buf_page_t &b= *static_cast<const buf_page_t*>(slot.object);
+ if (!b.is_freed())
+ page_checksum(b);
+ }
+ len= m_log.size();
+ }
+ while (0);
#endif
- if (len > srv_log_buffer_size / 2) {
- log_buffer_extend(ulong((len + 1) * 2));
- }
+ if (len > srv_log_buffer_size / 2)
+ log_buffer_extend(ulong((len + 1) * 2));
- fil_space_t* space = m_user_space;
+ fil_space_t *space= m_user_space;
- if (space != NULL && is_predefined_tablespace(space->id)) {
- /* Omit FILE_MODIFY for predefined tablespaces. */
- space = NULL;
- }
+ if (space && is_predefined_tablespace(space->id))
+ /* Omit FILE_MODIFY for predefined tablespaces. */
+ space= nullptr;
- mysql_mutex_lock(&log_sys.mutex);
+ mysql_mutex_lock(&log_sys.mutex);
- if (fil_names_write_if_was_clean(space)) {
- len = m_log.size();
- } else {
- /* This was not the first time of dirtying a
- tablespace since the latest checkpoint. */
- ut_ad(len == m_log.size());
- }
+ if (fil_names_write_if_was_clean(space))
+ len= m_log.size();
+ else
+ /* This was not the first time of dirtying a
+ tablespace since the latest checkpoint. */
+ ut_ad(len == m_log.size());
- *m_log.push<byte*>(1) = 0;
- len++;
+ *m_log.push<byte*>(1)= 0;
+ len++;
- /* check and attempt a checkpoint if exceeding capacity */
- log_margin_checkpoint_age(len);
+ /* check and attempt a checkpoint if exceeding capacity */
+ log_margin_checkpoint_age(len);
- return finish_write(len);
+ return finish_write(len);
}
/** Append the redo log records to the redo log buffer.
@@ -1188,131 +889,95 @@ piecewise:
return std::make_pair(start_lsn, flush);
}
-/** Find out whether a block was not X-latched by the mini-transaction */
-struct FindBlockX
-{
- const buf_block_t &block;
-
- FindBlockX(const buf_block_t &block): block(block) {}
-
- /** @return whether the block was not found x-latched */
- bool operator()(const mtr_memo_slot_t *slot) const
- {
- return slot->object != &block || !(slot->type & MTR_MEMO_PAGE_X_FIX);
- }
-};
-
-/** Find out whether a block was not X or U latched by the mini-transaction */
-struct FindBlockUX
+bool mtr_t::have_x_latch(const buf_block_t &block) const
{
- const buf_block_t &block;
+ if (!m_memo)
+ return false;
- FindBlockUX(const buf_block_t &block): block(block) {}
+ const mtr_memo_slot_t *found= nullptr;
- /** @return whether the block was not found x-latched */
- bool operator()(const mtr_memo_slot_t *slot) const
+ for (const mtr_memo_slot_t &slot : *m_memo)
{
- return slot->object != &block ||
- !(slot->type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
- }
-};
+ if (slot.object != &block)
+ continue;
-#ifdef UNIV_DEBUG
-/** Assert that the block is not present in the mini-transaction */
-struct FindNoBlock
-{
- const buf_block_t &block;
+ found= &slot;
- FindNoBlock(const buf_block_t &block): block(block) {}
+ if (!(slot.type & MTR_MEMO_PAGE_X_FIX))
+ continue;
- /** @return whether the block was not found */
- bool operator()(const mtr_memo_slot_t *slot) const
- {
- return slot->object != &block;
+ ut_ad(block.page.lock.have_x());
+ return true;
}
-};
-#endif /* UNIV_DEBUG */
-bool mtr_t::have_x_latch(const buf_block_t &block) const
-{
- if (m_memo.for_each_block(CIterate<FindBlockX>(FindBlockX(block))))
- {
- ut_ad(m_memo.for_each_block(CIterate<FindNoBlock>(FindNoBlock(block))));
- ut_ad(!memo_contains_flagged(&block,
- MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX |
- MTR_MEMO_BUF_FIX | MTR_MEMO_MODIFY));
- return false;
- }
- ut_ad(block.page.lock.have_x());
- return true;
+ ut_ad(!found);
+ return false;
}
bool mtr_t::have_u_or_x_latch(const buf_block_t &block) const
{
- if (m_memo.for_each_block(CIterate<FindBlockUX>(FindBlockUX(block))))
- return false;
- ut_ad(block.page.lock.have_u_or_x());
- return true;
+ if (m_memo)
+ {
+ for (const mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (slot.object == &block &&
+ slot.type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))
+ {
+ ut_ad(block.page.lock.have_u_or_x());
+ return true;
+ }
+ }
+ }
+ return false;
}
/** Check if we are holding exclusive tablespace latch
@param space tablespace to search for
@param shared whether to look for shared latch, instead of exclusive
@return whether space.latch is being held */
-bool mtr_t::memo_contains(const fil_space_t& space, bool shared)
-{
- Iterate<Find> iteration(Find(&space, shared
- ? MTR_MEMO_SPACE_S_LOCK
- : MTR_MEMO_SPACE_X_LOCK));
- if (m_memo.for_each_block_in_reverse(iteration))
- return false;
- ut_ad(shared || space.is_owner());
- return true;
-}
-
-/** Upgrade U-latched pages to X */
-struct UpgradeX
+bool mtr_t::memo_contains(const fil_space_t& space, bool shared) const
{
- const buf_block_t &block;
- UpgradeX(const buf_block_t &block) : block(block) {}
- bool operator()(mtr_memo_slot_t *slot) const
+ if (m_memo)
{
- if (slot->object == &block && (MTR_MEMO_PAGE_SX_FIX & slot->type))
- slot->type= static_cast<mtr_memo_type_t>
- (slot->type ^ (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX));
- return true;
+ const mtr_memo_type_t type= shared
+ ? MTR_MEMO_SPACE_S_LOCK : MTR_MEMO_SPACE_X_LOCK;
+
+ for (const mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (slot.object == &space && slot.type == type)
+ {
+ ut_ad(shared || space.is_owner());
+ return true;
+ }
+ }
}
-};
-/** Upgrade U locks on a block to X */
+ return false;
+}
+
void mtr_t::page_lock_upgrade(const buf_block_t &block)
{
ut_ad(block.page.lock.have_x());
- m_memo.for_each_block(CIterate<UpgradeX>((UpgradeX(block))));
+ ut_ad(m_memo);
+
+ for (mtr_memo_slot_t &slot : *m_memo)
+ if (slot.object == &block && slot.type & MTR_MEMO_PAGE_SX_FIX)
+ slot.type= mtr_memo_type_t(slot.type ^
+ (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX));
+
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block.index || !block.index->freed());
#endif /* BTR_CUR_HASH_ADAPT */
}
-/** Upgrade U locks to X */
-struct UpgradeLockX
-{
- const index_lock &lock;
- UpgradeLockX(const index_lock &lock) : lock(lock) {}
- bool operator()(mtr_memo_slot_t *slot) const
- {
- if (slot->object == &lock && (MTR_MEMO_SX_LOCK & slot->type))
- slot->type= static_cast<mtr_memo_type_t>
- (slot->type ^ (MTR_MEMO_SX_LOCK | MTR_MEMO_X_LOCK));
- return true;
- }
-};
-
-/** Upgrade U locks on a block to X */
void mtr_t::lock_upgrade(const index_lock &lock)
{
ut_ad(lock.have_x());
- m_memo.for_each_block(CIterate<UpgradeLockX>((UpgradeLockX(lock))));
+ ut_ad(m_memo);
+
+ for (mtr_memo_slot_t &slot : *m_memo)
+ if (slot.object == &lock && slot.type == MTR_MEMO_SX_LOCK)
+ slot.type= MTR_MEMO_X_LOCK;
}
/** Latch a buffer pool block.
@@ -1360,231 +1025,240 @@ done:
memo_push(block, fix_type);
}
-#ifdef UNIV_DEBUG
-/** Check if we are holding an rw-latch in this mini-transaction
-@param lock latch to search for
-@param type held latch type
-@return whether (lock,type) is contained */
-bool mtr_t::memo_contains(const index_lock &lock, mtr_memo_type_t type)
+void mtr_t::upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch)
{
- Iterate<Find> iteration(Find(&lock, type));
- if (m_memo.for_each_block_in_reverse(iteration))
- return false;
+ ut_ad(is_active());
+ ut_ad(m_memo);
+ ut_ad(savepoint < m_memo->size());
- switch (type) {
- case MTR_MEMO_X_LOCK:
- ut_ad(lock.have_x());
- break;
- case MTR_MEMO_SX_LOCK:
- ut_ad(lock.have_u_or_x());
- break;
- case MTR_MEMO_S_LOCK:
- ut_ad(lock.have_s());
- break;
+ mtr_memo_slot_t &slot= (*m_memo)[savepoint];
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ buf_block_t *block= static_cast<buf_block_t*>(slot.object);
+ ut_d(const auto state= block->page.state());
+ ut_ad(state > buf_page_t::UNFIXED);
+ ut_ad(state > buf_page_t::WRITE_FIX || state < buf_page_t::READ_FIX);
+
+ switch (rw_latch) {
default:
+ ut_ad("invalid state" == 0);
break;
+ case RW_SX_LATCH:
+ slot.type= MTR_MEMO_PAGE_SX_FIX;
+ block->page.lock.u_lock();
+ ut_ad(!block->page.is_io_fixed());
+ break;
+ case RW_X_LATCH:
+ slot.type= MTR_MEMO_PAGE_X_FIX;
+ block->page.lock.x_lock();
+ ut_ad(!block->page.is_io_fixed());
}
- return true;
+#ifdef BTR_CUR_HASH_ADAPT
+ btr_search_drop_page_hash_index(block, true);
+#endif
+ ut_ad(page_id_t(page_get_space_id(block->page.frame),
+ page_get_page_no(block->page.frame)) == block->page.id());
}
-/** Debug check for flags */
-struct FlaggedCheck {
- FlaggedCheck(const void* ptr, ulint flags)
- :
- m_ptr(ptr),
- m_flags(flags)
- {
- /* There must be some flags to look for. */
- ut_ad(flags);
- /* Look for rw-lock-related and page-related flags. */
- ut_ad(!(flags & ulint(~(MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX
- | MTR_MEMO_BUF_FIX
- | MTR_MEMO_MODIFY
- | MTR_MEMO_X_LOCK
- | MTR_MEMO_SX_LOCK
- | MTR_MEMO_S_LOCK))));
- /* Either some rw-lock-related or page-related flags
- must be specified, but not both at the same time. */
- ut_ad(!(flags & (MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX
- | MTR_MEMO_BUF_FIX
- | MTR_MEMO_MODIFY))
- == !!(flags & (MTR_MEMO_X_LOCK
- | MTR_MEMO_SX_LOCK
- | MTR_MEMO_S_LOCK)));
- }
-
- /** Visit a memo entry.
- @param[in] slot memo entry to visit
- @retval false if m_ptr was found
- @retval true if the iteration should continue */
- bool operator()(const mtr_memo_slot_t* slot) const
- {
- if (m_ptr != slot->object) {
- return(true);
- }
-
- auto f = m_flags & slot->type;
- if (!f) {
- return true;
- }
-
- if (f & (MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX
- | MTR_MEMO_PAGE_X_FIX)) {
- block_lock* lock = &static_cast<buf_block_t*>(
- const_cast<void*>(m_ptr))->page.lock;
- ut_ad(!(f & MTR_MEMO_PAGE_S_FIX) || lock->have_s());
- ut_ad(!(f & MTR_MEMO_PAGE_SX_FIX)
- || lock->have_u_or_x());
- ut_ad(!(f & MTR_MEMO_PAGE_X_FIX) || lock->have_x());
- } else {
- index_lock* lock = static_cast<index_lock*>(
- const_cast<void*>(m_ptr));
- ut_ad(!(f & MTR_MEMO_S_LOCK) || lock->have_s());
- ut_ad(!(f & MTR_MEMO_SX_LOCK) || lock->have_u_or_x());
- ut_ad(!(f & MTR_MEMO_X_LOCK) || lock->have_x());
- }
+#ifdef UNIV_DEBUG
+/** Check if we are holding an rw-latch in this mini-transaction
+@param lock latch to search for
+@param type held latch type
+@return whether (lock,type) is contained */
+bool mtr_t::memo_contains(const index_lock &lock, mtr_memo_type_t type) const
+{
+ ut_ad(type == MTR_MEMO_X_LOCK || type == MTR_MEMO_S_LOCK ||
+ type == MTR_MEMO_SX_LOCK);
- return(false);
- }
+ if (m_memo)
+ {
+ for (const mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (slot.object == &lock && slot.type == type)
+ {
+ switch (type) {
+ case MTR_MEMO_X_LOCK:
+ ut_ad(lock.have_x());
+ break;
+ case MTR_MEMO_SX_LOCK:
+ ut_ad(lock.have_u_or_x());
+ break;
+ case MTR_MEMO_S_LOCK:
+ ut_ad(lock.have_s());
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+ }
+ }
- const void*const m_ptr;
- const ulint m_flags;
-};
+ return false;
+}
/** Check if memo contains the given item.
@param object object to search
@param flags specify types of object (can be ORred) of
MTR_MEMO_PAGE_S_FIX ... values
@return true if contains */
-bool
-mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
+bool mtr_t::memo_contains_flagged(const void *object, ulint flags) const
{
- ut_ad(is_active());
+ ut_ad(is_active());
+ ut_ad(flags);
+ /* Look for rw-lock-related and page-related flags. */
+ ut_ad(!(flags & ulint(~(MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_BUF_FIX |
+ MTR_MEMO_MODIFY | MTR_MEMO_X_LOCK |
+ MTR_MEMO_SX_LOCK | MTR_MEMO_S_LOCK))));
+ /* Either some rw-lock-related or page-related flags
+ must be specified, but not both at the same time. */
+ ut_ad(!(flags & (MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX |
+ MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_BUF_FIX |
+ MTR_MEMO_MODIFY)) ==
+ !!(flags & (MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK | MTR_MEMO_S_LOCK)));
+
+ for (const mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (object != slot.object)
+ continue;
- return !m_memo.for_each_block_in_reverse(
- CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags)));
-}
+ auto f = flags & slot.type;
+ if (!f)
+ continue;
-/** Check if memo contains the given page.
-@param[in] ptr pointer to within buffer frame
-@param[in] flags specify types of object with OR of
- MTR_MEMO_PAGE_S_FIX... values
-@return the block
-@retval NULL if not found */
-buf_block_t*
-mtr_t::memo_contains_page_flagged(
- const byte* ptr,
- ulint flags) const
-{
- Iterate<FindPage> iteration(FindPage(ptr, flags));
- return m_memo.for_each_block_in_reverse(iteration)
- ? NULL : iteration.functor.get_block();
-}
-#endif /* UNIV_DEBUG */
+ if (f & (MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX))
+ {
+ const block_lock &lock= static_cast<const buf_page_t*>(object)->lock;
+ ut_ad(!(f & MTR_MEMO_PAGE_S_FIX) || lock.have_s());
+ ut_ad(!(f & MTR_MEMO_PAGE_SX_FIX) || lock.have_u_or_x());
+ ut_ad(!(f & MTR_MEMO_PAGE_X_FIX) || lock.have_x());
+ }
+ else
+ {
+ const index_lock &lock= *static_cast<const index_lock*>(object);
+ ut_ad(!(f & MTR_MEMO_S_LOCK) || lock.have_s());
+ ut_ad(!(f & MTR_MEMO_SX_LOCK) || lock.have_u_or_x());
+ ut_ad(!(f & MTR_MEMO_X_LOCK) || lock.have_x());
+ }
+ return true;
+ }
-/** Find a potentially modified block. */
-struct FindModified
+ return false;
+}
+
+buf_block_t* mtr_t::memo_contains_page_flagged(const byte *ptr, ulint flags)
+ const
{
- mtr_memo_slot_t *found= nullptr;
- const buf_block_t& block;
+ ptr= page_align(ptr);
- FindModified(const buf_block_t &block) : block(block) {}
- bool operator()(mtr_memo_slot_t *slot)
+ for (const mtr_memo_slot_t &slot : *m_memo)
{
- if (slot->object != &block)
- return true;
- found= slot;
- return !(slot->type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
+ if (!slot.object || !(flags & slot.type))
+ continue;
+
+ buf_page_t *bpage= static_cast<buf_page_t*>(slot.object);
+
+ if (ptr != bpage->frame)
+ continue;
+
+ ut_ad(!(slot.type & MTR_MEMO_PAGE_S_FIX) || bpage->lock.have_s());
+ ut_ad(!(slot.type & MTR_MEMO_PAGE_SX_FIX) || bpage->lock.have_u_or_x());
+ ut_ad(!(slot.type & MTR_MEMO_PAGE_X_FIX) || bpage->lock.have_x());
+ return static_cast<buf_block_t*>(slot.object);
}
-};
+
+ return nullptr;
+}
+#endif /* UNIV_DEBUG */
+
/** Mark the given latched page as modified.
@param block page that will be modified */
void mtr_t::modify(const buf_block_t &block)
{
- if (UNIV_UNLIKELY(m_memo.empty()))
+ if (UNIV_UNLIKELY(!m_memo))
{
/* This must be PageConverter::update_page() in IMPORT TABLESPACE. */
ut_ad(!block.page.in_LRU_list);
return;
}
- Iterate<FindModified> iteration((FindModified(block)));
- if (UNIV_UNLIKELY(m_memo.for_each_block(iteration)))
+ mtr_memo_slot_t *found= nullptr;
+
+ for (mtr_memo_slot_t &slot : *m_memo)
+ {
+ if (slot.object == &block &&
+ slot.type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))
+ {
+ found= &slot;
+ break;
+ }
+ }
+
+ if (UNIV_UNLIKELY(!found))
{
ut_ad("modifying an unlatched page" == 0);
return;
}
- iteration.functor.found->type= static_cast<mtr_memo_type_t>
- (iteration.functor.found->type | MTR_MEMO_MODIFY);
- if (is_block_dirtied(&block))
- m_made_dirty= true;
+ found->type= static_cast<mtr_memo_type_t>(found->type | MTR_MEMO_MODIFY);
+ if (!m_made_dirty)
+ m_made_dirty= is_block_dirtied(block.page);
}
-/** Handle an exclusively latched block that was later marked as freed. */
-struct MarkFreed
+/** Free a page.
+@param space tablespace
+@param offset offset of the page to be freed */
+void mtr_t::free(const fil_space_t &space, uint32_t offset)
{
- const page_id_t id;
- mutable buf_block_t *freed= nullptr;
- MarkFreed(page_id_t id) : id(id) {}
+ ut_ad(is_named_space(&space));
+ ut_ad(!m_freed_space || m_freed_space == &space);
- bool operator()(mtr_memo_slot_t *slot) const
+ if (is_logged())
{
- buf_block_t *block= static_cast<buf_block_t*>(slot->object);
- if (!block);
- else if (block == freed)
+ ut_ad(m_memo);
+ buf_block_t *freed= nullptr;
+ const page_id_t id{space.id, offset};
+
+ for (auto it= m_memo->rbegin(); it != m_memo->rend(); it++)
{
- if (slot->type & (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX))
- slot->type= MTR_MEMO_PAGE_X_FIX;
- else
+ mtr_memo_slot_t &slot= *it;
+ buf_block_t *block= static_cast<buf_block_t*>(slot.object);
+ if (!block);
+ else if (block == freed)
{
- ut_ad(slot->type == MTR_MEMO_BUF_FIX);
- block->page.unfix();
- slot->object= nullptr;
+ if (slot.type & (MTR_MEMO_PAGE_SX_FIX | MTR_MEMO_PAGE_X_FIX))
+ slot.type= MTR_MEMO_PAGE_X_FIX;
+ else
+ {
+ ut_ad(slot.type == MTR_MEMO_BUF_FIX);
+ slot.object= nullptr;
+ block->page.unfix();
+ }
}
- }
- else if (slot->type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX) &&
- block->page.id() == id)
- {
- ut_ad(!block->page.is_freed());
- ut_ad(!freed);
- freed= block;
- if (!(slot->type & MTR_MEMO_PAGE_X_FIX))
+ else if (slot.type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX) &&
+ block->page.id() == id)
{
- ut_d(bool upgraded=) block->page.lock.x_lock_upgraded();
- ut_ad(upgraded);
- }
- slot->type= MTR_MEMO_PAGE_X_MODIFY;
+ ut_ad(!block->page.is_freed());
+ ut_ad(!freed);
+ freed= block;
+ if (!(slot.type & MTR_MEMO_PAGE_X_FIX))
+ {
+ ut_d(bool upgraded=) block->page.lock.x_lock_upgraded();
+ ut_ad(upgraded);
+ }
+ slot.type= MTR_MEMO_PAGE_X_MODIFY;
#ifdef BTR_CUR_HASH_ADAPT
- if (block->index)
- btr_search_drop_page_hash_index(block);
+ if (block->index)
+ btr_search_drop_page_hash_index(block);
#endif /* BTR_CUR_HASH_ADAPT */
- block->page.set_freed(block->page.state());
+ block->page.set_freed(block->page.state());
+ }
}
- return true;
- }
-};
-/** Free a page.
-@param space tablespace
-@param offset offset of the page to be freed */
-void mtr_t::free(const fil_space_t &space, uint32_t offset)
-{
- ut_ad(is_named_space(&space));
- ut_ad(!m_freed_space || m_freed_space == &space);
-
- if (is_logged())
- {
- CIterate<MarkFreed> mf{MarkFreed{{space.id, offset}}};
- m_memo.for_each_block_in_reverse(mf);
- if (mf.functor.freed && !m_made_dirty)
- m_made_dirty= is_block_dirtied(mf.functor.freed);
- m_log.close(log_write<FREE_PAGE>({space.id, offset}, nullptr));
+ if (freed && !m_made_dirty)
+ m_made_dirty= is_block_dirtied(freed->page);
+ m_log.close(log_write<FREE_PAGE>(id, nullptr));
}
}
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index 3b566e1d6f9..f83b4d774b1 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -276,8 +276,6 @@ Searches the right position for a page cursor. */
bool
page_cur_search_with_match(
/*=======================*/
- const buf_block_t* block, /*!< in: buffer block */
- const dict_index_t* index, /*!< in/out: record descriptor */
const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or
@@ -302,6 +300,8 @@ page_cur_search_with_match(
ulint low_matched_fields;
ulint cur_matched_fields;
int cmp;
+ const dict_index_t* const index = cursor->index;
+ const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */
@@ -551,8 +551,6 @@ first partially matched field in the lower limit record
@param[out] cursor page cursor */
bool
page_cur_search_with_match_bytes(
- const buf_block_t* block,
- const dict_index_t* index,
const dtuple_t* tuple,
page_cur_mode_t mode,
ulint* iup_matched_fields,
@@ -574,6 +572,8 @@ page_cur_search_with_match_bytes(
ulint cur_matched_fields;
ulint cur_matched_bytes;
int cmp;
+ const dict_index_t* const index = cursor->index;
+ const buf_block_t* const block = cursor->block;
#ifdef UNIV_ZIP_DEBUG
const page_zip_des_t* page_zip = buf_block_get_page_zip(block);
#endif /* UNIV_ZIP_DEBUG */
@@ -801,18 +801,13 @@ up_rec_match:
/***********************************************************//**
Positions a page cursor on a randomly chosen user record on a page. If there
are no user records, sets the cursor on the infimum record. */
-void
-page_cur_open_on_rnd_user_rec(
-/*==========================*/
- buf_block_t* block, /*!< in: page */
- page_cur_t* cursor) /*!< out: page cursor */
+void page_cur_open_on_rnd_user_rec(page_cur_t *cursor)
{
- cursor->block= block;
- if (const ulint n_recs= page_get_n_recs(block->page.frame))
- if ((cursor->rec= page_rec_get_nth(block->page.frame,
+ if (const ulint n_recs= page_get_n_recs(cursor->block->page.frame))
+ if ((cursor->rec= page_rec_get_nth(cursor->block->page.frame,
ut_rnd_interval(n_recs) + 1)))
return;
- cursor->rec= page_get_infimum_rec(block->page.frame);
+ cursor->rec= page_get_infimum_rec(cursor->block->page.frame);
}
/**
@@ -1360,12 +1355,12 @@ rec_t*
page_cur_insert_rec_low(
/*====================*/
const page_cur_t*cur, /*!< in: page cursor */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- buf_block_t* block= cur->block;
+ buf_block_t *block= cur->block;
+ dict_index_t * const index= cur->index;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_n_fields(offsets) > 0);
@@ -1785,13 +1780,13 @@ page_cur_insert_rec_zip(
/*====================*/
page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
page_zip_des_t * const page_zip= page_cur_get_page_zip(cursor);
page_t * const page= cursor->block->page.frame;
+ dict_index_t * const index = cursor->index;
ut_ad(page_zip);
ut_ad(rec_offs_validate(rec, index, offsets));
@@ -1893,8 +1888,7 @@ page_cur_insert_rec_zip(
/* Try compressing the whole page afterwards. */
const mtr_log_t log_mode= mtr->set_log_mode(MTR_LOG_NONE);
- rec_t *insert_rec= page_cur_insert_rec_low(cursor, index, rec, offsets,
- mtr);
+ rec_t *insert_rec= page_cur_insert_rec_low(cursor, rec, offsets, mtr);
mtr->set_log_mode(log_mode);
if (insert_rec)
@@ -2242,7 +2236,6 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
- const dict_index_t* index, /*!< in: record descriptor */
const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -2264,6 +2257,7 @@ page_cur_delete_rec(
in the smallest user record, it cannot be used here either. */
current_rec = cursor->rec;
+ const dict_index_t* const index = cursor->index;
buf_block_t* const block = cursor->block;
ut_ad(rec_offs_validate(current_rec, index, offsets));
ut_ad(!!page_is_comp(block->page.frame)
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index 28b63dc4209..1aab3f432da 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -458,6 +458,7 @@ page_copy_rec_list_end_no_locks(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
+ cur1.index = cur2.index = index;
page_cur_position(rec, block, &cur1);
if (page_cur_is_before_first(&cur1) && !page_cur_move_to_next(&cur1)) {
@@ -483,8 +484,8 @@ page_copy_rec_list_end_no_locks(
rec_t* ins_rec;
offsets = rec_get_offsets(cur1.rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap);
- ins_rec = page_cur_insert_rec_low(&cur2, index,
- cur1.rec, offsets, mtr);
+ ins_rec = page_cur_insert_rec_low(&cur2, cur1.rec, offsets,
+ mtr);
if (UNIV_UNLIKELY(!ins_rec || !page_cur_move_to_next(&cur1))) {
err = DB_CORRUPTION;
break;
@@ -733,6 +734,7 @@ corrupted:
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
}
+ cur2.index = index;
page_cur_position(ret, new_block, &cur2);
const ulint n_core = page_rec_is_leaf(rec) ? index->n_core_fields : 0;
@@ -763,9 +765,8 @@ corrupted:
offsets = rec_get_offsets(cur1.rec, index, offsets,
n_core,
ULINT_UNDEFINED, &heap);
- cur2.rec = page_cur_insert_rec_low(&cur2, index,
- cur1.rec, offsets,
- mtr);
+ cur2.rec = page_cur_insert_rec_low(&cur2, cur1.rec,
+ offsets, mtr);
if (UNIV_UNLIKELY(!cur2.rec
|| !page_cur_move_to_next(&cur1))) {
*err = DB_CORRUPTION;
@@ -931,13 +932,14 @@ page_delete_rec_list_end(
{
page_cur_t cur;
page_cur_position(rec, block, &cur);
+ cur.index= index;
offsets= rec_get_offsets(rec, index, offsets, n_core,
ULINT_UNDEFINED, &heap);
rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true));
#ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(&block->page.zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
- page_cur_delete_rec(&cur, index, offsets, mtr);
+ page_cur_delete_rec(&cur, offsets, mtr);
}
while (page_offset(rec) != PAGE_NEW_SUPREMUM);
@@ -1134,6 +1136,7 @@ page_delete_rec_list_start(
return;
}
+ cur1.index = index;
page_cur_set_before_first(block, &cur1);
if (UNIV_UNLIKELY(!page_cur_move_to_next(&cur1))) {
ut_ad("corrupted page" == 0);
@@ -1147,7 +1150,7 @@ page_delete_rec_list_start(
offsets = rec_get_offsets(page_cur_get_rec(&cur1), index,
offsets, n_core,
ULINT_UNDEFINED, &heap);
- page_cur_delete_rec(&cur1, index, offsets, mtr);
+ page_cur_delete_rec(&cur1, offsets, mtr);
}
if (UNIV_LIKELY_NULL(heap)) {
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index c5fe7c04a17..5f5f527e06b 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -322,13 +322,9 @@ que_graph_free_recursive(
case QUE_NODE_UPDATE:
upd = static_cast<upd_node_t*>(node);
- if (upd->in_mysql_interface) {
-
- btr_pcur_free_for_mysql(upd->pcur);
- upd->in_mysql_interface = false;
- }
-
que_graph_free_recursive(upd->cascade_node);
+ ut_free(upd->pcur->old_rec_buf);
+ upd->pcur->old_rec_buf = NULL;
if (upd->cascade_heap) {
mem_heap_free(upd->cascade_heap);
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index b25864f91e8..9e336f267a3 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -257,9 +257,10 @@ public:
}
/** Position the cursor on the first user record. */
- rec_t* open(buf_block_t* block) noexcept
+ rec_t* open(buf_block_t* block, const dict_index_t* index) noexcept
MY_ATTRIBUTE((warn_unused_result))
{
+ m_cur.index = const_cast<dict_index_t*>(index);
page_cur_set_before_first(block, &m_cur);
return next();
}
@@ -289,10 +290,9 @@ public:
/** Remove the current record
@return true on success */
- bool remove(
- const dict_index_t* index,
- rec_offs* offsets) UNIV_NOTHROW
+ bool remove(rec_offs* offsets) UNIV_NOTHROW
{
+ const dict_index_t* const index = m_cur.index;
ut_ad(page_is_leaf(m_cur.block->page.frame));
/* We can't end up with an empty page unless it is root. */
if (page_get_n_recs(m_cur.block->page.frame) <= 1) {
@@ -315,7 +315,7 @@ public:
page_zip, m_cur.block->page.frame, index));
#endif /* UNIV_ZIP_DEBUG */
- page_cur_delete_rec(&m_cur, index, offsets, &m_mtr);
+ page_cur_delete_rec(&m_cur, offsets, &m_mtr);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(
@@ -1734,10 +1734,8 @@ re-organising the B+tree.
@return true if purge succeeded */
inline bool PageConverter::purge() UNIV_NOTHROW
{
- const dict_index_t* index = m_index->m_srv_index;
-
/* We can't have a page that is empty and not root. */
- if (m_rec_iter.remove(index, m_offsets)) {
+ if (m_rec_iter.remove(m_offsets)) {
++m_index->m_stats.m_n_purged;
@@ -1801,7 +1799,7 @@ PageConverter::update_records(
/* This will also position the cursor on the first user record. */
- if (!m_rec_iter.open(block)) {
+ if (!m_rec_iter.open(block, m_index->m_srv_index)) {
return DB_CORRUPTION;
}
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 1d772b02704..9b1d9a8b57f 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -194,8 +194,8 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
- ut_ad(!dict_index_is_clust(cursor->index));
- ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(!cursor->index()->is_clust());
+ ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
ut_ad(!entry->info_bits);
/* We know that in the alphabetical ordering, entry and rec are
@@ -204,7 +204,7 @@ row_ins_sec_index_entry_by_modify(
difference. */
update = row_upd_build_sec_rec_difference_binary(
- rec, cursor->index, *offsets, entry, heap);
+ rec, cursor->index(), *offsets, entry, heap);
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* We should never insert in place of a record that
@@ -218,8 +218,8 @@ row_ins_sec_index_entry_by_modify(
returns. After that point, set_committed(true)
would be invoked in commit_inplace_alter_table(). */
ut_a(update->n_fields == 0);
- ut_a(!cursor->index->is_committed());
- ut_ad(!dict_index_is_online_ddl(cursor->index));
+ ut_a(!cursor->index()->is_committed());
+ ut_ad(!dict_index_is_online_ddl(cursor->index()));
return(DB_SUCCESS);
}
@@ -288,15 +288,15 @@ row_ins_clust_index_entry_by_modify(
dberr_t err = DB_SUCCESS;
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
TABLE* mysql_table = NULL;
- ut_ad(dict_index_is_clust(cursor->index));
+ ut_ad(cursor->index()->is_clust());
rec = btr_cur_get_rec(cursor);
ut_ad(rec_get_deleted_flag(rec,
- dict_table_is_comp(cursor->index->table)));
+ cursor->index()->table->not_redundant()));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
- ut_ad(rec_get_trx_id(rec, cursor->index));
+ ut_ad(rec_get_trx_id(rec, cursor->index()));
/* Build an update vector containing all the fields to be modified;
NOTE that this vector may NOT contain system columns trx_id or
@@ -307,7 +307,7 @@ row_ins_clust_index_entry_by_modify(
}
update = row_upd_build_difference_binary(
- cursor->index, entry, rec, NULL, true, true,
+ cursor->index(), entry, rec, NULL, true, true,
thr_get_trx(thr), heap, mysql_table, &err);
if (err != DB_SUCCESS) {
return(err);
@@ -1115,7 +1115,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- index = btr_pcur_get_btr_cur(pcur)->index;
+ index = pcur->index();
ut_a(index == foreign->foreign_index);
@@ -1139,7 +1139,8 @@ row_ins_foreign_check_on_constraint(
ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,
tmp_heap);
cascade->pcur->old_rec = nullptr;
- err = btr_pcur_open_with_no_init(clust_index, ref,
+ cascade->pcur->btr_cur.page_cur.index = clust_index;
+ err = btr_pcur_open_with_no_init(ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -1623,9 +1624,9 @@ row_ins_check_foreign_constraint(
n_fields_cmp = dtuple_get_n_fields_cmp(entry);
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
-
- err = btr_pcur_open(check_index, entry, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.btr_cur.page_cur.index = check_index;
+ err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, 0,
+ &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
goto end_scan;
}
@@ -2065,9 +2066,9 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_set_n_fields_cmp(entry, n_unique);
const auto allow_duplicates = thr_get_trx(thr)->duplicates;
-
- dberr_t err = btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
- &pcur, mtr);
+ pcur.btr_cur.page_cur.index = index;
+ dberr_t err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
+ &pcur, 0, mtr);
if (err != DB_SUCCESS) {
goto end_scan;
}
@@ -2219,11 +2220,11 @@ row_ins_duplicate_error_in_clust_online(
dberr_t err = DB_SUCCESS;
const rec_t* rec = btr_cur_get_rec(cursor);
- ut_ad(!cursor->index->is_instant());
+ ut_ad(!cursor->index()->is_instant());
if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
- cursor->index->n_fields,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
+ cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets);
if (err != DB_SUCCESS) {
@@ -2236,8 +2237,8 @@ row_ins_duplicate_error_in_clust_online(
}
if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) {
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
- cursor->index->n_fields,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
+ cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets);
}
@@ -2270,7 +2271,7 @@ row_ins_duplicate_error_in_clust(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
- ut_ad(dict_index_is_clust(cursor->index));
+ ut_ad(cursor->index()->is_clust());
/* NOTE: For unique non-clustered indexes there may be any number
of delete marked records with the same value for the non-clustered
@@ -2285,15 +2286,17 @@ row_ins_duplicate_error_in_clust(
user records on the leaf level. So, even if low_match would suggest
that a duplicate key violation may occur, this may not be the case. */
- n_unique = dict_index_get_n_unique(cursor->index);
+ n_unique = dict_index_get_n_unique(cursor->index());
if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor);
if (!page_rec_is_infimum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(rec, cursor->index(),
+ offsets,
+ cursor->index()
+ ->n_core_fields,
ULINT_UNDEFINED, &heap);
/* We set a lock on the possible duplicate: this
@@ -2314,13 +2317,13 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), rec,
- cursor->index, offsets, thr);
+ cursor->index(), offsets, thr);
}
switch (err) {
@@ -2332,11 +2335,11 @@ row_ins_duplicate_error_in_clust(
}
if (row_ins_dupl_error_with_rec(
- rec, entry, cursor->index, offsets)) {
+ rec, entry, cursor->index(), offsets)) {
duplicate:
- trx->error_info = cursor->index;
+ trx->error_info = cursor->index();
err = DB_DUPLICATE_KEY;
- if (cursor->index->table->versioned()
+ if (cursor->index()->table->versioned()
&& entry->vers_history_row())
{
ulint trx_id_len;
@@ -2360,8 +2363,10 @@ duplicate:
rec = page_rec_get_next(btr_cur_get_rec(cursor));
if (rec && !page_rec_is_supremum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(rec, cursor->index(),
+ offsets,
+ cursor->index()
+ ->n_core_fields,
ULINT_UNDEFINED, &heap);
if (trx->duplicates) {
@@ -2374,13 +2379,13 @@ duplicate:
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
}
switch (err) {
@@ -2391,7 +2396,7 @@ duplicate:
/* fall through */
case DB_SUCCESS:
if (row_ins_dupl_error_with_rec(
- rec, entry, cursor->index,
+ rec, entry, cursor->index(),
offsets)) {
goto duplicate;
}
@@ -2433,7 +2438,7 @@ row_ins_must_modify_rec(
and a secondary index node pointer contains all index fields. */
return(cursor->low_match
- >= dict_index_get_n_unique_in_tree(cursor->index)
+ >= dict_index_get_n_unique_in_tree(cursor->index())
&& !page_rec_is_infimum(btr_cur_get_rec(cursor)));
}
@@ -2462,6 +2467,7 @@ row_ins_index_entry_big_rec(
btr_pcur_t pcur;
rec_t* rec;
+ pcur.btr_cur.page_cur.index = index;
ut_ad(index->is_primary());
DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern_latch");
@@ -2473,8 +2479,8 @@ row_ins_index_entry_big_rec(
index->set_modified(mtr);
}
- dberr_t error = btr_pcur_open(index, entry, PAGE_CUR_LE,
- BTR_MODIFY_TREE, &pcur, &mtr);
+ dberr_t error = btr_pcur_open(entry, PAGE_CUR_LE,
+ BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) {
return error;
}
@@ -2600,8 +2606,8 @@ row_ins_clust_index_entry_low(
/* Note that we use PAGE_CUR_LE as the search mode, because then
the function will return in both low_match and up_match of the
cursor sensible values */
- err = btr_pcur_open_low(index, 0, entry, PAGE_CUR_LE, mode, &pcur,
- auto_inc, &mtr);
+ pcur.btr_cur.page_cur.index = index;
+ err = btr_pcur_open(entry, PAGE_CUR_LE, mode, &pcur, auto_inc, &mtr);
if (err != DB_SUCCESS) {
index->table->file_unreadable = true;
commit_exit:
@@ -2712,7 +2718,7 @@ skip_bulk_insert:
/* fall through */
case DB_SUCCESS_LOCKED_REC:
case DB_DUPLICATE_KEY:
- trx->error_info = cursor->index;
+ trx->error_info = cursor->index();
}
} else {
/* Note that the following may return also
@@ -2861,6 +2867,7 @@ row_ins_sec_index_entry_low(
cursor.thr = thr;
cursor.rtr_info = NULL;
+ cursor.page_cur.index = index;
ut_ad(thr_get_trx(thr)->id != 0);
mtr.start();
@@ -2878,15 +2885,13 @@ row_ins_sec_index_entry_low(
the function will return in both low_match and up_match of the
cursor sensible values */
- if (dict_index_is_spatial(index)) {
- cursor.index = index;
+ if (index->is_spatial()) {
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
rtr_info_update_btr(&cursor, &rtr_info);
- err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_RTREE_INSERT,
- search_mode,
- &cursor, &mtr);
+ err = btr_cur_search_to_nth_level(0, entry,
+ PAGE_CUR_RTREE_INSERT,
+ search_mode, &cursor, &mtr);
if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF
&& rtr_info.mbr_adj) {
@@ -2903,9 +2908,8 @@ row_ins_sec_index_entry_low(
index->set_modified(mtr);
}
err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_RTREE_INSERT,
- search_mode,
- &cursor, &mtr);
+ 0, entry, PAGE_CUR_RTREE_INSERT,
+ search_mode, &cursor, &mtr);
}
DBUG_EXECUTE_IF(
@@ -2921,10 +2925,8 @@ row_ins_sec_index_entry_low(
: BTR_INSERT));
}
- err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
- search_mode,
- &cursor, &mtr);
+ err = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
+ search_mode, &cursor, &mtr);
}
if (err != DB_SUCCESS) {
@@ -3001,7 +3003,7 @@ row_ins_sec_index_entry_low(
transaction. Let us now reposition the cursor and
continue the insertion (bypassing the change buffer). */
err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
+ 0, entry, PAGE_CUR_LE,
btr_latch_mode(search_mode
& ~(BTR_INSERT
| BTR_IGNORE_SEC_UNIQUE)),
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 1b56d18cd3d..0689f9ca029 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -1658,7 +1658,7 @@ row_log_table_apply_delete_low(
dberr_t error;
row_ext_t* ext;
dtuple_t* row;
- dict_index_t* index = btr_pcur_get_btr_cur(pcur)->index;
+ dict_index_t* index = pcur->index();
ut_ad(dict_index_is_clust(index));
@@ -1695,8 +1695,9 @@ err_exit:
row, ext, index, heap);
mtr->start();
index->set_modified(*mtr);
- error = btr_pcur_open(index, entry, PAGE_CUR_LE,
- BTR_PURGE_TREE, pcur, mtr);
+ pcur->btr_cur.page_cur.index = index;
+ error = btr_pcur_open(entry, PAGE_CUR_LE,
+ BTR_PURGE_TREE, pcur, 0, mtr);
if (error) {
goto err_exit;
}
@@ -1760,6 +1761,7 @@ row_log_table_apply_delete(
btr_pcur_t pcur;
rec_offs* offsets;
+ pcur.btr_cur.page_cur.index = index;
ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field());
ut_ad(!rec_offs_any_extern(moffsets));
@@ -1778,8 +1780,8 @@ row_log_table_apply_delete(
mtr_start(&mtr);
index->set_modified(mtr);
- dberr_t err = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
- BTR_PURGE_TREE, &pcur, &mtr);
+ dberr_t err = btr_pcur_open(old_pk, PAGE_CUR_LE,
+ BTR_PURGE_TREE, &pcur, 0, &mtr);
if (err != DB_SUCCESS) {
goto all_done;
}
@@ -1891,6 +1893,8 @@ row_log_table_apply_update(
dberr_t error;
ulint n_index = 0;
+ pcur.btr_cur.page_cur.index = index;
+
ut_ad(dtuple_get_n_fields_cmp(old_pk)
== dict_index_get_n_unique(index));
ut_ad(dtuple_get_n_fields(old_pk) - (log->same_pk ? 0 : 2)
@@ -1913,8 +1917,8 @@ row_log_table_apply_update(
mtr.start();
index->set_modified(mtr);
- error = btr_pcur_open(index, old_pk, PAGE_CUR_LE,
- BTR_MODIFY_TREE, &pcur, &mtr);
+ error = btr_pcur_open(old_pk, PAGE_CUR_LE,
+ BTR_MODIFY_TREE, &pcur, 0, &mtr);
if (error != DB_SUCCESS) {
func_exit:
mtr.commit();
@@ -2059,7 +2063,7 @@ func_exit_committed:
for (n_index += index->type != DICT_CLUSTERED;
(index = dict_table_get_next_index(index)); n_index++) {
- if (index->type & DICT_FTS) {
+ if (!index->is_btree()) {
continue;
}
@@ -2087,9 +2091,10 @@ func_exit_committed:
mtr.start();
index->set_modified(mtr);
+ pcur.btr_cur.page_cur.index = index;
if (ROW_FOUND != row_search_index_entry(
- index, entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
+ entry, BTR_MODIFY_TREE, &pcur, &mtr)) {
ut_ad(0);
error = DB_CORRUPTION;
break;
@@ -3069,13 +3074,14 @@ row_log_apply_op_low(
mtr_start(&mtr);
index->set_modified(mtr);
+ cursor.page_cur.index = index;
/* We perform the pessimistic variant of the operations if we
already hold index->lock exclusively. First, search the
record. The operation may already have been performed,
depending on when the row in the clustered index was
scanned. */
- *error = btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
+ *error = btr_cur_search_to_nth_level(0, entry, PAGE_CUR_LE,
has_index_lock
? BTR_MODIFY_TREE
: BTR_MODIFY_LEAF,
@@ -3130,7 +3136,7 @@ row_log_apply_op_low(
mtr_start(&mtr);
index->set_modified(mtr);
*error = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
+ 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr);
if (UNIV_UNLIKELY(*error != DB_SUCCESS)) {
goto func_exit;
@@ -3234,7 +3240,7 @@ insert_the_rec:
mtr_start(&mtr);
index->set_modified(mtr);
*error = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
+ 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, &mtr);
if (*error != DB_SUCCESS) {
break;
@@ -3949,8 +3955,8 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
}
bool success= true;
- dict_index_t *index= dict_table_get_next_index(clust_index);
- while (index)
+ for (dict_index_t *index= clust_index;
+ (index= dict_table_get_next_index(index)) != nullptr; )
{
index->lock.s_lock(SRW_LOCK_CALL);
if (index->online_log &&
@@ -3969,7 +3975,6 @@ void UndorecApplier::log_insert(const dtuple_t &tuple,
row_log_mark_other_online_index_abort(index->table);
return;
}
- index= dict_table_get_next_index(index);
}
}
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 56b5ab2f883..dba3c0a144a 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -145,13 +145,13 @@ public:
mtr.start();
index->set_modified(mtr);
- ins_cur.index = index;
+ ins_cur.page_cur.index = index;
rtr_init_rtr_info(&rtr_info, false, &ins_cur, index,
false);
rtr_info_update_btr(&ins_cur, &rtr_info);
error = btr_cur_search_to_nth_level(
- index, 0, dtuple, PAGE_CUR_RTREE_INSERT,
+ 0, dtuple, PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_LEAF, &ins_cur, &mtr);
/* It need to update MBR in parent entry,
@@ -165,7 +165,7 @@ public:
mtr.start();
index->set_modified(mtr);
error = btr_cur_search_to_nth_level(
- index, 0, dtuple,
+ 0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE, &ins_cur, &mtr);
}
@@ -190,7 +190,7 @@ public:
rtr_info_update_btr(&ins_cur, &rtr_info);
error = btr_cur_search_to_nth_level(
- index, 0, dtuple,
+ 0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE,
&ins_cur, &mtr);
@@ -2061,13 +2061,15 @@ end_of_index:
if (!block) {
goto err_exit;
}
- btr_leaf_page_release(page_cur_get_block(cur),
- BTR_SEARCH_LEAF, &mtr);
+
page_cur_set_before_first(block, cur);
if (!page_cur_move_to_next(cur)
|| page_cur_is_after_last(cur)) {
goto corrupted_rec;
}
+
+ const auto s = mtr.get_savepoint();
+ mtr.rollback_to_savepoint(s - 2, s - 1);
}
} else {
mem_heap_empty(row_heap);
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index de469c5b088..6ac0d26bb2a 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1456,11 +1456,8 @@ row_create_update_node_for_mysql(
node->in_mysql_interface = true;
node->is_delete = NO_DELETE;
- node->searched_update = FALSE;
- node->select = NULL;
- node->pcur = btr_pcur_create_for_mysql();
-
- DBUG_PRINT("info", ("node: %p, pcur: %p", node, node->pcur));
+ node->pcur = new (mem_heap_alloc(heap, sizeof(btr_pcur_t)))
+ btr_pcur_t();
node->table = table;
@@ -1472,10 +1469,6 @@ row_create_update_node_for_mysql(
UT_LIST_INIT(node->columns, &sym_node_t::col_var_list);
node->has_clust_rec_x_lock = TRUE;
- node->cmpl_info = 0;
-
- node->table_sym = NULL;
- node->col_assign_list = NULL;
DBUG_RETURN(node);
}
@@ -1650,8 +1643,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
clust_index = dict_table_get_first_index(table);
btr_pcur_copy_stored_position(node->pcur,
- prebuilt->pcur->btr_cur.index
- == clust_index
+ prebuilt->pcur->index() == clust_index
? prebuilt->pcur
: prebuilt->clust_pcur);
@@ -1804,7 +1796,7 @@ row_unlock_for_mysql(
}
rec = btr_pcur_get_rec(pcur);
- index = btr_pcur_get_btr_cur(pcur)->index;
+ index = pcur->index();
/* If the record has been modified by this
transaction, do not unlock it. */
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 3c3beeb0eda..e216d9faa3b 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -347,8 +347,9 @@ row_purge_remove_sec_if_poss_tree(
log_free_check();
mtr.start();
index->set_modified(mtr);
+ pcur.btr_cur.page_cur.index = index;
- search_result = row_search_index_entry(index, entry, BTR_PURGE_TREE,
+ search_result = row_search_index_entry(entry, BTR_PURGE_TREE,
&pcur, &mtr);
switch (search_result) {
@@ -452,6 +453,7 @@ row_purge_remove_sec_if_poss_leaf(
virtual index. */
mode = (index->type & (DICT_SPATIAL | DICT_VIRTUAL))
? BTR_MODIFY_LEAF : BTR_PURGE_LEAF;
+ pcur.btr_cur.page_cur.index = index;
/* Set the purge node for the call to row_purge_poss_sec(). */
pcur.btr_cur.purge_node = node;
@@ -459,7 +461,7 @@ row_purge_remove_sec_if_poss_leaf(
pcur.btr_cur.thr = NULL;
index->lock.u_lock(SRW_LOCK_CALL);
search_result = row_search_index_entry(
- index, entry, mode, &pcur, &mtr);
+ entry, mode, &pcur, &mtr);
index->lock.u_unlock();
} else {
/* Set the query thread, so that ibuf_insert_low() will be
@@ -467,7 +469,7 @@ row_purge_remove_sec_if_poss_leaf(
pcur.btr_cur.thr = static_cast<que_thr_t*>(
que_node_get_parent(node));
search_result = row_search_index_entry(
- index, entry, mode, &pcur, &mtr);
+ entry, mode, &pcur, &mtr);
}
switch (search_result) {
@@ -1344,7 +1346,7 @@ purge_node_t::validate_pcur()
return(true);
}
- dict_index_t* clust_index = pcur.btr_cur.index;
+ dict_index_t* clust_index = pcur.index();
rec_offs* offsets = rec_get_offsets(
pcur.old_rec, clust_index, NULL, pcur.old_n_core_fields,
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index 62a41be115e..599033353c5 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -1196,11 +1196,12 @@ row_search_on_row_ref(
ut_ad(dtuple_check_typed(ref));
dict_index_t *index = dict_table_get_first_index(table);
+ btr_pcur_init(pcur);
+ pcur->btr_cur.page_cur.index = index;
if (UNIV_UNLIKELY(ref->info_bits != 0)) {
ut_ad(ref->is_metadata());
ut_ad(ref->n_fields <= index->n_uniq);
- btr_pcur_init(pcur);
if (pcur->open_leaf(true, index, mode, mtr) != DB_SUCCESS
|| !btr_pcur_move_to_next_user_rec(pcur, mtr)) {
return false;
@@ -1215,7 +1216,7 @@ row_search_on_row_ref(
& REC_INFO_MIN_REC_FLAG;
} else {
ut_a(ref->n_fields == index->n_uniq);
- if (btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr)
+ if (btr_pcur_open(ref, PAGE_CUR_LE, mode, pcur, 0, mtr)
!= DB_SUCCESS) {
return false;
}
@@ -1265,7 +1266,6 @@ Searches an index record.
enum row_search_result
row_search_index_entry(
/*===================*/
- dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */
btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
@@ -1278,12 +1278,12 @@ row_search_index_entry(
ut_ad(dtuple_check_typed(entry));
- if (index->is_spatial()) {
- if (rtr_pcur_open(index, entry, mode, pcur, mtr)) {
+ if (pcur->index()->is_spatial()) {
+ if (rtr_pcur_open(pcur->index(), entry, mode, pcur, mtr)) {
return ROW_NOT_FOUND;
}
} else {
- if (btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr)
+ if (btr_pcur_open(entry, PAGE_CUR_LE, mode, pcur, 0, mtr)
!= DB_SUCCESS) {
return ROW_NOT_FOUND;
}
@@ -1292,7 +1292,7 @@ row_search_index_entry(
switch (btr_pcur_get_btr_cur(pcur)->flag) {
case BTR_CUR_DELETE_REF:
ut_ad(!(~mode & BTR_DELETE));
- ut_ad(!index->is_spatial());
+ ut_ad(!pcur->index()->is_spatial());
return(ROW_NOT_DELETED_REF);
case BTR_CUR_DEL_MARK_IBUF:
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 615f767e7d2..41c9f4456e4 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -1009,17 +1009,16 @@ row_sel_get_clust_rec(
*out_rec = NULL;
- offsets = rec_get_offsets(rec,
- btr_pcur_get_btr_cur(&plan->pcur)->index,
- offsets,
- btr_pcur_get_btr_cur(&plan->pcur)->index
- ->n_core_fields, ULINT_UNDEFINED, &heap);
+ offsets = rec_get_offsets(rec, plan->pcur.index(), offsets,
+ plan->pcur.index()->n_core_fields,
+ ULINT_UNDEFINED, &heap);
row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
index = dict_table_get_first_index(plan->table);
plan->clust_pcur.old_rec = nullptr;
- dberr_t err = btr_pcur_open_with_no_init(index, plan->clust_ref,
+ plan->clust_pcur.btr_cur.page_cur.index = index;
+ dberr_t err = btr_pcur_open_with_no_init(plan->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
&plan->clust_pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -1412,6 +1411,7 @@ row_sel_open_pcur(
}
plan->pcur.old_rec = nullptr;
+ plan->pcur.btr_cur.page_cur.index = index;
dberr_t err;
@@ -1432,7 +1432,7 @@ row_sel_open_pcur(
que_node_get_val(exp));
}
- err = btr_pcur_open_with_no_init(index, plan->tuple,
+ err = btr_pcur_open_with_no_init(plan->tuple,
plan->mode, BTR_SEARCH_LEAF,
&plan->pcur, mtr);
} else {
@@ -3383,9 +3383,9 @@ Row_sel_get_clust_rec_for_mysql::operator()(
sec_index, *offsets);
clust_index = dict_table_get_first_index(sec_index->table);
+ prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
- dberr_t err = btr_pcur_open_with_no_init(clust_index,
- prebuilt->clust_ref,
+ dberr_t err = btr_pcur_open_with_no_init(prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@@ -3450,9 +3450,10 @@ Row_sel_get_clust_rec_for_mysql::operator()(
rec, sec_index, true,
sec_index->n_fields, heap);
page_cur_t page_cursor;
+ page_cursor.block = block;
+ page_cursor.index = sec_index;
ulint up_match = 0, low_match = 0;
- ut_ad(!page_cur_search_with_match(block, sec_index,
- tuple, PAGE_CUR_LE,
+ ut_ad(!page_cur_search_with_match(tuple, PAGE_CUR_LE,
&up_match,
&low_match,
&page_cursor,
@@ -3672,7 +3673,7 @@ static bool sel_restore_position_for_mysql(bool *same_user_rec,
next:
if (btr_pcur_move_to_next(pcur, mtr)
&& rec_is_metadata(btr_pcur_get_rec(pcur),
- *pcur->btr_cur.index)) {
+ *pcur->index())) {
btr_pcur_move_to_next(pcur, mtr);
}
@@ -3688,7 +3689,7 @@ next:
prev:
if (btr_pcur_is_on_user_rec(pcur) && !moves_up
&& !rec_is_metadata(btr_pcur_get_rec(pcur),
- *pcur->btr_cur.index)) {
+ *pcur->index())) {
if (!btr_pcur_move_to_prev(pcur, mtr)) {
return true;
}
@@ -3970,7 +3971,7 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(trx->read_view.is_open());
pcur->old_rec = nullptr;
- if (btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
+ if (btr_pcur_open_with_no_init(search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, mtr)
!= DB_SUCCESS) {
return SEL_RETRY;
@@ -4400,6 +4401,8 @@ row_search_mvcc(
DBUG_RETURN(DB_CORRUPTION);
}
+ pcur->btr_cur.page_cur.index = index;
+
/* We need to get the virtual column values stored in secondary
index key, if this is covered index scan or virtual key read is
requested. */
@@ -4791,7 +4794,7 @@ wait_table_again:
}
}
- err = btr_pcur_open_with_no_init(index, search_tuple, mode,
+ err = btr_pcur_open_with_no_init(search_tuple, mode,
BTR_SEARCH_LEAF, pcur, &mtr);
if (err != DB_SUCCESS) {
@@ -6212,6 +6215,7 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows)
mtr.start();
dict_index_t *clust_index= dict_table_get_first_index(prebuilt->table);
+ prebuilt->clust_pcur->btr_cur.page_cur.index = clust_index;
dberr_t err= prebuilt->pcur->open_leaf(true, index, BTR_SEARCH_LEAF, &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS))
{
@@ -6387,7 +6391,7 @@ rec_loop:
const auto savepoint= mtr.get_savepoint();
row_build_row_ref_in_tuple(prebuilt->clust_ref, rec, index, offsets);
- err= btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
+ err= btr_pcur_open_with_no_init(prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, &mtr);
if (err != DB_SUCCESS)
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index eae89a36a6d..6567019a33d 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -68,7 +68,7 @@ row_undo_ins_remove_clust_rec(
dberr_t err;
ulint n_tries = 0;
mtr_t mtr;
- dict_index_t* index = node->pcur.btr_cur.index;
+ dict_index_t* index = node->pcur.index();
table_id_t table_id = 0;
const bool dict_locked = node->trx->dict_operation_lock_mode;
restart:
@@ -265,6 +265,7 @@ row_undo_ins_remove_sec_low(
mtr_t mtr;
const bool modify_leaf = mode == BTR_MODIFY_LEAF;
+ pcur.btr_cur.page_cur.index = index;
row_mtr_start(&mtr, index, !modify_leaf);
if (modify_leaf) {
@@ -284,7 +285,7 @@ row_undo_ins_remove_sec_low(
btr_pcur_get_btr_cur(&pcur)->thr = thr;
}
- switch (row_search_index_entry(index, entry, mode, &pcur, &mtr)) {
+ switch (row_search_index_entry(entry, mode, &pcur, &mtr)) {
case ROW_BUFFERED:
case ROW_NOT_DELETED_REF:
/* These are invalid outcomes, because the mode passed
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 01b639db085..2d04dca4003 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -224,14 +224,14 @@ static bool row_undo_mod_must_purge(const undo_node_t &node)
ut_ad(!node.table->is_temporary());
const btr_cur_t &btr_cur= node.pcur.btr_cur;
- ut_ad(btr_cur.index->is_primary());
+ ut_ad(btr_cur.index()->is_primary());
DEBUG_SYNC_C("rollback_purge_clust");
if (!purge_sys.is_purgeable(node.new_trx_id))
return false;
const rec_t *rec= btr_cur_get_rec(&btr_cur);
- return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index)) ==
+ return trx_read_trx_id(rec + row_trx_id_offset(rec, btr_cur.index())) ==
node.new_trx_id;
}
@@ -495,6 +495,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
row_mtr_start(&mtr, index, !modify_leaf);
+ pcur.btr_cur.page_cur.index = index;
btr_cur = btr_pcur_get_btr_cur(&pcur);
if (index->is_spatial()) {
@@ -522,8 +523,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
ut_ad(!dict_index_is_online_ddl(index));
}
- search_result = row_search_index_entry(index, entry, mode,
- &pcur, &mtr);
+ search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
case ROW_NOT_FOUND:
@@ -668,6 +668,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
row_search_result search_result;
const auto orig_mode = mode;
+ pcur.btr_cur.page_cur.index = index;
ut_ad(trx->id != 0);
if (dict_index_is_spatial(index)) {
@@ -685,8 +686,7 @@ try_again:
btr_cur->thr = thr;
- search_result = row_search_index_entry(index, entry, mode,
- &pcur, &mtr);
+ search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
switch (search_result) {
mem_heap_t* heap;
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 36941798bc2..3b2fe849bcd 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -1899,9 +1899,9 @@ row_upd_sec_index_entry(
/* Set the query thread, so that ibuf_insert_low() will be
able to invoke thd_get_trx(). */
btr_pcur_get_btr_cur(&pcur)->thr = thr;
+ pcur.btr_cur.page_cur.index = index;
- search_result = row_search_index_entry(index, entry, mode,
- &pcur, &mtr);
+ search_result = row_search_index_entry(entry, mode, &pcur, &mtr);
btr_cur = btr_pcur_get_btr_cur(&pcur);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index f9a152e294e..45292fc1d0b 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -594,7 +594,7 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo)
if (undo_block != block)
{
- mtr.memo_release(undo_block, MTR_MEMO_PAGE_S_FIX);
+ mtr.release(*undo_block);
undo_block= block;
}
trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,