summaryrefslogtreecommitdiff
path: root/storage/innobase/btr/btr0defragment.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/btr/btr0defragment.cc')
-rw-r--r--storage/innobase/btr/btr0defragment.cc85
1 files changed, 54 insertions, 31 deletions
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index 8823bab572d..23d93caecf5 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (C) 2012, 2014 Facebook, Inc. All Rights Reserved.
-Copyright (C) 2014, 2021, MariaDB Corporation.
+Copyright (C) 2014, 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
@@ -283,7 +283,8 @@ btr_defragment_calc_n_recs_for_size(
/*************************************************************//**
Merge as many records from the from_block to the to_block. Delete
the from_block if all records are successfully merged to to_block.
-@return the to_block to target for next merge operation. */
+@return the to_block to target for next merge operation.
+@retval nullptr if corruption was noticed */
static
buf_block_t*
btr_defragment_merge_pages(
@@ -330,9 +331,9 @@ btr_defragment_merge_pages(
// reorganizing the page, otherwise we need to reorganize the page
// first to release more space.
if (move_size > max_ins_size) {
- if (!btr_page_reorganize_block(page_zip_level,
- to_block, index,
- mtr)) {
+ dberr_t err = btr_page_reorganize_block(page_zip_level,
+ to_block, index, mtr);
+ if (err != DB_SUCCESS) {
if (!dict_index_is_clust(index)
&& page_is_leaf(to_page)) {
ibuf_reset_free_bits(to_block);
@@ -341,23 +342,30 @@ btr_defragment_merge_pages(
// not compressable. There's no point to try
// merging into this page. Continue to the
// next page.
- return from_block;
+ return err == DB_FAIL ? from_block : nullptr;
}
ut_ad(page_validate(to_page, index));
max_ins_size = page_get_max_insert_size(to_page, n_recs);
- ut_a(max_ins_size >= move_size);
+ if (max_ins_size < move_size) {
+ return nullptr;
+ }
}
// Move records to pack to_page more full.
orig_pred = NULL;
target_n_recs = n_recs_to_move;
+ dberr_t err;
while (n_recs_to_move > 0) {
rec = page_rec_get_nth(from_page,
n_recs_to_move + 1);
orig_pred = page_copy_rec_list_start(
- to_block, from_block, rec, index, mtr);
+ to_block, from_block, rec, index, mtr, &err);
if (orig_pred)
break;
+ if (err != DB_FAIL) {
+ return nullptr;
+ }
+
// If we reach here, that means compression failed after packing
// n_recs_to_move number of records to to_page. We try to reduce
// the targeted data size on the to_page by
@@ -396,19 +404,20 @@ btr_defragment_merge_pages(
}
}
btr_cur_t parent;
- if (n_recs_to_move == n_recs) {
+ if (!btr_page_get_father(index, from_block, mtr, &parent)) {
+ to_block = nullptr;
+ } else if (n_recs_to_move == n_recs) {
/* The whole page is merged with the previous page,
free it. */
- const page_id_t from{from_block->page.id()};
- lock_update_merge_left(*to_block, orig_pred, from);
+ lock_update_merge_left(*to_block, orig_pred,
+ from_block->page.id());
btr_search_drop_page_hash_index(from_block);
- ut_a(DB_SUCCESS == btr_level_list_remove(*from_block, *index,
- mtr));
- btr_page_get_father(index, from_block, mtr, &parent);
- btr_cur_node_ptr_delete(&parent, mtr);
- /* btr_blob_dbg_remove(from_page, index,
- "btr_defragment_n_pages"); */
- btr_page_free(index, from_block, mtr);
+ if (btr_level_list_remove(*from_block, *index, mtr)
+ != DB_SUCCESS
+ || btr_cur_node_ptr_delete(&parent, mtr) != DB_SUCCESS
+ || btr_page_free(index, from_block, mtr) != DB_SUCCESS) {
+ return nullptr;
+ }
} else {
// There are still records left on the page, so
// increment n_defragmented. Node pointer will be changed
@@ -424,15 +433,20 @@ btr_defragment_merge_pages(
orig_pred,
from_block);
// FIXME: reuse the node_ptr!
- btr_page_get_father(index, from_block, mtr, &parent);
- btr_cur_node_ptr_delete(&parent, mtr);
+ if (btr_cur_node_ptr_delete(&parent, mtr)
+ != DB_SUCCESS) {
+ return nullptr;
+ }
rec = page_rec_get_next(
page_get_infimum_rec(from_page));
node_ptr = dict_index_build_node_ptr(
index, rec, page_get_page_no(from_page),
heap, level);
- btr_insert_on_non_leaf_level(0, index, level+1,
- node_ptr, mtr);
+ if (btr_insert_on_non_leaf_level(0, index, level+1,
+ node_ptr, mtr)
+ != DB_SUCCESS) {
+ return nullptr;
+ }
}
to_block = from_block;
}
@@ -507,6 +521,9 @@ btr_defragment_n_pages(
blocks[i] = btr_block_get(*index, page_no, RW_X_LATCH, true,
mtr);
+ if (!blocks[i]) {
+ return nullptr;
+ }
}
if (n_pages == 1) {
@@ -517,7 +534,8 @@ btr_defragment_n_pages(
return NULL;
/* given page is the last page.
Lift the records to father. */
- btr_lift_page_up(index, block, mtr);
+ dberr_t err;
+ btr_lift_page_up(index, block, mtr, &err);
}
return NULL;
}
@@ -580,6 +598,9 @@ btr_defragment_n_pages(
if (new_block != current_block) {
n_defragmented ++;
current_block = new_block;
+ if (!new_block) {
+ break;
+ }
}
}
mem_heap_free(heap);
@@ -667,17 +688,19 @@ processed:
mtr_start(&mtr);
dict_index_t *index = item->pcur->btr_cur.index;
index->set_modified(mtr);
- /* To follow the latching order defined in WL#6326, acquire index->lock X-latch.
- This entitles us to acquire page latches in any order for the index. */
+ /* To follow the latching order defined in WL#6326,
+ acquire index->lock X-latch. This entitles us to
+ acquire page latches in any order for the index. */
mtr_x_lock_index(index, &mtr);
- /* This will acquire index->lock SX-latch, which per WL#6363 is allowed
+ /* This will acquire index->lock U latch, which is allowed
when we are already holding the X-latch. */
- item->pcur->restore_position(BTR_MODIFY_TREE, &mtr);
- buf_block_t* first_block = btr_pcur_get_block(item->pcur);
if (buf_block_t *last_block =
- btr_defragment_n_pages(first_block, index,
- srv_defragment_n_pages,
- &mtr)) {
+ item->pcur->restore_position(BTR_MODIFY_TREE, &mtr)
+ == btr_pcur_t::CORRUPTED
+ ? nullptr
+ : btr_defragment_n_pages(btr_pcur_get_block(item->pcur),
+ index, srv_defragment_n_pages,
+ &mtr)) {
/* If we haven't reached the end of the index,
place the cursor on the last record of last page,
store the cursor position, and put back in queue. */