MDEV-21174: Replace mlog_write_ulint() with mtr_t::write()

mtr_t::write(): Replaces mlog_write_ulint(), mlog_write_ull().
Optimize away writes if the page contents does not change,
except when a dummy write has been explicitly requested.

Because the member function template takes a block descriptor as a
parameter, it is possible to introduce better consistency checks.
Due to this, the code for handling file-based lists, undo logs
and user transactions was refactored to pass around buf_block_t.
This commit is contained in:
Marko Mäkelä 2019-12-03 10:19:45 +02:00
parent 504823bcce
commit 56f6dab1d0
53 changed files with 2735 additions and 3531 deletions

File diff suppressed because it is too large Load Diff

View File

@ -92,6 +92,8 @@ PageBulk::init()
new_page_zip = buf_block_get_page_zip(new_block); new_page_zip = buf_block_get_page_zip(new_block);
new_page_no = page_get_page_no(new_page); new_page_no = page_get_page_no(new_page);
byte* index_id = PAGE_HEADER + PAGE_INDEX_ID + new_page;
if (new_page_zip) { if (new_page_zip) {
page_create_zip(new_block, m_index, m_level, 0, page_create_zip(new_block, m_index, m_level, 0,
&m_mtr); &m_mtr);
@ -100,11 +102,9 @@ PageBulk::init()
page_zip_write_header(new_page_zip, page_zip_write_header(new_page_zip,
FIL_PAGE_PREV + new_page, FIL_PAGE_PREV + new_page,
8, &m_mtr); 8, &m_mtr);
mach_write_to_8(PAGE_HEADER + PAGE_INDEX_ID + new_page, mach_write_to_8(index_id, m_index->id);
m_index->id); page_zip_write_header(new_page_zip, index_id,
page_zip_write_header(new_page_zip, 8, &m_mtr);
PAGE_HEADER + PAGE_INDEX_ID
+ new_page, 8, &m_mtr);
} else { } else {
ut_ad(!dict_index_is_spatial(m_index)); ut_ad(!dict_index_is_spatial(m_index));
page_create(new_block, &m_mtr, page_create(new_block, &m_mtr,
@ -114,10 +114,10 @@ PageBulk::init()
== FIL_PAGE_PREV + 4); == FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff); compile_time_assert(FIL_NULL == 0xffffffff);
mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, &m_mtr); mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, &m_mtr);
mlog_write_ulint(PAGE_HEADER + PAGE_LEVEL + new_page, m_mtr.write<2,mtr_t::OPT>(*new_block,
m_level, MLOG_2BYTES, &m_mtr); PAGE_HEADER + PAGE_LEVEL
mlog_write_ull(PAGE_HEADER + PAGE_INDEX_ID + new_page, + new_page, m_level);
m_index->id, &m_mtr); m_mtr.write<8>(*new_block, index_id, m_index->id);
} }
} else { } else {
new_block = btr_block_get(*m_index, m_page_no, RW_X_LATCH, new_block = btr_block_get(*m_index, m_page_no, RW_X_LATCH,
@ -130,7 +130,7 @@ PageBulk::init()
ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW); ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW);
btr_page_set_level(new_page, new_page_zip, m_level, &m_mtr); btr_page_set_level(new_block, m_level, &m_mtr);
} }
if (!m_level && dict_index_is_sec_or_ibuf(m_index)) { if (!m_level && dict_index_is_sec_or_ibuf(m_index)) {
@ -169,13 +169,14 @@ PageBulk::init()
} }
/** Insert a record in the page. /** Insert a record in the page.
@tparam fmt the page format
@param[in] rec record @param[in] rec record
@param[in] offsets record offsets */ @param[in] offsets record offsets */
void template<PageBulk::format fmt>
PageBulk::insert( inline void PageBulk::insertPage(const rec_t *rec, ulint *offsets)
const rec_t* rec,
ulint* offsets)
{ {
ut_ad((m_page_zip != nullptr) == (fmt == COMPRESSED));
ut_ad((fmt != REDUNDANT) == m_is_comp);
ulint rec_size; ulint rec_size;
ut_ad(m_heap != NULL); ut_ad(m_heap != NULL);
@ -210,7 +211,7 @@ PageBulk::insert(
/* 3. Set the n_owned field in the inserted record to zero, /* 3. Set the n_owned field in the inserted record to zero,
and set the heap_no field. */ and set the heap_no field. */
if (m_is_comp) { if (fmt != REDUNDANT) {
rec_set_n_owned_new(insert_rec, NULL, 0); rec_set_n_owned_new(insert_rec, NULL, 0);
rec_set_heap_no_new(insert_rec, rec_set_heap_no_new(insert_rec,
PAGE_HEAP_NO_USER_LOW + m_rec_no); PAGE_HEAP_NO_USER_LOW + m_rec_no);
@ -242,15 +243,30 @@ PageBulk::insert(
m_cur_rec = insert_rec; m_cur_rec = insert_rec;
} }
/** Insert a record in the page.
@param[in] rec record
@param[in] offsets record offsets */
inline void PageBulk::insert(const rec_t *rec, ulint *offsets)
{
if (UNIV_LIKELY_NULL(m_page_zip))
insertPage<COMPRESSED>(rec, offsets);
else if (m_is_comp)
insertPage<DYNAMIC>(rec, offsets);
else
insertPage<REDUNDANT>(rec, offsets);
}
/** Mark end of insertion to the page. Scan all records to set page dirs, /** Mark end of insertion to the page. Scan all records to set page dirs,
and set page header members. and set page header members.
Note: we refer to page_copy_rec_list_end_to_created_page. */ @tparam fmt the page format */
void template<PageBulk::format fmt>
PageBulk::finish() inline void PageBulk::finishPage()
{ {
ut_ad(m_rec_no > 0); ut_ad(m_rec_no > 0);
ut_ad((m_page_zip != nullptr) == (fmt == COMPRESSED));
ut_ad((fmt != REDUNDANT) == m_is_comp);
ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no) ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no)
<= page_get_free_space_of_empty(m_is_comp)); <= page_get_free_space_of_empty(fmt != REDUNDANT));
/* See page_copy_rec_list_end_to_created_page() */ /* See page_copy_rec_list_end_to_created_page() */
ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2)); ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2));
@ -304,26 +320,26 @@ PageBulk::finish()
ut_ad(!dict_index_is_spatial(m_index)); ut_ad(!dict_index_is_spatial(m_index));
ut_ad(!page_get_instant(m_page)); ut_ad(!page_get_instant(m_page));
ut_ad(!mach_read_from_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page));
if (!m_flush_observer && !m_page_zip) { if (fmt != COMPRESSED && !m_flush_observer) {
mlog_write_ulint(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page, m_mtr.write<2,mtr_t::OPT>(*m_block,
2 + slot_index, MLOG_2BYTES, &m_mtr); PAGE_HEADER + PAGE_N_DIR_SLOTS
mlog_write_ulint(PAGE_HEADER + PAGE_HEAP_TOP + m_page, + m_page, 2 + slot_index);
ulint(m_heap_top - m_page), m_mtr.write<2>(*m_block, PAGE_HEADER + PAGE_HEAP_TOP + m_page,
MLOG_2BYTES, &m_mtr); ulint(m_heap_top - m_page));
mlog_write_ulint(PAGE_HEADER + PAGE_N_HEAP + m_page, m_mtr.write<2>(*m_block,
(PAGE_HEAP_NO_USER_LOW + m_rec_no) PAGE_HEADER + PAGE_N_HEAP + m_page,
| ulint(m_is_comp) << 15, (PAGE_HEAP_NO_USER_LOW + m_rec_no)
MLOG_2BYTES, &m_mtr); | uint16_t{fmt != REDUNDANT} << 15);
mlog_write_ulint(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no, m_mtr.write<2>(*m_block,
MLOG_2BYTES, &m_mtr); PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
mlog_write_ulint(PAGE_HEADER + PAGE_LAST_INSERT + m_page, m_mtr.write<2>(*m_block,
ulint(m_cur_rec - m_page), PAGE_HEADER + PAGE_LAST_INSERT + m_page,
MLOG_2BYTES, &m_mtr); ulint(m_cur_rec - m_page));
mlog_write_ulint(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page, m_mtr.write<2>(*m_block,
PAGE_RIGHT, MLOG_2BYTES, &m_mtr); PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page,
mlog_write_ulint(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0, PAGE_RIGHT);
MLOG_2BYTES, &m_mtr);
} else { } else {
/* For ROW_FORMAT=COMPRESSED, redo log may be written /* For ROW_FORMAT=COMPRESSED, redo log may be written
in PageBulk::compress(). */ in PageBulk::compress(). */
@ -333,18 +349,29 @@ PageBulk::finish()
ulint(m_heap_top - m_page)); ulint(m_heap_top - m_page));
mach_write_to_2(PAGE_HEADER + PAGE_N_HEAP + m_page, mach_write_to_2(PAGE_HEADER + PAGE_N_HEAP + m_page,
(PAGE_HEAP_NO_USER_LOW + m_rec_no) (PAGE_HEAP_NO_USER_LOW + m_rec_no)
| ulint(m_is_comp) << 15); | uint16_t{fmt != REDUNDANT} << 15);
mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no); mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
mach_write_to_2(PAGE_HEADER + PAGE_LAST_INSERT + m_page, mach_write_to_2(PAGE_HEADER + PAGE_LAST_INSERT + m_page,
ulint(m_cur_rec - m_page)); ulint(m_cur_rec - m_page));
mach_write_to_2(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page, mach_write_to_2(PAGE_HEADER + PAGE_DIRECTION_B - 1 + m_page,
PAGE_RIGHT); PAGE_RIGHT);
mach_write_to_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0);
} }
m_block->skip_flush_check = false; m_block->skip_flush_check = false;
} }
/** Mark end of insertion to the page. Scan all records to set page dirs,
and set page header members. */
inline void PageBulk::finish()
{
if (UNIV_LIKELY_NULL(m_page_zip))
finishPage<COMPRESSED>();
else if (m_is_comp)
finishPage<DYNAMIC>();
else
finishPage<REDUNDANT>();
}
/** Commit inserts done to the page /** Commit inserts done to the page
@param[in] success Flag whether all inserts succeed. */ @param[in] success Flag whether all inserts succeed. */
void void
@ -521,28 +548,24 @@ PageBulk::copyOut(
@param[in] next_page_no next page no */ @param[in] next_page_no next page no */
inline void PageBulk::setNext(ulint next_page_no) inline void PageBulk::setNext(ulint next_page_no)
{ {
if (UNIV_LIKELY_NULL(m_page_zip)) { if (UNIV_LIKELY_NULL(m_page_zip))
/* For ROW_FORMAT=COMPRESSED, redo log may be written /* For ROW_FORMAT=COMPRESSED, redo log may be written
in PageBulk::compress(). */ in PageBulk::compress(). */
mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no); mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no);
} else { else
mlog_write_ulint(m_page + FIL_PAGE_NEXT, next_page_no, m_mtr.write<4>(*m_block, m_page + FIL_PAGE_NEXT, next_page_no);
MLOG_4BYTES, &m_mtr);
}
} }
/** Set previous page /** Set previous page
@param[in] prev_page_no previous page no */ @param[in] prev_page_no previous page no */
inline void PageBulk::setPrev(ulint prev_page_no) inline void PageBulk::setPrev(ulint prev_page_no)
{ {
if (UNIV_LIKELY_NULL(m_page_zip)) { if (UNIV_LIKELY_NULL(m_page_zip))
/* For ROW_FORMAT=COMPRESSED, redo log may be written /* For ROW_FORMAT=COMPRESSED, redo log may be written
in PageBulk::compress(). */ in PageBulk::compress(). */
mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no); mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no);
} else { else
mlog_write_ulint(m_page + FIL_PAGE_PREV, prev_page_no, m_mtr.write<4>(*m_block, m_page + FIL_PAGE_PREV, prev_page_no);
MLOG_4BYTES, &m_mtr);
}
} }
/** Check if required space is available in the page for the rec to be inserted. /** Check if required space is available in the page for the rec to be inserted.
@ -748,9 +771,10 @@ BtrBulk::pageCommit(
page_bulk->setNext(next_page_bulk->getPageNo()); page_bulk->setNext(next_page_bulk->getPageNo());
next_page_bulk->setPrev(page_bulk->getPageNo()); next_page_bulk->setPrev(page_bulk->getPageNo());
} else { } else {
/** Suppose a page is released and latched again, we need to ut_ad(!page_has_next(page_bulk->getPage()));
/* If a page is released and latched again, we need to
mark it modified in mini-transaction. */ mark it modified in mini-transaction. */
page_bulk->setNext(FIL_NULL); page_bulk->set_modified();
} }
ut_ad(!rw_lock_own_flagged(&m_index->lock, ut_ad(!rw_lock_own_flagged(&m_index->lock,

View File

@ -154,8 +154,7 @@ static
void void
btr_cur_unmark_extern_fields( btr_cur_unmark_extern_fields(
/*=========================*/ /*=========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed buf_block_t* block, /*!< in/out: index page */
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */ rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */ dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@ -181,8 +180,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /*!< in: index of rec; the index tree MUST be dict_index_t* index, /*!< in: index of rec; the index tree MUST be
X-latched */ X-latched */
rec_t* rec, /*!< in: record */ rec_t* rec, /*!< in: record */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed buf_block_t* block, /*!< in: index page of rec */
part will be updated, or NULL */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const upd_t* update, /*!< in: update vector */ const upd_t* update, /*!< in: update vector */
bool rollback,/*!< in: performing rollback? */ bool rollback,/*!< in: performing rollback? */
@ -198,8 +196,7 @@ btr_rec_free_externally_stored_fields(
tree MUST be X-latched */ tree MUST be X-latched */
rec_t* rec, /*!< in: record */ rec_t* rec, /*!< in: record */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed buf_block_t* block, /*!< in: index page of rec */
part will be updated, or NULL */
bool rollback,/*!< in: performing rollback? */ bool rollback,/*!< in: performing rollback? */
mtr_t* mtr); /*!< in: mini-transaction handle which contains mtr_t* mtr); /*!< in: mini-transaction handle which contains
an X-latch to record page and to the index an X-latch to record page and to the index
@ -224,7 +221,6 @@ btr_cur_latch_leaves(
uint32_t left_page_no; uint32_t left_page_no;
uint32_t right_page_no; uint32_t right_page_no;
buf_block_t* get_block; buf_block_t* get_block;
page_t* page = buf_block_get_frame(block);
bool spatial; bool spatial;
btr_latch_leaves_t latch_leaves = {{NULL, NULL, NULL}, {0, 0, 0}}; btr_latch_leaves_t latch_leaves = {{NULL, NULL, NULL}, {0, 0, 0}};
@ -252,7 +248,8 @@ btr_cur_latch_leaves(
true, mtr); true, mtr);
latch_leaves.blocks[1] = get_block; latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); ut_a(page_is_comp(get_block->frame)
== page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (spatial) { if (spatial) {
cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS] cursor->rtr_info->tree_blocks[RTR_MAX_LEVELS]
@ -268,7 +265,7 @@ btr_cur_latch_leaves(
dict_index_get_lock(cursor->index), dict_index_get_lock(cursor->index),
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK)); MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
/* x-latch also siblings from left to right */ /* x-latch also siblings from left to right */
left_page_no = btr_page_get_prev(page); left_page_no = btr_page_get_prev(block->frame);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
@ -304,11 +301,12 @@ btr_cur_latch_leaves(
/* Sanity check only after both the blocks are latched. */ /* Sanity check only after both the blocks are latched. */
if (latch_leaves.blocks[0] != NULL) { if (latch_leaves.blocks[0] != NULL) {
ut_a(page_is_comp(latch_leaves.blocks[0]->frame) ut_a(page_is_comp(latch_leaves.blocks[0]->frame)
== page_is_comp(page)); == page_is_comp(block->frame));
ut_a(btr_page_get_next(latch_leaves.blocks[0]->frame) ut_a(btr_page_get_next(latch_leaves.blocks[0]->frame)
== page_get_page_no(page)); == block->page.id.page_no());
} }
ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); ut_a(page_is_comp(get_block->frame)
== page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (spatial) { if (spatial) {
@ -316,7 +314,7 @@ btr_cur_latch_leaves(
= get_block; = get_block;
} }
right_page_no = btr_page_get_next(page); right_page_no = btr_page_get_next(block->frame);
if (right_page_no != FIL_NULL) { if (right_page_no != FIL_NULL) {
if (spatial) { if (spatial) {
@ -331,9 +329,9 @@ btr_cur_latch_leaves(
latch_leaves.blocks[2] = get_block; latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->frame)
== page_is_comp(page)); == page_is_comp(block->frame));
ut_a(btr_page_get_prev(get_block->frame) ut_a(btr_page_get_prev(get_block->frame)
== page_get_page_no(page)); == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (spatial) { if (spatial) {
cursor->rtr_info->tree_blocks[ cursor->rtr_info->tree_blocks[
@ -348,7 +346,7 @@ btr_cur_latch_leaves(
mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH; mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
/* latch also left sibling */ /* latch also left sibling */
rw_lock_s_lock(&block->lock); rw_lock_s_lock(&block->lock);
left_page_no = btr_page_get_prev(page); left_page_no = btr_page_get_prev(block->frame);
rw_lock_s_unlock(&block->lock); rw_lock_s_unlock(&block->lock);
if (left_page_no != FIL_NULL) { if (left_page_no != FIL_NULL) {
@ -360,9 +358,9 @@ btr_cur_latch_leaves(
cursor->left_block = get_block; cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) ut_a(page_is_comp(get_block->frame)
== page_is_comp(page)); == page_is_comp(block->frame));
ut_a(btr_page_get_next(get_block->frame) ut_a(btr_page_get_next(get_block->frame)
== page_get_page_no(page)); == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
} }
@ -372,7 +370,8 @@ btr_cur_latch_leaves(
true, mtr); true, mtr);
latch_leaves.blocks[1] = get_block; latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); ut_a(page_is_comp(get_block->frame)
== page_is_comp(block->frame));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
return(latch_leaves); return(latch_leaves);
case BTR_CONT_MODIFY_TREE: case BTR_CONT_MODIFY_TREE:
@ -2424,8 +2423,7 @@ btr_cur_search_to_nth_level_func(
cursor->up_bytes = up_bytes; cursor->up_bytes = up_bytes;
if (autoinc) { if (autoinc) {
page_set_autoinc(tree_blocks[0], page_set_autoinc(tree_blocks[0], autoinc, mtr, false);
index, autoinc, mtr, false);
} }
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
@ -4160,8 +4158,6 @@ btr_cur_update_in_place(
further pages */ further pages */
{ {
dict_index_t* index; dict_index_t* index;
buf_block_t* block;
page_zip_des_t* page_zip;
dberr_t err; dberr_t err;
rec_t* rec; rec_t* rec;
roll_ptr_t roll_ptr = 0; roll_ptr_t roll_ptr = 0;
@ -4190,11 +4186,11 @@ btr_cur_update_in_place(
<< ") by " << ib::hex(trx_id) << ": " << ") by " << ib::hex(trx_id) << ": "
<< rec_printer(rec, offsets).str()); << rec_printer(rec, offsets).str());
block = btr_cur_get_block(cursor); buf_block_t* block = btr_cur_get_block(cursor);
page_zip = buf_block_get_page_zip(block); page_zip_des_t* page_zip = buf_block_get_page_zip(block);
/* Check that enough space is available on the compressed page. */ /* Check that enough space is available on the compressed page. */
if (page_zip) { if (UNIV_LIKELY_NULL(page_zip)) {
ut_ad(!index->table->is_temporary()); ut_ad(!index->table->is_temporary());
if (!btr_cur_update_alloc_zip( if (!btr_cur_update_alloc_zip(
@ -4277,8 +4273,7 @@ btr_cur_update_in_place(
/* The new updated record owns its possible externally /* The new updated record owns its possible externally
stored fields */ stored fields */
btr_cur_unmark_extern_fields(page_zip, btr_cur_unmark_extern_fields(block, rec, index, offsets, mtr);
rec, index, offsets, mtr);
} }
ut_ad(err == DB_SUCCESS); ut_ad(err == DB_SUCCESS);
@ -4803,7 +4798,6 @@ btr_cur_pessimistic_update(
big_rec_t* dummy_big_rec; big_rec_t* dummy_big_rec;
dict_index_t* index; dict_index_t* index;
buf_block_t* block; buf_block_t* block;
page_t* page;
page_zip_des_t* page_zip; page_zip_des_t* page_zip;
rec_t* rec; rec_t* rec;
page_cur_t* page_cursor; page_cur_t* page_cursor;
@ -4813,13 +4807,11 @@ btr_cur_pessimistic_update(
ibool was_first; ibool was_first;
ulint n_reserved = 0; ulint n_reserved = 0;
ulint n_ext; ulint n_ext;
ulint max_ins_size = 0;
*offsets = NULL; *offsets = NULL;
*big_rec = NULL; *big_rec = NULL;
block = btr_cur_get_block(cursor); block = btr_cur_get_block(cursor);
page = buf_block_get_frame(block);
page_zip = buf_block_get_page_zip(block); page_zip = buf_block_get_page_zip(block);
index = cursor->index; index = cursor->index;
@ -4828,7 +4820,7 @@ btr_cur_pessimistic_update(
MTR_MEMO_SX_LOCK)); MTR_MEMO_SX_LOCK));
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
ut_ad(!page_zip || !index->table->is_temporary()); ut_ad(!page_zip || !index->table->is_temporary());
/* The insert buffer tree should never be updated in place. */ /* The insert buffer tree should never be updated in place. */
@ -4861,7 +4853,7 @@ btr_cur_pessimistic_update(
if (page_zip if (page_zip
&& optim_err != DB_ZIP_OVERFLOW && optim_err != DB_ZIP_OVERFLOW
&& !dict_index_is_clust(index) && !dict_index_is_clust(index)
&& page_is_leaf(page)) { && page_is_leaf(block->frame)) {
ut_ad(!index->table->is_temporary()); ut_ad(!index->table->is_temporary());
ibuf_update_free_bits_zip(block, mtr); ibuf_update_free_bits_zip(block, mtr);
} }
@ -4910,7 +4902,7 @@ btr_cur_pessimistic_update(
/* We have to set appropriate extern storage bits in the new /* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */ record to be inserted: we have to remember which fields were such */
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); ut_ad(!page_is_comp(block->frame) || !rec_get_node_ptr_flag(rec));
ut_ad(rec_offs_validate(rec, index, *offsets)); ut_ad(rec_offs_validate(rec, index, *offsets));
if (index->is_primary()) { if (index->is_primary()) {
n_ext += btr_push_update_extern_fields( n_ext += btr_push_update_extern_fields(
@ -4933,12 +4925,12 @@ btr_cur_pessimistic_update(
DEBUG_SYNC_C("blob_rollback_middle"); DEBUG_SYNC_C("blob_rollback_middle");
btr_rec_free_updated_extern_fields( btr_rec_free_updated_extern_fields(
index, rec, page_zip, *offsets, update, true, mtr); index, rec, block, *offsets, update, true, mtr);
} }
if (page_zip_rec_needs_ext( if (page_zip_rec_needs_ext(
rec_get_converted_size(index, new_entry, n_ext), rec_get_converted_size(index, new_entry, n_ext),
page_is_comp(page), page_is_comp(block->frame),
dict_index_get_n_fields(index), dict_index_get_n_fields(index),
block->zip_size()) block->zip_size())
|| (UNIV_UNLIKELY(update->is_alter_metadata()) || (UNIV_UNLIKELY(update->is_alter_metadata())
@ -4954,14 +4946,15 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip ut_a(!page_zip
|| page_zip_validate(page_zip, page, index)); || page_zip_validate(page_zip, block->frame,
index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
index->table->space->release_free_extents(n_reserved); index->table->space->release_free_extents(n_reserved);
err = DB_TOO_BIG_RECORD; err = DB_TOO_BIG_RECORD;
goto err_exit; goto err_exit;
} }
ut_ad(page_is_leaf(page)); ut_ad(page_is_leaf(block->frame));
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG); ut_ad(flags & BTR_KEEP_POS_FLAG);
} }
@ -4996,10 +4989,9 @@ btr_cur_pessimistic_update(
btr_cur_write_sys(new_entry, index, trx_id, roll_ptr); btr_cur_write_sys(new_entry, index, trx_id, roll_ptr);
} }
if (!page_zip) { const ulint max_ins_size = page_zip
max_ins_size = page_get_max_insert_size_after_reorganize( ? 0 : page_get_max_insert_size_after_reorganize(block->frame,
page, 1); 1);
}
if (UNIV_UNLIKELY(is_metadata)) { if (UNIV_UNLIKELY(is_metadata)) {
ut_ad(new_entry->is_metadata()); ut_ad(new_entry->is_metadata());
@ -5027,7 +5019,7 @@ btr_cur_pessimistic_update(
} }
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
page_cursor = btr_cur_get_page_cur(cursor); page_cursor = btr_cur_get_page_cur(cursor);
@ -5058,8 +5050,8 @@ btr_cur_pessimistic_update(
|| rec_is_alter_metadata(rec, *index)) { || rec_is_alter_metadata(rec, *index)) {
/* The new inserted record owns its possible externally /* The new inserted record owns its possible externally
stored fields */ stored fields */
btr_cur_unmark_extern_fields( btr_cur_unmark_extern_fields(btr_cur_get_block(cursor),
page_zip, rec, index, *offsets, mtr); rec, index, *offsets, mtr);
} else { } else {
/* In delete-marked records, DB_TRX_ID must /* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */ always refer to an existing undo log record. */
@ -5067,7 +5059,7 @@ btr_cur_pessimistic_update(
} }
bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG); bool adjust = big_rec_vec && (flags & BTR_KEEP_POS_FLAG);
ut_ad(!adjust || page_is_leaf(page)); ut_ad(!adjust || page_is_leaf(block->frame));
if (btr_cur_compress_if_useful(cursor, adjust, mtr)) { if (btr_cur_compress_if_useful(cursor, adjust, mtr)) {
if (adjust) { if (adjust) {
@ -5075,7 +5067,7 @@ btr_cur_pessimistic_update(
true, *offsets); true, *offsets);
} }
} else if (!dict_index_is_clust(index) } else if (!dict_index_is_clust(index)
&& page_is_leaf(page)) { && page_is_leaf(block->frame)) {
/* Update the free bits in the insert buffer. /* Update the free bits in the insert buffer.
This is the same block which was skipped by This is the same block which was skipped by
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
@ -5090,7 +5082,7 @@ btr_cur_pessimistic_update(
if (!srv_read_only_mode if (!srv_read_only_mode
&& !big_rec_vec && !big_rec_vec
&& page_is_leaf(page) && page_is_leaf(block->frame)
&& !dict_index_is_online_ddl(index)) { && !dict_index_is_online_ddl(index)) {
mtr_memo_release(mtr, dict_index_get_lock(index), mtr_memo_release(mtr, dict_index_get_lock(index),
@ -5115,13 +5107,13 @@ btr_cur_pessimistic_update(
BTR_KEEP_IBUF_BITMAP. */ BTR_KEEP_IBUF_BITMAP. */
if (!dict_index_is_clust(index) if (!dict_index_is_clust(index)
&& !index->table->is_temporary() && !index->table->is_temporary()
&& page_is_leaf(page)) { && page_is_leaf(block->frame)) {
ibuf_reset_free_bits(block); ibuf_reset_free_bits(block);
} }
} }
if (big_rec_vec != NULL) { if (big_rec_vec != NULL) {
ut_ad(page_is_leaf(page)); ut_ad(page_is_leaf(block->frame));
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(flags & BTR_KEEP_POS_FLAG); ut_ad(flags & BTR_KEEP_POS_FLAG);
@ -5170,28 +5162,20 @@ btr_cur_pessimistic_update(
/* Update PAGE_MAX_TRX_ID in the index page header. /* Update PAGE_MAX_TRX_ID in the index page header.
It was not updated by btr_cur_pessimistic_insert() It was not updated by btr_cur_pessimistic_insert()
because of BTR_NO_LOCKING_FLAG. */ because of BTR_NO_LOCKING_FLAG. */
buf_block_t* rec_block; page_update_max_trx_id(btr_cur_get_block(cursor),
btr_cur_get_page_zip(cursor),
rec_block = btr_cur_get_block(cursor);
page_update_max_trx_id(rec_block,
buf_block_get_page_zip(rec_block),
trx_id, mtr); trx_id, mtr);
} }
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) { if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* The new inserted record owns its possible externally /* The new inserted record owns its possible externally
stored fields */ stored fields */
buf_block_t* rec_block = btr_cur_get_block(cursor);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, block->frame,
page = buf_block_get_frame(rec_block); index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
page_zip = buf_block_get_page_zip(rec_block); btr_cur_unmark_extern_fields(btr_cur_get_block(cursor), rec,
index, *offsets, mtr);
btr_cur_unmark_extern_fields(page_zip,
rec, index, *offsets, mtr);
} else { } else {
/* In delete-marked records, DB_TRX_ID must /* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */ always refer to an existing undo log record. */
@ -5222,7 +5206,8 @@ btr_cur_pessimistic_update(
return_after_reservations: return_after_reservations:
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(btr_cur_get_page_zip(cursor),
btr_cur_get_page(cursor), index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
index->table->space->release_free_extents(n_reserved); index->table->space->release_free_extents(n_reserved);
@ -5393,7 +5378,6 @@ btr_cur_del_mark_set_clust_rec(
{ {
roll_ptr_t roll_ptr; roll_ptr_t roll_ptr;
dberr_t err; dberr_t err;
page_zip_des_t* page_zip;
trx_t* trx; trx_t* trx;
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
@ -5431,7 +5415,7 @@ btr_cur_del_mark_set_clust_rec(
the adaptive hash index does not depend on the delete-mark the adaptive hash index does not depend on the delete-mark
and the delete-mark is being updated in place. */ and the delete-mark is being updated in place. */
page_zip = buf_block_get_page_zip(block); page_zip_des_t* page_zip = buf_block_get_page_zip(block);
btr_rec_set_deleted_flag(rec, page_zip, TRUE); btr_rec_set_deleted_flag(rec, page_zip, TRUE);
@ -5905,7 +5889,7 @@ btr_cur_pessimistic_delete(
if (rec_offs_any_extern(offsets)) { if (rec_offs_any_extern(offsets)) {
btr_rec_free_externally_stored_fields(index, btr_rec_free_externally_stored_fields(index,
rec, offsets, page_zip, rec, offsets, block,
rollback, mtr); rollback, mtr);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, page, index));
@ -7144,13 +7128,12 @@ static
void void
btr_cur_set_ownership_of_extern_field( btr_cur_set_ownership_of_extern_field(
/*==================================*/ /*==================================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed buf_block_t* block, /*!< in/out: index page */
part will be updated, or NULL */
rec_t* rec, /*!< in/out: clustered index record */ rec_t* rec, /*!< in/out: clustered index record */
dict_index_t* index, /*!< in: index of the page */ dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
ulint i, /*!< in: field number */ ulint i, /*!< in: field number */
ibool val, /*!< in: value to set */ bool val, /*!< in: value to set */
mtr_t* mtr) /*!< in: mtr, or NULL if not logged */ mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
{ {
byte* data; byte* data;
@ -7174,15 +7157,14 @@ btr_cur_set_ownership_of_extern_field(
byte_val |= BTR_EXTERN_OWNER_FLAG; byte_val |= BTR_EXTERN_OWNER_FLAG;
} }
if (page_zip) { if (UNIV_LIKELY_NULL(block->page.zip.data)) {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val); mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr); page_zip_write_blob_ptr(&block->page.zip, rec, index, offsets,
} else if (mtr != NULL) { i, mtr);
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
MLOG_1BYTE, mtr);
} else { } else {
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val); mtr->write<1,mtr_t::OPT>(*block,
data + local_len + BTR_EXTERN_LEN,
byte_val);
} }
} }
@ -7194,8 +7176,7 @@ to free the field. */
void void
btr_cur_disown_inherited_fields( btr_cur_disown_inherited_fields(
/*============================*/ /*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed buf_block_t* block, /*!< in/out: index page */
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */ rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */ dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@ -7212,7 +7193,7 @@ btr_cur_disown_inherited_fields(
if (rec_offs_nth_extern(offsets, i) if (rec_offs_nth_extern(offsets, i)
&& !upd_get_field_by_field_no(update, i, false)) { && !upd_get_field_by_field_no(update, i, false)) {
btr_cur_set_ownership_of_extern_field( btr_cur_set_ownership_of_extern_field(
page_zip, rec, index, offsets, i, FALSE, mtr); block, rec, index, offsets, i, false, mtr);
} }
} }
} }
@ -7225,29 +7206,23 @@ static
void void
btr_cur_unmark_extern_fields( btr_cur_unmark_extern_fields(
/*=========================*/ /*=========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed buf_block_t* block, /*!< in/out: index page */
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */ rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */ dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
mtr_t* mtr) /*!< in: mtr, or NULL if not logged */ mtr_t* mtr) /*!< in: mtr, or NULL if not logged */
{ {
ulint n;
ulint i;
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec)); ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
n = rec_offs_n_fields(offsets);
if (!rec_offs_any_extern(offsets)) { if (!rec_offs_any_extern(offsets)) {
return; return;
} }
for (i = 0; i < n; i++) { const ulint n = rec_offs_n_fields(offsets);
if (rec_offs_nth_extern(offsets, i)) {
for (ulint i = 0; i < n; i++) {
if (rec_offs_nth_extern(offsets, i)) {
btr_cur_set_ownership_of_extern_field( btr_cur_set_ownership_of_extern_field(
page_zip, rec, index, offsets, i, TRUE, mtr); block, rec, index, offsets, i, true, mtr);
} }
} }
} }
@ -7648,7 +7623,6 @@ btr_store_big_rec_extern_fields(
for (ulint blob_npages = 0;; ++blob_npages) { for (ulint blob_npages = 0;; ++blob_npages) {
buf_block_t* block; buf_block_t* block;
page_t* page;
const ulint commit_freq = 4; const ulint commit_freq = 4;
ulint r_extents; ulint r_extents;
@ -7711,11 +7685,9 @@ btr_store_big_rec_extern_fields(
ut_a(block != NULL); ut_a(block != NULL);
page_no = block->page.id.page_no(); page_no = block->page.id.page_no();
page = buf_block_get_frame(block);
if (prev_page_no != FIL_NULL) { if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block; buf_block_t* prev_block;
page_t* prev_page;
prev_block = buf_page_get( prev_block = buf_page_get(
page_id_t(space_id, prev_page_no), page_id_t(space_id, prev_page_no),
@ -7724,23 +7696,25 @@ btr_store_big_rec_extern_fields(
buf_block_dbg_add_level(prev_block, buf_block_dbg_add_level(prev_block,
SYNC_EXTERN_STORAGE); SYNC_EXTERN_STORAGE);
prev_page = buf_block_get_frame(prev_block);
if (page_zip) { if (page_zip) {
mlog_write_ulint( mtr.write<4>(*prev_block,
prev_page + FIL_PAGE_NEXT, prev_block->frame
page_no, MLOG_4BYTES, &mtr); + FIL_PAGE_NEXT,
memcpy(buf_block_get_page_zip( page_no);
prev_block) memcpy_aligned<4>(
->data + FIL_PAGE_NEXT, buf_block_get_page_zip(
prev_page + FIL_PAGE_NEXT, 4); prev_block)
->data + FIL_PAGE_NEXT,
prev_block->frame
+ FIL_PAGE_NEXT, 4);
} else { } else {
mlog_write_ulint( mtr.write<4>(*prev_block,
prev_page + FIL_PAGE_DATA BTR_BLOB_HDR_NEXT_PAGE_NO
+ BTR_BLOB_HDR_NEXT_PAGE_NO, + FIL_PAGE_DATA
page_no, MLOG_4BYTES, &mtr); + prev_block->frame,
page_no);
} }
} else if (dict_index_is_online_ddl(index)) { } else if (dict_index_is_online_ddl(index)) {
row_log_table_blob_alloc(index, page_no); row_log_table_blob_alloc(index, page_no);
} }
@ -7751,7 +7725,7 @@ btr_store_big_rec_extern_fields(
/* Write FIL_PAGE_TYPE to the redo log /* Write FIL_PAGE_TYPE to the redo log
separately, before logging any other separately, before logging any other
changes to the page, so that the debug changes to the block, so that the debug
assertions in assertions in
recv_parse_or_apply_log_rec_body() can recv_parse_or_apply_log_rec_body() can
be made simpler. Before InnoDB Plugin be made simpler. Before InnoDB Plugin
@ -7759,13 +7733,13 @@ btr_store_big_rec_extern_fields(
FIL_PAGE_TYPE was logged as part of FIL_PAGE_TYPE was logged as part of
the mlog_log_string() below. */ the mlog_log_string() below. */
mlog_write_ulint(page + FIL_PAGE_TYPE, mtr.write<2>(*block,
prev_page_no == FIL_NULL block->frame + FIL_PAGE_TYPE,
? FIL_PAGE_TYPE_ZBLOB prev_page_no == FIL_NULL
: FIL_PAGE_TYPE_ZBLOB2, ? FIL_PAGE_TYPE_ZBLOB
MLOG_2BYTES, &mtr); : FIL_PAGE_TYPE_ZBLOB2);
c_stream.next_out = page c_stream.next_out = block->frame
+ FIL_PAGE_DATA; + FIL_PAGE_DATA;
c_stream.avail_out = static_cast<uInt>( c_stream.avail_out = static_cast<uInt>(
payload_size_zip); payload_size_zip);
@ -7799,15 +7773,13 @@ btr_store_big_rec_extern_fields(
Number */ Number */
ut_ad(!dict_index_is_spatial(index)); ut_ad(!dict_index_is_spatial(index));
mlog_write_ulint(page mtr.write<4>(*block, block->frame
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
space_id, space_id);
MLOG_4BYTES, &mtr); mtr.write<4>(*block, block->frame
mlog_write_ulint(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, rec_page_no);
rec_page_no, mlog_log_string(block->frame
MLOG_4BYTES, &mtr);
mlog_log_string(page
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
page_zip_get_size(page_zip) page_zip_get_size(page_zip)
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
@ -7828,7 +7800,7 @@ btr_store_big_rec_extern_fields(
ut_ad(blob_page_zip); ut_ad(blob_page_zip);
ut_ad(page_zip_get_size(blob_page_zip) ut_ad(page_zip_get_size(blob_page_zip)
== page_zip_get_size(page_zip)); == page_zip_get_size(page_zip));
memcpy(blob_page_zip->data, page, memcpy(blob_page_zip->data, block->frame,
page_zip_get_size(page_zip)); page_zip_get_size(page_zip));
if (err == Z_OK && prev_page_no != FIL_NULL) { if (err == Z_OK && prev_page_no != FIL_NULL) {
@ -7880,9 +7852,9 @@ btr_store_big_rec_extern_fields(
break; break;
} }
} else { } else {
mlog_write_ulint(page + FIL_PAGE_TYPE, mtr.write<2>(*block, FIL_PAGE_TYPE
FIL_PAGE_TYPE_BLOB, + block->frame,
MLOG_2BYTES, &mtr); FIL_PAGE_TYPE_BLOB);
if (extern_len > payload_size) { if (extern_len > payload_size) {
store_len = payload_size; store_len = payload_size;
@ -7890,47 +7862,44 @@ btr_store_big_rec_extern_fields(
store_len = extern_len; store_len = extern_len;
} }
mlog_write_string(page + FIL_PAGE_DATA mlog_write_string(FIL_PAGE_DATA
+ BTR_BLOB_HDR_SIZE, + BTR_BLOB_HDR_SIZE
+ block->frame,
(const byte*) (const byte*)
big_rec_vec->fields[i].data big_rec_vec->fields[i].data
+ big_rec_vec->fields[i].len + big_rec_vec->fields[i].len
- extern_len, - extern_len,
store_len, &mtr); store_len, &mtr);
mlog_write_ulint(page + FIL_PAGE_DATA mtr.write<4>(*block, BTR_BLOB_HDR_PART_LEN
+ BTR_BLOB_HDR_PART_LEN, + FIL_PAGE_DATA + block->frame,
store_len, MLOG_4BYTES, &mtr); store_len);
mlog_write_ulint(page + FIL_PAGE_DATA compile_time_assert(FIL_NULL == 0xffffffff);
+ BTR_BLOB_HDR_NEXT_PAGE_NO, mlog_memset(block, BTR_BLOB_HDR_NEXT_PAGE_NO
FIL_NULL, MLOG_4BYTES, &mtr); + FIL_PAGE_DATA, 4, 0xff, &mtr);
extern_len -= store_len; extern_len -= store_len;
ut_ad(!mach_read_from_4(BTR_EXTERN_LEN ut_ad(!mach_read_from_4(BTR_EXTERN_LEN
+ field_ref)); + field_ref));
mlog_write_ulint(field_ref mtr.write<4>(*rec_block,
+ BTR_EXTERN_LEN + 4, BTR_EXTERN_LEN + 4 + field_ref,
big_rec_vec->fields[i].len big_rec_vec->fields[i].len
- extern_len, - extern_len);
MLOG_4BYTES, &mtr);
if (prev_page_no == FIL_NULL) { if (prev_page_no == FIL_NULL) {
ut_ad(blob_npages == 0); ut_ad(blob_npages == 0);
mlog_write_ulint(field_ref mtr.write<4,mtr_t::OPT>(
+ BTR_EXTERN_SPACE_ID, *rec_block,
space_id, MLOG_4BYTES, field_ref + BTR_EXTERN_SPACE_ID,
&mtr); space_id);
mlog_write_ulint(field_ref mtr.write<4>(*rec_block, field_ref
+ BTR_EXTERN_PAGE_NO, + BTR_EXTERN_PAGE_NO,
page_no, MLOG_4BYTES, page_no);
&mtr);
mlog_write_ulint(field_ref mtr.write<4>(*rec_block, field_ref
+ BTR_EXTERN_OFFSET, + BTR_EXTERN_OFFSET,
FIL_PAGE_DATA, FIL_PAGE_DATA);
MLOG_4BYTES,
&mtr);
} }
prev_page_no = page_no; prev_page_no = page_no;
@ -8038,8 +8007,7 @@ btr_free_externally_stored_field(
page_zip_write_blob_ptr(), or NULL */ page_zip_write_blob_ptr(), or NULL */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index), const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
or NULL */ or NULL */
page_zip_des_t* page_zip, /*!< in: compressed page corresponding buf_block_t* block, /*!< in/out: page of field_ref */
to rec, or NULL if rec == NULL */
ulint i, /*!< in: field number of field_ref; ulint i, /*!< in: field number of field_ref;
ignored if rec == NULL */ ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */ bool rollback, /*!< in: performing rollback? */
@ -8084,10 +8052,8 @@ btr_free_externally_stored_field(
const ulint ext_zip_size = index->table->space->zip_size(); const ulint ext_zip_size = index->table->space->zip_size();
const ulint rec_zip_size = rec ? ext_zip_size : 0; const ulint rec_zip_size = rec ? ext_zip_size : 0;
if (rec == NULL) { /* !rec holds in a call from purge when field_ref is in an undo page */
/* This is a call from row_purge_upd_exist_or_extern(). */ ut_ad(rec || !block->page.zip.data);
ut_ad(!page_zip);
}
for (;;) { for (;;) {
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
@ -8156,24 +8122,23 @@ btr_free_externally_stored_field(
btr_page_free(index, ext_block, &mtr, true); btr_page_free(index, ext_block, &mtr, true);
if (page_zip != NULL) { if (UNIV_LIKELY_NULL(block->page.zip.data)) {
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO, mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
next_page_no); next_page_no);
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4, memset(field_ref + BTR_EXTERN_LEN, 0, 4);
0); page_zip_write_blob_ptr(&block->page.zip,
page_zip_write_blob_ptr(page_zip, rec, index, rec, index,
offsets, i, &mtr); offsets, i, &mtr);
} else { } else {
mlog_write_ulint(field_ref mtr.write<4>(*block,
+ BTR_EXTERN_PAGE_NO, BTR_EXTERN_PAGE_NO + field_ref,
next_page_no, next_page_no);
MLOG_4BYTES, &mtr); mtr.write<4>(*block,
mlog_write_ulint(field_ref BTR_EXTERN_LEN + 4 + field_ref,
+ BTR_EXTERN_LEN + 4, 0, 0U);
MLOG_4BYTES, &mtr);
} }
} else { } else {
ut_a(!page_zip); ut_ad(!block->page.zip.data);
btr_check_blob_fil_page_type(space_id, page_no, page, btr_check_blob_fil_page_type(space_id, page_no, page,
FALSE); FALSE);
@ -8182,17 +8147,16 @@ btr_free_externally_stored_field(
+ BTR_BLOB_HDR_NEXT_PAGE_NO); + BTR_BLOB_HDR_NEXT_PAGE_NO);
btr_page_free(index, ext_block, &mtr, true); btr_page_free(index, ext_block, &mtr, true);
mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO, mtr.write<4>(*block, BTR_EXTERN_PAGE_NO + field_ref,
next_page_no, next_page_no);
MLOG_4BYTES, &mtr);
/* Zero out the BLOB length. If the server /* Zero out the BLOB length. If the server
crashes during the execution of this function, crashes during the execution of this function,
trx_rollback_all_recovered() could trx_rollback_all_recovered() could
dereference the half-deleted BLOB, fetching a dereference the half-deleted BLOB, fetching a
wrong prefix for the BLOB. */ wrong prefix for the BLOB. */
mlog_write_ulint(field_ref + BTR_EXTERN_LEN + 4, mtr.write<4,mtr_t::OPT>(*block,
0, BTR_EXTERN_LEN + 4 + field_ref,
MLOG_4BYTES, &mtr); 0U);
} }
/* Commit mtr and release the BLOB block to save memory. */ /* Commit mtr and release the BLOB block to save memory. */
@ -8210,8 +8174,7 @@ btr_rec_free_externally_stored_fields(
tree MUST be X-latched */ tree MUST be X-latched */
rec_t* rec, /*!< in/out: record */ rec_t* rec, /*!< in/out: record */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed buf_block_t* block, /*!< in: index page of rec */
part will be updated, or NULL */
bool rollback,/*!< in: performing rollback? */ bool rollback,/*!< in: performing rollback? */
mtr_t* mtr) /*!< in: mini-transaction handle which contains mtr_t* mtr) /*!< in: mini-transaction handle which contains
an X-latch to record page and to the index an X-latch to record page and to the index
@ -8233,7 +8196,7 @@ btr_rec_free_externally_stored_fields(
if (rec_offs_nth_extern(offsets, i)) { if (rec_offs_nth_extern(offsets, i)) {
btr_free_externally_stored_field( btr_free_externally_stored_field(
index, btr_rec_get_field_ref(rec, offsets, i), index, btr_rec_get_field_ref(rec, offsets, i),
rec, offsets, page_zip, i, rollback, mtr); rec, offsets, block, i, rollback, mtr);
} }
} }
} }
@ -8248,8 +8211,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /*!< in: index of rec; the index tree MUST be dict_index_t* index, /*!< in: index of rec; the index tree MUST be
X-latched */ X-latched */
rec_t* rec, /*!< in/out: record */ rec_t* rec, /*!< in/out: record */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed buf_block_t* block, /*!< in: index page of rec */
part will be updated, or NULL */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const upd_t* update, /*!< in: update vector */ const upd_t* update, /*!< in: update vector */
bool rollback,/*!< in: performing rollback? */ bool rollback,/*!< in: performing rollback? */
@ -8277,7 +8239,7 @@ btr_rec_free_updated_extern_fields(
btr_free_externally_stored_field( btr_free_externally_stored_field(
index, data + len - BTR_EXTERN_FIELD_REF_SIZE, index, data + len - BTR_EXTERN_FIELD_REF_SIZE,
rec, offsets, page_zip, rec, offsets, block,
ufield->field_no, rollback, mtr); ufield->field_no, rollback, mtr);
} }
} }

View File

@ -71,25 +71,13 @@ buf_dblwr_page_inside(
return(FALSE); return(FALSE);
} }
/****************************************************************//** /** @return the TRX_SYS page */
Calls buf_page_get() on the TRX_SYS_PAGE and returns a pointer to the inline buf_block_t *buf_dblwr_trx_sys_get(mtr_t *mtr)
doublewrite buffer within it.
@return pointer to the doublewrite buffer within the filespace header
page. */
UNIV_INLINE
byte*
buf_dblwr_get(
/*==========*/
mtr_t* mtr) /*!< in/out: MTR to hold the page latch */
{ {
buf_block_t* block; buf_block_t *block= buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
0, RW_X_LATCH, mtr);
block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
0, RW_X_LATCH, mtr); return block;
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
return(buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE);
} }
/********************************************************************//** /********************************************************************//**
@ -106,12 +94,7 @@ buf_dblwr_sync_datafiles()
/****************************************************************//** /****************************************************************//**
Creates or initialializes the doublewrite buffer at a database start. */ Creates or initialializes the doublewrite buffer at a database start. */
static static void buf_dblwr_init(const byte *doublewrite)
void
buf_dblwr_init(
/*===========*/
byte* doublewrite) /*!< in: pointer to the doublewrite buf
header on trx sys page */
{ {
ulint buf_size; ulint buf_size;
@ -164,7 +147,6 @@ buf_dblwr_create()
{ {
buf_block_t* block2; buf_block_t* block2;
buf_block_t* new_block; buf_block_t* new_block;
byte* doublewrite;
byte* fseg_header; byte* fseg_header;
ulint page_no; ulint page_no;
ulint prev_page_no; ulint prev_page_no;
@ -180,14 +162,15 @@ buf_dblwr_create()
mtr.start(); mtr.start();
buf_dblwr_being_created = TRUE; buf_dblwr_being_created = TRUE;
doublewrite = buf_dblwr_get(&mtr); buf_block_t *trx_sys_block = buf_dblwr_trx_sys_get(&mtr);
if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC) if (mach_read_from_4(TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
+ trx_sys_block->frame)
== TRX_SYS_DOUBLEWRITE_MAGIC_N) { == TRX_SYS_DOUBLEWRITE_MAGIC_N) {
/* The doublewrite buffer has already been created: /* The doublewrite buffer has already been created:
just read in some numbers */ just read in some numbers */
buf_dblwr_init(doublewrite); buf_dblwr_init(TRX_SYS_DOUBLEWRITE + trx_sys_block->frame);
mtr.commit(); mtr.commit();
buf_dblwr_being_created = FALSE; buf_dblwr_being_created = FALSE;
@ -229,7 +212,8 @@ buf_dblwr_create()
buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK); buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
fseg_header = doublewrite + TRX_SYS_DOUBLEWRITE_FSEG; fseg_header = TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG
+ trx_sys_block->frame;
prev_page_no = 0; prev_page_no = 0;
for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE for (i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
@ -265,30 +249,38 @@ buf_dblwr_create()
recv_parse_or_apply_log_rec_body() will see a valid recv_parse_or_apply_log_rec_body() will see a valid
page type. The flushes of new_block are actually page type. The flushes of new_block are actually
unnecessary here. */ unnecessary here. */
ut_d(mlog_write_ulint(FIL_PAGE_TYPE + new_block->frame, ut_d(mtr.write<2>(*new_block,
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, &mtr)); FIL_PAGE_TYPE + new_block->frame,
FIL_PAGE_TYPE_SYS));
if (i == FSP_EXTENT_SIZE / 2) { if (i == FSP_EXTENT_SIZE / 2) {
ut_a(page_no == FSP_EXTENT_SIZE); ut_a(page_no == FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE_BLOCK1, TRX_SYS_DOUBLEWRITE
page_no, MLOG_4BYTES, &mtr); + TRX_SYS_DOUBLEWRITE_BLOCK1
mlog_write_ulint(doublewrite + trx_sys_block->frame,
+ TRX_SYS_DOUBLEWRITE_REPEAT page_no);
+ TRX_SYS_DOUBLEWRITE_BLOCK1, mtr.write<4>(*trx_sys_block,
page_no, MLOG_4BYTES, &mtr); TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_REPEAT
+ TRX_SYS_DOUBLEWRITE_BLOCK1
+ trx_sys_block->frame,
page_no);
} else if (i == FSP_EXTENT_SIZE / 2 } else if (i == FSP_EXTENT_SIZE / 2
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
ut_a(page_no == 2 * FSP_EXTENT_SIZE); ut_a(page_no == 2 * FSP_EXTENT_SIZE);
mlog_write_ulint(doublewrite mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE_BLOCK2, TRX_SYS_DOUBLEWRITE
page_no, MLOG_4BYTES, &mtr); + TRX_SYS_DOUBLEWRITE_BLOCK2
mlog_write_ulint(doublewrite + trx_sys_block->frame,
+ TRX_SYS_DOUBLEWRITE_REPEAT page_no);
+ TRX_SYS_DOUBLEWRITE_BLOCK2, mtr.write<4>(*trx_sys_block,
page_no, MLOG_4BYTES, &mtr); TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_REPEAT
+ TRX_SYS_DOUBLEWRITE_BLOCK2
+ trx_sys_block->frame,
page_no);
} else if (i > FSP_EXTENT_SIZE / 2) { } else if (i > FSP_EXTENT_SIZE / 2) {
ut_a(page_no == prev_page_no + 1); ut_a(page_no == prev_page_no + 1);
} }
@ -303,29 +295,32 @@ buf_dblwr_create()
lock the fseg header too many times. Since lock the fseg header too many times. Since
this code is not done while any other threads this code is not done while any other threads
are active, restart the MTR occasionally. */ are active, restart the MTR occasionally. */
mtr_commit(&mtr); mtr.commit();
mtr_start(&mtr); mtr.start();
doublewrite = buf_dblwr_get(&mtr); trx_sys_block = buf_dblwr_trx_sys_get(&mtr);
fseg_header = doublewrite fseg_header = TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_FSEG; + TRX_SYS_DOUBLEWRITE_FSEG
+ trx_sys_block->frame;
} }
prev_page_no = page_no; prev_page_no = page_no;
} }
mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE_MAGIC_N, TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
MLOG_4BYTES, &mtr); + trx_sys_block->frame,
mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC TRX_SYS_DOUBLEWRITE_MAGIC_N);
+ TRX_SYS_DOUBLEWRITE_REPEAT, mtr.write<4>(*trx_sys_block,
TRX_SYS_DOUBLEWRITE_MAGIC_N, TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_MAGIC
MLOG_4BYTES, &mtr); + TRX_SYS_DOUBLEWRITE_REPEAT
+ trx_sys_block->frame,
TRX_SYS_DOUBLEWRITE_MAGIC_N);
mlog_write_ulint(doublewrite mtr.write<4>(*trx_sys_block,
+ TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED, TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED
TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N, + trx_sys_block->frame,
MLOG_4BYTES, &mtr); TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N);
mtr_commit(&mtr); mtr.commit();
/* Flush the modified pages to disk and make a checkpoint */ /* Flush the modified pages to disk and make a checkpoint */
log_make_checkpoint(); log_make_checkpoint();

View File

@ -35,24 +35,13 @@ Created 4/18/1996 Heikki Tuuri
#include "log0recv.h" #include "log0recv.h"
#include "os0file.h" #include "os0file.h"
/**********************************************************************//** /** @return the DICT_HDR block, x-latched */
Gets a pointer to the dictionary header and x-latches its page. buf_block_t *dict_hdr_get(mtr_t* mtr)
@return pointer to the dictionary header, page x-latched */
dict_hdr_t*
dict_hdr_get(
/*=========*/
mtr_t* mtr) /*!< in: mtr */
{ {
buf_block_t* block; buf_block_t *block= buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),
dict_hdr_t* header; 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO), return block;
0, RW_X_LATCH, mtr);
header = DICT_HDR + buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
return(header);
} }
/**********************************************************************//** /**********************************************************************//**
@ -67,36 +56,41 @@ dict_hdr_get_new_id(
ulint* space_id) /*!< out: space id ulint* space_id) /*!< out: space id
(not assigned if NULL) */ (not assigned if NULL) */
{ {
dict_hdr_t* dict_hdr;
ib_id_t id; ib_id_t id;
mtr_t mtr; mtr_t mtr;
mtr_start(&mtr); mtr.start();
dict_hdr = dict_hdr_get(&mtr); buf_block_t* dict_hdr = dict_hdr_get(&mtr);
if (table_id) { if (table_id) {
id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID); id = mach_read_from_8(DICT_HDR + DICT_HDR_TABLE_ID
+ dict_hdr->frame);
id++; id++;
mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr); mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_TABLE_ID
+ dict_hdr->frame, id);
*table_id = id; *table_id = id;
} }
if (index_id) { if (index_id) {
id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID); id = mach_read_from_8(DICT_HDR + DICT_HDR_INDEX_ID
+ dict_hdr->frame);
id++; id++;
mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr); mtr.write<8>(*dict_hdr, DICT_HDR + DICT_HDR_INDEX_ID
+ dict_hdr->frame, id);
*index_id = id; *index_id = id;
} }
if (space_id) { if (space_id) {
*space_id = mach_read_from_4(dict_hdr + DICT_HDR_MAX_SPACE_ID); *space_id = mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ dict_hdr->frame);
if (fil_assign_new_space_id(space_id)) { if (fil_assign_new_space_id(space_id)) {
mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID, mtr.write<4>(*dict_hdr,
*space_id, MLOG_4BYTES, &mtr); DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ dict_hdr->frame, *space_id);
} }
} }
mtr_commit(&mtr); mtr.commit();
} }
/**********************************************************************//** /**********************************************************************//**
@ -106,7 +100,6 @@ void
dict_hdr_flush_row_id(void) dict_hdr_flush_row_id(void)
/*=======================*/ /*=======================*/
{ {
dict_hdr_t* dict_hdr;
row_id_t id; row_id_t id;
mtr_t mtr; mtr_t mtr;
@ -114,13 +107,13 @@ dict_hdr_flush_row_id(void)
id = dict_sys.row_id; id = dict_sys.row_id;
mtr_start(&mtr); mtr.start();
dict_hdr = dict_hdr_get(&mtr); buf_block_t* d = dict_hdr_get(&mtr);
mlog_write_ull(dict_hdr + DICT_HDR_ROW_ID, id, &mtr); mtr.write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame, id);
mtr_commit(&mtr); mtr.commit();
} }
/*****************************************************************//** /*****************************************************************//**
@ -134,7 +127,6 @@ dict_hdr_create(
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
buf_block_t* block; buf_block_t* block;
dict_hdr_t* dict_header;
ulint root_page_no; ulint root_page_no;
ut_ad(mtr); ut_ad(mtr);
@ -147,24 +139,22 @@ dict_hdr_create(
ut_a(DICT_HDR_PAGE_NO == block->page.id.page_no()); ut_a(DICT_HDR_PAGE_NO == block->page.id.page_no());
dict_header = dict_hdr_get(mtr); buf_block_t* d = dict_hdr_get(mtr);
/* Start counting row, table, index, and tree ids from /* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */ DICT_HDR_FIRST_ID */
mlog_write_ull(dict_header + DICT_HDR_ROW_ID, mtr->write<8>(*d, DICT_HDR + DICT_HDR_ROW_ID + d->frame,
DICT_HDR_FIRST_ID, mtr); DICT_HDR_FIRST_ID);
mtr->write<8>(*d, DICT_HDR + DICT_HDR_TABLE_ID + d->frame,
DICT_HDR_FIRST_ID);
mtr->write<8>(*d, DICT_HDR + DICT_HDR_INDEX_ID + d->frame,
DICT_HDR_FIRST_ID);
mlog_write_ull(dict_header + DICT_HDR_TABLE_ID, ut_ad(!mach_read_from_4(DICT_HDR + DICT_HDR_MAX_SPACE_ID + d->frame));
DICT_HDR_FIRST_ID, mtr);
mlog_write_ull(dict_header + DICT_HDR_INDEX_ID,
DICT_HDR_FIRST_ID, mtr);
ut_ad(mach_read_from_4(dict_header + DICT_HDR_MAX_SPACE_ID) == 0);
/* Obsolete, but we must initialize it anyway. */ /* Obsolete, but we must initialize it anyway. */
mlog_write_ulint(dict_header + DICT_HDR_MIX_ID_LOW, mtr->write<4>(*d, DICT_HDR + DICT_HDR_MIX_ID_LOW + d->frame,
DICT_HDR_FIRST_ID, MLOG_4BYTES, mtr); DICT_HDR_FIRST_ID);
/* Create the B-tree roots for the clustered indexes of the basic /* Create the B-tree roots for the clustered indexes of the basic
system tables */ system tables */
@ -178,8 +168,7 @@ dict_hdr_create(
return(FALSE); return(FALSE);
} }
mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no, mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLES + d->frame, root_page_no);
MLOG_4BYTES, mtr);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, root_page_no = btr_create(DICT_UNIQUE,
fil_system.sys_space, DICT_TABLE_IDS_ID, fil_system.sys_space, DICT_TABLE_IDS_ID,
@ -189,8 +178,8 @@ dict_hdr_create(
return(FALSE); return(FALSE);
} }
mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no, mtr->write<4>(*d, DICT_HDR + DICT_HDR_TABLE_IDS + d->frame,
MLOG_4BYTES, mtr); root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_COLUMNS_ID, fil_system.sys_space, DICT_COLUMNS_ID,
@ -200,8 +189,8 @@ dict_hdr_create(
return(FALSE); return(FALSE);
} }
mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no, mtr->write<4>(*d, DICT_HDR + DICT_HDR_COLUMNS + d->frame,
MLOG_4BYTES, mtr); root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_INDEXES_ID, fil_system.sys_space, DICT_INDEXES_ID,
@ -211,8 +200,8 @@ dict_hdr_create(
return(FALSE); return(FALSE);
} }
mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no, mtr->write<4>(*d, DICT_HDR + DICT_HDR_INDEXES + d->frame,
MLOG_4BYTES, mtr); root_page_no);
/*--------------------------*/ /*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_FIELDS_ID, fil_system.sys_space, DICT_FIELDS_ID,
@ -222,8 +211,7 @@ dict_hdr_create(
return(FALSE); return(FALSE);
} }
mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no, mtr->write<4>(*d, DICT_HDR + DICT_HDR_FIELDS + d->frame, root_page_no);
MLOG_4BYTES, mtr);
/*--------------------------*/ /*--------------------------*/
return(TRUE); return(TRUE);
@ -239,7 +227,6 @@ dict_boot(void)
{ {
dict_table_t* table; dict_table_t* table;
dict_index_t* index; dict_index_t* index;
dict_hdr_t* dict_hdr;
mem_heap_t* heap; mem_heap_t* heap;
mtr_t mtr; mtr_t mtr;
@ -271,7 +258,7 @@ dict_boot(void)
mutex_enter(&dict_sys.mutex); mutex_enter(&dict_sys.mutex);
/* Get the dictionary header */ /* Get the dictionary header */
dict_hdr = dict_hdr_get(&mtr); const byte* dict_hdr = &dict_hdr_get(&mtr)->frame[DICT_HDR];
/* Because we only write new row ids to disk-based data structure /* Because we only write new row ids to disk-based data structure
(dictionary header) when it is divisible by (dictionary header) when it is divisible by

View File

@ -373,16 +373,18 @@ dict_build_table_def_step(
mtr.start(); mtr.start();
undo->table_id = trx->table_id; undo->table_id = trx->table_id;
undo->dict_operation = TRUE; undo->dict_operation = TRUE;
page_t* page = trx_undo_page_get( buf_block_t* block = trx_undo_page_get(
page_id_t(trx->rsegs.m_redo.rseg->space->id, page_id_t(trx->rsegs.m_redo.rseg->space->id,
undo->hdr_page_no), undo->hdr_page_no),
&mtr); &mtr);
mlog_write_ulint(page + undo->hdr_offset mtr.write<1,mtr_t::OPT>(
+ TRX_UNDO_DICT_TRANS, *block,
TRUE, MLOG_1BYTE, &mtr); block->frame + undo->hdr_offset
mlog_write_ull(page + undo->hdr_offset + TRX_UNDO_DICT_TRANS, 1U);
+ TRX_UNDO_TABLE_ID, mtr.write<8,mtr_t::OPT>(
trx->table_id, &mtr); *block,
block->frame + undo->hdr_offset
+ TRX_UNDO_TABLE_ID, trx->table_id);
mtr.commit(); mtr.commit();
log_write_up_to(mtr.commit_lsn(), true); log_write_up_to(mtr.commit_lsn(), true);
} }
@ -851,14 +853,13 @@ dict_create_index_tree_step(
err = DB_OUT_OF_FILE_SPACE; ); err = DB_OUT_OF_FILE_SPACE; );
} }
ulint len; ulint len;
byte* data = rec_get_nth_field_old(btr_pcur_get_rec(&pcur), byte* data = rec_get_nth_field_old(btr_pcur_get_rec(&pcur),
DICT_FLD__SYS_INDEXES__PAGE_NO, DICT_FLD__SYS_INDEXES__PAGE_NO,
&len); &len);
ut_ad(len == 4); ut_ad(len == 4);
if (mach_read_from_4(data) != node->page_no) { mtr.write<4,mtr_t::OPT>(*btr_pcur_get_block(&pcur), data,
mlog_write_ulint(data, node->page_no, MLOG_4BYTES, &mtr); node->page_no);
}
mtr.commit(); mtr.commit();

View File

@ -4013,7 +4013,7 @@ dict_set_corrupted(
if (len != 4) { if (len != 4) {
goto fail; goto fail;
} }
mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr); mtr.write<4>(*btr_cur_get_block(&cursor), field, index->type);
status = "Flagged"; status = "Flagged";
} else { } else {
fail: fail:
@ -4113,11 +4113,8 @@ dict_index_set_merge_threshold(
DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD, &len); DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD, &len);
ut_ad(len == 4); ut_ad(len == 4);
mtr.write<4,mtr_t::OPT>(*btr_cur_get_block(&cursor), field,
if (len == 4) { merge_threshold);
mlog_write_ulint(field, merge_threshold,
MLOG_4BYTES, &mtr);
}
} }
mtr_commit(&mtr); mtr_commit(&mtr);

View File

@ -1481,7 +1481,8 @@ void dict_check_tablespaces_and_store_max_id()
/* Initialize the max space_id from sys header */ /* Initialize the max space_id from sys header */
mtr.start(); mtr.start();
ulint max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID ulint max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID
+ dict_hdr_get(&mtr)); + DICT_HDR
+ dict_hdr_get(&mtr)->frame);
mtr.commit(); mtr.commit();
fil_set_max_space_id_if_bigger(max_space_id); fil_set_max_space_id_if_bigger(max_space_id);

View File

@ -2035,8 +2035,9 @@ fil_crypt_rotate_page(
modified = true; modified = true;
/* force rotation by dummy updating page */ /* force rotation by dummy updating page */
mlog_write_ulint(frame + FIL_PAGE_SPACE_ID, mtr.write<1,mtr_t::FORCED>(*block,
space_id, MLOG_4BYTES, &mtr); &frame[FIL_PAGE_SPACE_ID],
frame[FIL_PAGE_SPACE_ID]);
/* statistics */ /* statistics */
state->crypt_stat.pages_modified++; state->crypt_stat.pages_modified++;

View File

@ -3899,8 +3899,8 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
<< " to " << ib::hex(flags); << " to " << ib::hex(flags);
} }
mtr.set_named_space(space); mtr.set_named_space(space);
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS mtr.write<4>(*b, FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ b->frame, flags, MLOG_4BYTES, &mtr); + b->frame, flags);
} }
func_exit: func_exit:
mtr.commit(); mtr.commit();

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -628,12 +628,8 @@ rtr_adjust_upper_level(
rtr_mbr_t* new_mbr, /*!< in: MBR on the new page */ rtr_mbr_t* new_mbr, /*!< in: MBR on the new page */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
page_t* page;
page_t* new_page;
ulint page_no; ulint page_no;
ulint new_page_no; ulint new_page_no;
page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip;
dict_index_t* index = sea_cur->index; dict_index_t* index = sea_cur->index;
btr_cur_t cursor; btr_cur_t cursor;
ulint* offsets; ulint* offsets;
@ -657,13 +653,9 @@ rtr_adjust_upper_level(
level = btr_page_get_level(buf_block_get_frame(block)); level = btr_page_get_level(buf_block_get_frame(block));
ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block))); ut_ad(level == btr_page_get_level(buf_block_get_frame(new_block)));
page = buf_block_get_frame(block);
page_no = block->page.id.page_no(); page_no = block->page.id.page_no();
page_zip = buf_block_get_page_zip(block);
new_page = buf_block_get_frame(new_block);
new_page_no = new_block->page.id.page_no(); new_page_no = new_block->page.id.page_no();
new_page_zip = buf_block_get_page_zip(new_block);
/* Set new mbr for the old page on the upper level. */ /* Set new mbr for the old page on the upper level. */
/* Look up the index for the node pointer to page */ /* Look up the index for the node pointer to page */
@ -672,7 +664,8 @@ rtr_adjust_upper_level(
page_cursor = btr_cur_get_page_cur(&cursor); page_cursor = btr_cur_get_page_cur(&cursor);
rtr_update_mbr_field(&cursor, offsets, NULL, page, mbr, NULL, mtr); rtr_update_mbr_field(&cursor, offsets, NULL, block->frame, mbr, NULL,
mtr);
/* Already updated parent MBR, reset in our path */ /* Already updated parent MBR, reset in our path */
if (sea_cur->rtr_info) { if (sea_cur->rtr_info) {
@ -686,7 +679,7 @@ rtr_adjust_upper_level(
/* Insert the node for the new page. */ /* Insert the node for the new page. */
node_ptr_upper = rtr_index_build_node_ptr( node_ptr_upper = rtr_index_build_node_ptr(
index, new_mbr, index, new_mbr,
page_rec_get_next(page_get_infimum_rec(new_page)), page_rec_get_next(page_get_infimum_rec(new_block->frame)),
new_page_no, heap); new_page_no, heap);
ulint up_match = 0; ulint up_match = 0;
@ -742,26 +735,25 @@ rtr_adjust_upper_level(
ut_ad(block->zip_size() == index->table->space->zip_size()); ut_ad(block->zip_size() == index->table->space->zip_size());
const uint32_t next_page_no = btr_page_get_next(page); const uint32_t next_page_no = btr_page_get_next(block->frame);
if (next_page_no != FIL_NULL) { if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get( buf_block_t* next_block = btr_block_get(
*index, next_page_no, RW_X_LATCH, false, mtr); *index, next_page_no, RW_X_LATCH, false, mtr);
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page)); ut_a(page_is_comp(next_block->frame)
== page_is_comp(block->frame));
ut_a(btr_page_get_prev(next_block->frame) ut_a(btr_page_get_prev(next_block->frame)
== block->page.id.page_no()); == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
btr_page_set_prev(buf_block_get_frame(next_block), btr_page_set_prev(next_block, new_page_no, mtr);
buf_block_get_page_zip(next_block),
new_page_no, mtr);
} }
btr_page_set_next(page, page_zip, new_page_no, mtr); btr_page_set_next(block, new_page_no, mtr);
btr_page_set_prev(new_page, new_page_zip, page_no, mtr); btr_page_set_prev(new_block, page_no, mtr);
btr_page_set_next(new_page, new_page_zip, next_page_no, mtr); btr_page_set_next(new_block, next_page_no, mtr);
} }
/*************************************************************//** /*************************************************************//**
@ -848,11 +840,8 @@ rtr_split_page_move_rec_list(
ut_ad(!is_leaf || cur_split_node->key != first_rec); ut_ad(!is_leaf || cur_split_node->key != first_rec);
rec = page_cur_insert_rec_low( rec = page_cur_insert_rec_low(
page_cur_get_rec(&new_page_cursor), page_cur_get_rec(&new_page_cursor),
index, index, cur_split_node->key, offsets, mtr);
cur_split_node->key,
offsets,
mtr);
ut_a(rec); ut_a(rec);

View File

@ -17856,14 +17856,10 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save)
space->zip_size(), RW_X_LATCH, &mtr); space->zip_size(), RW_X_LATCH, &mtr);
if (block != NULL) { if (block != NULL) {
byte* page = block->frame; ib::info() << "Dirtying page: " << block->page.id;
mtr.write<1,mtr_t::FORCED>(*block,
ib::info() << "Dirtying page: " << page_id_t( block->frame + FIL_PAGE_SPACE_ID,
page_get_space_id(page), page_get_page_no(page)); block->frame[FIL_PAGE_SPACE_ID]);
mlog_write_ulint(page + FIL_PAGE_TYPE,
fil_page_get_type(page),
MLOG_2BYTES, &mtr);
} }
mtr.commit(); mtr.commit();
goto func_exit; goto func_exit;

View File

@ -10198,12 +10198,12 @@ commit_cache_norebuild(
space->zip_size(), space->zip_size(),
RW_X_LATCH, &mtr)) { RW_X_LATCH, &mtr)) {
mtr.set_named_space(space); mtr.set_named_space(space);
mlog_write_ulint( mtr.write<4,mtr_t::OPT>(
*b,
FSP_HEADER_OFFSET FSP_HEADER_OFFSET
+ FSP_SPACE_FLAGS + b->frame, + FSP_SPACE_FLAGS + b->frame,
space->flags space->flags
& ~FSP_FLAGS_MEM_MASK, & ~FSP_FLAGS_MEM_MASK);
MLOG_4BYTES, &mtr);
} }
mtr.commit(); mtr.commit();
} }

View File

@ -332,17 +332,12 @@ ibuf_header_page_get(
return page; return page;
} }
/******************************************************************//** /** Acquire the change buffer root page.
Gets the root page and sx-latches it. @param[in,out] mtr mini-transaction
@return insert buffer tree root page */ @return change buffer root page, SX-latched */
static static buf_block_t *ibuf_tree_root_get(mtr_t *mtr)
page_t*
ibuf_tree_root_get(
/*===============*/
mtr_t* mtr) /*!< in: mtr */
{ {
buf_block_t* block; buf_block_t* block;
page_t* root;
ut_ad(ibuf_inside(mtr)); ut_ad(ibuf_inside(mtr));
ut_ad(mutex_own(&ibuf_mutex)); ut_ad(mutex_own(&ibuf_mutex));
@ -356,13 +351,11 @@ ibuf_tree_root_get(
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
root = buf_block_get_frame(block); ut_ad(page_get_space_id(block->frame) == IBUF_SPACE_ID);
ut_ad(page_get_page_no(block->frame) == FSP_IBUF_TREE_ROOT_PAGE_NO);
ut_ad(ibuf.empty == page_is_empty(block->frame));
ut_ad(page_get_space_id(root) == IBUF_SPACE_ID); return block;
ut_ad(page_get_page_no(root) == FSP_IBUF_TREE_ROOT_PAGE_NO);
ut_ad(ibuf.empty == page_is_empty(root));
return(root);
} }
/******************************************************************//** /******************************************************************//**
@ -624,29 +617,27 @@ ibuf_bitmap_page_get_bits_low(
} }
/** Sets the desired bit for a given page in a bitmap page. /** Sets the desired bit for a given page in a bitmap page.
@param[in,out] page bitmap page @tparam bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in,out] block bitmap page
@param[in] page_id page id whose bits to set @param[in] page_id page id whose bits to set
@param[in] physical_size page size @param[in] physical_size page size
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in] val value to set @param[in] val value to set
@param[in,out] mtr mtr containing an x-latch to the bitmap page */ @param[in,out] mtr mtr containing an x-latch to the bitmap page */
static template<ulint bit>
void static void
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits(
page_t* page, buf_block_t* block,
const page_id_t page_id, const page_id_t page_id,
ulint physical_size, ulint physical_size,
ulint bit,
ulint val, ulint val,
mtr_t* mtr) mtr_t* mtr)
{ {
ulint byte_offset; ulint byte_offset;
ulint bit_offset; ulint bit_offset;
ulint map_byte;
ut_ad(bit < IBUF_BITS_PER_PAGE); static_assert(bit < IBUF_BITS_PER_PAGE, "wrong bit");
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr->is_named_space(page_id.space())); ut_ad(mtr->is_named_space(page_id.space()));
bit_offset = (page_id.page_no() % physical_size) bit_offset = (page_id.page_no() % physical_size)
@ -657,21 +648,22 @@ ibuf_bitmap_page_set_bits(
ut_ad(byte_offset + IBUF_BITMAP < srv_page_size); ut_ad(byte_offset + IBUF_BITMAP < srv_page_size);
map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset); byte* map_byte = &block->frame[IBUF_BITMAP + byte_offset];
byte b = *map_byte;
if (bit == IBUF_BITMAP_FREE) { if (bit == IBUF_BITMAP_FREE) {
ut_ad(bit_offset + 1 < 8); ut_ad(bit_offset + 1 < 8);
ut_ad(val <= 3); ut_ad(val <= 3);
b &= ~(3U << bit_offset);
map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2); b |= (val & 2) << (bit_offset - 1)
map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2); | (val & 1) << (bit_offset + 1);
} else { } else {
ut_ad(val <= 1); ut_ad(val <= 1);
map_byte = ut_bit_set_nth(map_byte, bit_offset, val); b &= ~(1U << bit_offset);
b |= val << bit_offset;
} }
mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte, mtr->write<1,mtr_t::OPT>(*block, map_byte, b);
MLOG_1BYTE, mtr);
} }
/** Calculates the bitmap page number for a given page number. /** Calculates the bitmap page number for a given page number.
@ -697,7 +689,7 @@ stored.
page containing the descriptor bits for the file page; the bitmap page page containing the descriptor bits for the file page; the bitmap page
is x-latched */ is x-latched */
static static
page_t* buf_block_t*
ibuf_bitmap_get_map_page_func( ibuf_bitmap_get_map_page_func(
const page_id_t page_id, const page_id_t page_id,
ulint zip_size, ulint zip_size,
@ -718,8 +710,7 @@ ibuf_bitmap_get_map_page_func(
buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP); buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP);
return block;
return(buf_block_get_frame(block));
} }
/** Gets the ibuf bitmap page where the bits describing a given file page are /** Gets the ibuf bitmap page where the bits describing a given file page are
@ -749,31 +740,19 @@ ibuf_set_free_bits_low(
ulint val, /*!< in: value to set: < 4 */ ulint val, /*!< in: value to set: < 4 */
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
{ {
page_t* bitmap_page;
buf_frame_t* frame;
ut_ad(mtr->is_named_space(block->page.id.space())); ut_ad(mtr->is_named_space(block->page.id.space()));
if (!page_is_leaf(block->frame)) {
if (!block) {
return; return;
} }
frame = buf_block_get_frame(block);
if (!frame || !page_is_leaf(frame)) {
return;
}
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
block->zip_size(), mtr);
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
ut_a(val <= ibuf_index_page_calc_free(block)); ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */ #endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(), ibuf_bitmap_get_map_page(block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, val, mtr); mtr),
block->page.id, block->physical_size(), val, mtr);
} }
/************************************************************************//** /************************************************************************//**
@ -793,34 +772,21 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */ #endif /* UNIV_IBUF_DEBUG */
ulint val) /*!< in: value to set: < 4 */ ulint val) /*!< in: value to set: < 4 */
{ {
mtr_t mtr; if (!page_is_leaf(block->frame)) {
page_t* page;
page_t* bitmap_page;
page = buf_block_get_frame(block);
if (!page_is_leaf(page)) {
return; return;
} }
mtr_start(&mtr); mtr_t mtr;
mtr.start();
const fil_space_t* space = mtr.set_named_space_id( const fil_space_t* space = mtr.set_named_space_id(
block->page.id.space()); block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id, buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
block->zip_size(), &mtr); block->zip_size(),
&mtr);
switch (space->purpose) { if (space->purpose != FIL_TYPE_TABLESPACE) {
case FIL_TYPE_LOG: mtr.set_log_mode(MTR_LOG_NO_REDO);
ut_ad(0);
break;
case FIL_TYPE_TABLESPACE:
break;
/* fall through */
case FIL_TYPE_TEMPORARY:
case FIL_TYPE_IMPORT:
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
} }
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
@ -830,31 +796,17 @@ ibuf_set_free_bits_func(
old_val = ibuf_bitmap_page_get_bits( old_val = ibuf_bitmap_page_get_bits(
bitmap_page, block->page.id, bitmap_page, block->page.id,
IBUF_BITMAP_FREE, &mtr); IBUF_BITMAP_FREE, &mtr);
# if 0
if (old_val != max_val) {
fprintf(stderr,
"Ibuf: page %lu old val %lu max val %lu\n",
page_get_page_no(page),
old_val, max_val);
}
# endif
ut_a(old_val <= max_val); ut_a(old_val <= max_val);
} }
# if 0
fprintf(stderr, "Setting page no %lu free bits to %lu should be %lu\n",
page_get_page_no(page), val,
ibuf_index_page_calc_free(block));
# endif
ut_a(val <= ibuf_index_page_calc_free(block)); ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */ #endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(), bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, val, &mtr); val, &mtr);
mtr_commit(&mtr); mtr.commit();
} }
/************************************************************************//** /************************************************************************//**
@ -929,19 +881,10 @@ ibuf_update_free_bits_zip(
buf_block_t* block, /*!< in/out: index page */ buf_block_t* block, /*!< in/out: index page */
mtr_t* mtr) /*!< in/out: mtr */ mtr_t* mtr) /*!< in/out: mtr */
{ {
page_t* bitmap_page; ut_ad(page_is_leaf(block->frame));
ulint after; ut_ad(block->zip_size());
ut_a(block); ulint after = ibuf_index_page_calc_free_zip(block);
buf_frame_t* frame = buf_block_get_frame(block);
ut_a(frame);
ut_a(page_is_leaf(frame));
ut_a(block->zip_size());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
block->zip_size(), mtr);
after = ibuf_index_page_calc_free_zip(block);
if (after == 0) { if (after == 0) {
/* We move the page to the front of the buffer pool LRU list: /* We move the page to the front of the buffer pool LRU list:
@ -952,9 +895,10 @@ ibuf_update_free_bits_zip(
buf_page_make_young(&block->page); buf_page_make_young(&block->page);
} }
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(), ibuf_bitmap_get_map_page(block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, after, mtr); mtr),
block->page.id, block->physical_size(), after, mtr);
} }
/**********************************************************************//** /**********************************************************************//**
@ -1029,7 +973,6 @@ ibuf_page_low(
{ {
ibool ret; ibool ret;
mtr_t local_mtr; mtr_t local_mtr;
page_t* bitmap_page;
ut_ad(!recv_no_ibuf_operations); ut_ad(!recv_no_ibuf_operations);
ut_ad(x_latch || mtr == NULL); ut_ad(x_latch || mtr == NULL);
@ -1064,10 +1007,8 @@ ibuf_page_low(
zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH, zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
file, line, &local_mtr, &err); file, line, &local_mtr, &err);
bitmap_page = buf_block_get_frame(block);
ret = ibuf_bitmap_page_get_bits_low( ret = ibuf_bitmap_page_get_bits_low(
bitmap_page, page_id, zip_size, block->frame, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF); MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
mtr_commit(&local_mtr); mtr_commit(&local_mtr);
@ -1080,10 +1021,10 @@ ibuf_page_low(
mtr_start(mtr); mtr_start(mtr);
} }
bitmap_page = ibuf_bitmap_get_map_page_func(page_id, zip_size, ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page_func(
file, line, mtr); page_id, zip_size, file, line,
mtr)->frame,
ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, zip_size, page_id, zip_size,
IBUF_BITMAP_IBUF, mtr); IBUF_BITMAP_IBUF, mtr);
if (mtr == &local_mtr) { if (mtr == &local_mtr) {
@ -1891,23 +1832,16 @@ ibuf_data_too_much_free(void)
return(ibuf.free_list_len >= 3 + (ibuf.size / 2) + 3 * ibuf.height); return(ibuf.free_list_len >= 3 + (ibuf.size / 2) + 3 * ibuf.height);
} }
/*********************************************************************//** /** Allocate a change buffer page.
Allocates a new page from the ibuf file segment and adds it to the free @retval true on success
list. @retval false if no space left */
@return TRUE on success, FALSE if no space left */ static bool ibuf_add_free_page()
static
ibool
ibuf_add_free_page(void)
/*====================*/
{ {
mtr_t mtr; mtr_t mtr;
page_t* header_page; page_t* header_page;
buf_block_t* block; buf_block_t* block;
page_t* page;
page_t* root;
page_t* bitmap_page;
mtr_start(&mtr); mtr.start();
/* Acquire the fsp latch before the ibuf header, obeying the latching /* Acquire the fsp latch before the ibuf header, obeying the latching
order */ order */
mtr_x_lock_space(fil_system.sys_space, &mtr); mtr_x_lock_space(fil_system.sys_space, &mtr);
@ -1928,26 +1862,24 @@ ibuf_add_free_page(void)
&mtr); &mtr);
if (block == NULL) { if (block == NULL) {
mtr_commit(&mtr); mtr.commit();
return false;
return(FALSE);
} }
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
ibuf_enter(&mtr); ibuf_enter(&mtr);
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
root = ibuf_tree_root_get(&mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
page = buf_block_get_frame(block);
mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST, mtr.write<2>(*block, block->frame + FIL_PAGE_TYPE,
MLOG_2BYTES, &mtr); FIL_PAGE_IBUF_FREE_LIST);
/* Add the page to the free list and update the ibuf size data */ /* Add the page to the free list and update the ibuf size data */
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, flst_add_last(ibuf_tree_root_get(&mtr),
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
ibuf.seg_size++; ibuf.seg_size++;
ibuf.free_list_len++; ibuf.free_list_len++;
@ -1955,17 +1887,18 @@ ibuf_add_free_page(void)
/* Set the bit indicating that this page is now an ibuf tree page /* Set the bit indicating that this page is now an ibuf tree page
(level 2 page) */ (level 2 page) */
const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no()); const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no());
bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits(bitmap_page, page_id, srv_page_size, ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(bitmap_page, page_id,
IBUF_BITMAP_IBUF, TRUE, &mtr); srv_page_size, true,
&mtr);
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
return(TRUE); return true;
} }
/*********************************************************************//** /*********************************************************************//**
@ -1979,9 +1912,6 @@ ibuf_remove_free_page(void)
mtr_t mtr2; mtr_t mtr2;
page_t* header_page; page_t* header_page;
ulint page_no; ulint page_no;
page_t* page;
page_t* root;
page_t* bitmap_page;
log_free_check(); log_free_check();
@ -2009,12 +1939,12 @@ ibuf_remove_free_page(void)
ibuf_mtr_start(&mtr2); ibuf_mtr_start(&mtr2);
root = ibuf_tree_root_get(&mtr2); buf_block_t* root = ibuf_tree_root_get(&mtr2);
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
+ root).page; + root->frame).page;
/* NOTE that we must release the latch on the ibuf tree root /* NOTE that we must release the latch on the ibuf tree root
because in fseg_free_page we access level 1 pages, and the root because in fseg_free_page we access level 1 pages, and the root
@ -2044,22 +1974,15 @@ ibuf_remove_free_page(void)
root = ibuf_tree_root_get(&mtr); root = ibuf_tree_root_get(&mtr);
ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
+ root).page); + root->frame).page);
{ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
buf_block_t* block; buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
/* Remove the page from the free list and update the ibuf size data */ /* Remove the page from the free list and update the ibuf size data */
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr); block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
mutex_exit(&ibuf_pessimistic_insert_mutex); mutex_exit(&ibuf_pessimistic_insert_mutex);
@ -2069,13 +1992,12 @@ ibuf_remove_free_page(void)
/* Set the bit indicating that this page is no more an ibuf tree page /* Set the bit indicating that this page is no more an ibuf tree page
(level 2 page) */ (level 2 page) */
bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(
bitmap_page, page_id, srv_page_size, bitmap_page, page_id, srv_page_size, false, &mtr);
IBUF_BITMAP_IBUF, FALSE, &mtr);
ut_d(buf_page_set_file_page_was_freed(page_id)); ut_d(buf_page_set_file_page_was_freed(page_id));
@ -3305,8 +3227,7 @@ ibuf_insert_low(
ulint buffered; ulint buffered;
lint min_n_recs; lint min_n_recs;
rec_t* ins_rec; rec_t* ins_rec;
ibool old_bit_value; buf_block_t* bitmap_page;
page_t* bitmap_page;
buf_block_t* block; buf_block_t* block;
page_t* root; page_t* root;
dberr_t err; dberr_t err;
@ -3459,8 +3380,8 @@ ibuf_insert_low(
if (op == IBUF_OP_INSERT) { if (op == IBUF_OP_INSERT) {
ulint bits = ibuf_bitmap_page_get_bits( ulint bits = ibuf_bitmap_page_get_bits(
bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE, bitmap_page->frame, page_id, physical_size,
&bitmap_mtr); IBUF_BITMAP_FREE, &bitmap_mtr);
if (buffered + entry_size + page_dir_calc_reserved_space(1) if (buffered + entry_size + page_dir_calc_reserved_space(1)
> ibuf_index_page_calc_free_from_bits(physical_size, > ibuf_index_page_calc_free_from_bits(physical_size,
@ -3505,17 +3426,8 @@ ibuf_insert_low(
/* Set the bitmap bit denoting that the insert buffer contains /* Set the bitmap bit denoting that the insert buffer contains
buffered entries for this index page, if the bit is not set yet */ buffered entries for this index page, if the bit is not set yet */
ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
old_bit_value = ibuf_bitmap_page_get_bits( bitmap_page, page_id, physical_size, true, &bitmap_mtr);
bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, &bitmap_mtr);
if (!old_bit_value) {
ibuf_bitmap_page_set_bits(bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, TRUE,
&bitmap_mtr);
}
ibuf_mtr_commit(&bitmap_mtr); ibuf_mtr_commit(&bitmap_mtr);
cursor = btr_pcur_get_btr_cur(&pcur); cursor = btr_pcur_get_btr_cur(&pcur);
@ -3548,7 +3460,7 @@ ibuf_insert_low(
which would cause the sx-latching of the root after that to which would cause the sx-latching of the root after that to
break the latching order. */ break the latching order. */
root = ibuf_tree_root_get(&mtr); root = ibuf_tree_root_get(&mtr)->frame;
err = btr_cur_optimistic_insert( err = btr_cur_optimistic_insert(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
@ -3760,9 +3672,6 @@ ibuf_insert_to_index_page_low(
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */ after which to insert the buffered entry */
{ {
const page_t* page;
const page_t* bitmap_page;
ulint old_bits;
rec_t* rec; rec_t* rec;
DBUG_ENTER("ibuf_insert_to_index_page_low"); DBUG_ENTER("ibuf_insert_to_index_page_low");
@ -3790,11 +3699,10 @@ ibuf_insert_to_index_page_low(
DBUG_RETURN(rec); DBUG_RETURN(rec);
} }
page = buf_block_get_frame(block);
ib::error() << "Insert buffer insert fails; page free " ib::error() << "Insert buffer insert fails; page free "
<< page_get_max_insert_size(page, 1) << ", dtuple size " << page_get_max_insert_size(block->frame, 1)
<< rec_get_converted_size(index, entry, 0); << ", dtuple size "
<< rec_get_converted_size(index, entry, 0);
fputs("InnoDB: Cannot insert index record ", stderr); fputs("InnoDB: Cannot insert index record ", stderr);
dtuple_print(stderr, entry); dtuple_print(stderr, entry);
@ -3802,14 +3710,14 @@ ibuf_insert_to_index_page_low(
"InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
"InnoDB: that table.\n", stderr); "InnoDB: that table.\n", stderr);
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
block->zip_size(), mtr);
old_bits = ibuf_bitmap_page_get_bits(
bitmap_page, block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, mtr);
ib::error() << "page " << block->page.id << ", size " ib::error() << "page " << block->page.id << ", size "
<< block->physical_size() << ", bitmap bits " << old_bits; << block->physical_size() << ", bitmap bits "
<< ibuf_bitmap_page_get_bits(
ibuf_bitmap_get_map_page(block->page.id,
block->zip_size(),
mtr)->frame,
block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, mtr);
ib::error() << BUG_REPORT_MSG; ib::error() << BUG_REPORT_MSG;
@ -3898,7 +3806,6 @@ ibuf_insert_to_index_page(
if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) { if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
upd_t* update; upd_t* update;
page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur); rec = page_cur_get_rec(&page_cur);
@ -3910,8 +3817,7 @@ ibuf_insert_to_index_page(
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
update = row_upd_build_sec_rec_difference_binary( update = row_upd_build_sec_rec_difference_binary(
rec, index, offsets, entry, heap); rec, index, offsets, entry, heap);
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
page_zip = buf_block_get_page_zip(block);
if (update->n_fields == 0) { if (update->n_fields == 0) {
/* The records only differ in the delete-mark. /* The records only differ in the delete-mark.
@ -4023,7 +3929,7 @@ ibuf_set_del_mark(
if (low_match == dtuple_get_n_fields(entry)) { if (low_match == dtuple_get_n_fields(entry)) {
rec_t* rec; rec_t* rec;
page_zip_des_t* page_zip; page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur); rec = page_cur_get_rec(&page_cur);
page_zip = page_cur_get_page_zip(&page_cur); page_zip = page_cur_get_page_zip(&page_cur);
@ -4272,7 +4178,7 @@ bool ibuf_delete_rec(ulint space, ulint page_no, btr_pcur_t* pcur,
goto func_exit; goto func_exit;
} }
root = ibuf_tree_root_get(mtr); root = ibuf_tree_root_get(mtr)->frame;
btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 0, btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur), 0,
false, mtr); false, mtr);
@ -4317,10 +4223,10 @@ bool ibuf_page_exists(const buf_page_t& bpage)
bool bitmap_bits = false; bool bitmap_bits = false;
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
if (const page_t* bitmap_page = ibuf_bitmap_get_map_page( if (const buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
bpage.id, bpage.zip_size(), &mtr)) { bpage.id, bpage.zip_size(), &mtr)) {
bitmap_bits = ibuf_bitmap_page_get_bits( bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page, bpage.id, bpage.zip_size(), bitmap_page->frame, bpage.id, bpage.zip_size(),
IBUF_BITMAP_BUFFERED, &mtr) != 0; IBUF_BITMAP_BUFFERED, &mtr) != 0;
} }
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
@ -4351,7 +4257,6 @@ ibuf_merge_or_delete_for_page(
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
ulint volume = 0; ulint volume = 0;
#endif /* UNIV_IBUF_DEBUG */ #endif /* UNIV_IBUF_DEBUG */
page_zip_des_t* page_zip = NULL;
bool corruption_noticed = false; bool corruption_noticed = false;
mtr_t mtr; mtr_t mtr;
@ -4385,18 +4290,18 @@ ibuf_merge_or_delete_for_page(
block = NULL; block = NULL;
update_ibuf_bitmap = false; update_ibuf_bitmap = false;
} else { } else {
page_t* bitmap_page = NULL;
ulint bitmap_bits = 0; ulint bitmap_bits = 0;
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
bitmap_page = ibuf_bitmap_get_map_page( buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr); page_id, zip_size, &mtr);
if (bitmap_page && if (bitmap_page
fil_page_get_type(bitmap_page) != FIL_PAGE_TYPE_ALLOCATED) { && fil_page_get_type(bitmap_page->frame)
!= FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits( bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page, page_id, zip_size, bitmap_page->frame, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr); IBUF_BITMAP_BUFFERED, &mtr);
} }
@ -4429,7 +4334,6 @@ ibuf_merge_or_delete_for_page(
the debug checks. */ the debug checks. */
rw_lock_x_lock_move_ownership(&(block->lock)); rw_lock_x_lock_move_ownership(&(block->lock));
page_zip = buf_block_get_page_zip(block);
if (!fil_page_index_page_check(block->frame) if (!fil_page_index_page_check(block->frame)
|| !page_is_leaf(block->frame)) { || !page_is_leaf(block->frame)) {
@ -4496,8 +4400,7 @@ ibuf_merge_or_delete_for_page(
|| ibuf_rec_get_space(&mtr, rec) != page_id.space()) { || ibuf_rec_get_space(&mtr, rec) != page_id.space()) {
if (block != NULL) { if (block != NULL) {
page_header_reset_last_insert( page_header_reset_last_insert(block, &mtr);
block->frame, page_zip, &mtr);
} }
goto reset_bit; goto reset_bit;
@ -4519,8 +4422,9 @@ ibuf_merge_or_delete_for_page(
ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec); ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
max_trx_id = page_get_max_trx_id(page_align(rec)); max_trx_id = page_get_max_trx_id(page_align(rec));
page_update_max_trx_id(block, page_zip, max_trx_id, page_update_max_trx_id(block,
&mtr); buf_block_get_page_zip(block),
max_trx_id, &mtr);
ut_ad(page_validate(page_align(rec), ibuf.index)); ut_ad(page_validate(page_align(rec), ibuf.index));
@ -4635,28 +4539,17 @@ ibuf_merge_or_delete_for_page(
} }
reset_bit: reset_bit:
if (update_ibuf_bitmap) { if (!update_ibuf_bitmap) {
page_t* bitmap_page; } else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr)) {
bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, /* FIXME: update the bitmap byte only once! */
&mtr); ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap, page_id, physical_size, false, &mtr);
ibuf_bitmap_page_set_bits(
bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
if (block != NULL) { if (block != NULL) {
ulint old_bits = ibuf_bitmap_page_get_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, page_id, zip_size, bitmap, page_id, physical_size,
IBUF_BITMAP_FREE, &mtr); ibuf_index_page_calc_free(block), &mtr);
ulint new_bits = ibuf_index_page_calc_free(block);
if (old_bits != new_bits) {
ibuf_bitmap_page_set_bits(
bitmap_page, page_id, physical_size,
IBUF_BITMAP_FREE, new_bits, &mtr);
}
} }
} }
@ -4760,18 +4653,15 @@ bool
ibuf_is_empty(void) ibuf_is_empty(void)
/*===============*/ /*===============*/
{ {
bool is_empty;
const page_t* root;
mtr_t mtr; mtr_t mtr;
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
mutex_enter(&ibuf_mutex); ut_d(mutex_enter(&ibuf_mutex));
root = ibuf_tree_root_get(&mtr); const buf_block_t* root = ibuf_tree_root_get(&mtr);
mutex_exit(&ibuf_mutex); bool is_empty = page_is_empty(root->frame);
is_empty = page_is_empty(root);
ut_a(is_empty == ibuf.empty); ut_a(is_empty == ibuf.empty);
ut_d(mutex_exit(&ibuf_mutex));
ibuf_mtr_commit(&mtr); ibuf_mtr_commit(&mtr);
return(is_empty); return(is_empty);
@ -4849,9 +4739,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
the space, as usual. */ the space, as usual. */
for (page_no = 0; page_no < size; page_no += physical_size) { for (page_no = 0; page_no < size; page_no += physical_size) {
page_t* bitmap_page;
ulint i;
if (trx_is_interrupted(trx)) { if (trx_is_interrupted(trx)) {
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
return(DB_INTERRUPTED); return(DB_INTERRUPTED);
@ -4863,10 +4750,15 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ibuf_enter(&mtr); ibuf_enter(&mtr);
bitmap_page = ibuf_bitmap_get_map_page( buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id_t(space->id, page_no), zip_size, &mtr); page_id_t(space->id, page_no), zip_size, &mtr);
if (!bitmap_page) {
mutex_exit(&ibuf_mutex);
mtr.commit();
return DB_CORRUPTION;
}
if (buf_page_is_zeroes(bitmap_page, physical_size)) { if (buf_page_is_zeroes(bitmap_page->frame, physical_size)) {
/* This means we got all-zero page instead of /* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be ibuf bitmap page. The subsequent page should be
all-zero pages. */ all-zero pages. */
@ -4886,17 +4778,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
continue; continue;
} }
if (!bitmap_page) { for (ulint i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size;
mutex_exit(&ibuf_mutex); i++) {
return DB_CORRUPTION;
}
for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size; i++) {
const ulint offset = page_no + i; const ulint offset = page_no + i;
const page_id_t cur_page_id(space->id, offset); const page_id_t cur_page_id(space->id, offset);
if (ibuf_bitmap_page_get_bits( if (ibuf_bitmap_page_get_bits(
bitmap_page, cur_page_id, zip_size, bitmap_page->frame, cur_page_id, zip_size,
IBUF_BITMAP_IBUF, &mtr)) { IBUF_BITMAP_IBUF, &mtr)) {
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
@ -4914,7 +4802,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
} }
if (ibuf_bitmap_page_get_bits( if (ibuf_bitmap_page_get_bits(
bitmap_page, cur_page_id, zip_size, bitmap_page->frame, cur_page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr)) { IBUF_BITMAP_BUFFERED, &mtr)) {
ib_errf(trx->mysql_thd, ib_errf(trx->mysql_thd,
@ -4928,10 +4816,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
/* Tolerate this error, so that /* Tolerate this error, so that
slightly corrupted tables can be slightly corrupted tables can be
imported and dumped. Clear the bit. */ imported and dumped. Clear the bit. */
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap_page, cur_page_id, bitmap_page, cur_page_id,
physical_size, physical_size, false, &mtr);
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
} }
} }
@ -4951,7 +4838,6 @@ ibuf_set_bitmap_for_bulk_load(
buf_block_t* block, buf_block_t* block,
bool reset) bool reset)
{ {
page_t* bitmap_page;
mtr_t mtr; mtr_t mtr;
ulint free_val; ulint free_val;
@ -4959,20 +4845,22 @@ ibuf_set_bitmap_for_bulk_load(
free_val = ibuf_index_page_calc_free(block); free_val = ibuf_index_page_calc_free(block);
mtr_start(&mtr); mtr.start();
fil_space_t* space = mtr.set_named_space_id(block->page.id.space()); fil_space_t* space = mtr.set_named_space_id(block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id, buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
space->zip_size(), &mtr); space->zip_size(),
&mtr);
free_val = reset ? 0 : ibuf_index_page_calc_free(block); free_val = reset ? 0 : ibuf_index_page_calc_free(block);
ibuf_bitmap_page_set_bits( /* FIXME: update the bitmap byte only once! */
ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
bitmap_page, block->page.id, block->physical_size(), bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, free_val, &mtr); free_val, &mtr);
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap_page, block->page.id, block->physical_size(), bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_BUFFERED, FALSE, &mtr); false, &mtr);
mtr_commit(&mtr); mtr.commit();
} }

View File

@ -541,7 +541,7 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
page. We are not modifying the compressed page frame at all. */ page. We are not modifying the compressed page frame at all. */
*rec|= REC_INFO_MIN_REC_FLAG; *rec|= REC_INFO_MIN_REC_FLAG;
else else
mlog_write_ulint(rec, *rec | REC_INFO_MIN_REC_FLAG, MLOG_1BYTE, mtr); mtr->write<1>(block, rec, *rec | REC_INFO_MIN_REC_FLAG);
} }
/** Seek to the parent page of a B-tree page. /** Seek to the parent page of a B-tree page.

View File

@ -29,28 +29,6 @@ Created 6/2/1994 Heikki Tuuri
#include "mtr0log.h" #include "mtr0log.h"
#include "page0zip.h" #include "page0zip.h"
/**************************************************************//**
Sets the index id field of a page. */
UNIV_INLINE
void
btr_page_set_index_id(
/*==================*/
page_t* page, /*!< in: page to be created */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
part will be updated, or NULL */
index_id_t id, /*!< in: index id */
mtr_t* mtr) /*!< in: mtr */
{
if (page_zip) {
mach_write_to_8(page + (PAGE_HEADER + PAGE_INDEX_ID), id);
page_zip_write_header(page_zip,
page + (PAGE_HEADER + PAGE_INDEX_ID),
8, mtr);
} else {
mlog_write_ull(page + (PAGE_HEADER + PAGE_INDEX_ID), id, mtr);
}
}
/**************************************************************//** /**************************************************************//**
Gets the index id field of a page. Gets the index id field of a page.
@return index id */ @return index id */
@ -63,77 +41,56 @@ btr_page_get_index_id(
return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID)); return(mach_read_from_8(page + PAGE_HEADER + PAGE_INDEX_ID));
} }
/********************************************************//** /** Set PAGE_LEVEL.
Sets the node level field in an index page. */ @param[in,out] block buffer block
UNIV_INLINE @param[in] level page level
void @param[in,out] mtr mini-transaction */
btr_page_set_level( inline
/*===============*/ void btr_page_set_level(buf_block_t *block, ulint level, mtr_t *mtr)
page_t* page, /*!< in: index page */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
part will be updated, or NULL */
ulint level, /*!< in: level, leaf level == 0 */
mtr_t* mtr) /*!< in: mini-transaction handle */
{ {
ut_ad(page != NULL); ut_ad(level <= BTR_MAX_NODE_LEVEL);
ut_ad(mtr != NULL);
ut_ad(level <= BTR_MAX_NODE_LEVEL);
if (page_zip) { byte *page_level= PAGE_HEADER + PAGE_LEVEL + block->frame;
mach_write_to_2(page + (PAGE_HEADER + PAGE_LEVEL), level);
page_zip_write_header(page_zip, if (UNIV_LIKELY_NULL(block->page.zip.data))
page + (PAGE_HEADER + PAGE_LEVEL), {
2, mtr); mach_write_to_2(page_level, level);
} else { page_zip_write_header(&block->page.zip, page_level, 2, mtr);
mlog_write_ulint(page + (PAGE_HEADER + PAGE_LEVEL), level, }
MLOG_2BYTES, mtr); else
} mtr->write<2,mtr_t::OPT>(*block, page_level, level);
} }
/********************************************************//** /** Set FIL_PAGE_NEXT.
Sets the next index page field. */ @param[in,out] block buffer block
UNIV_INLINE @param[in] next number of successor page
void @param[in,out] mtr mini-transaction */
btr_page_set_next( inline void btr_page_set_next(buf_block_t *block, ulint next, mtr_t *mtr)
/*==============*/
page_t* page, /*!< in: index page */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
part will be updated, or NULL */
ulint next, /*!< in: next page number */
mtr_t* mtr) /*!< in: mini-transaction handle */
{ {
ut_ad(page != NULL); byte *fil_page_next= block->frame + FIL_PAGE_NEXT;
ut_ad(mtr != NULL); if (UNIV_LIKELY_NULL(block->page.zip.data))
{
if (page_zip) { mach_write_to_4(fil_page_next, next);
mach_write_to_4(page + FIL_PAGE_NEXT, next); page_zip_write_header(&block->page.zip, fil_page_next, 4, mtr);
page_zip_write_header(page_zip, page + FIL_PAGE_NEXT, 4, mtr); }
} else { else
mlog_write_ulint(page + FIL_PAGE_NEXT, next, MLOG_4BYTES, mtr); mtr->write<4>(*block, fil_page_next, next);
}
} }
/********************************************************//** /** Set FIL_PAGE_PREV.
Sets the previous index page field. */ @param[in,out] block buffer block
UNIV_INLINE @param[in] prev number of predecessor page
void @param[in,out] mtr mini-transaction */
btr_page_set_prev( inline void btr_page_set_prev(buf_block_t *block, ulint prev, mtr_t *mtr)
/*==============*/
page_t* page, /*!< in: index page */
page_zip_des_t* page_zip,/*!< in: compressed page whose uncompressed
part will be updated, or NULL */
ulint prev, /*!< in: previous page number */
mtr_t* mtr) /*!< in: mini-transaction handle */
{ {
ut_ad(page != NULL); byte *fil_page_prev= block->frame + FIL_PAGE_PREV;
ut_ad(mtr != NULL); if (UNIV_LIKELY_NULL(block->page.zip.data))
{
if (page_zip) { mach_write_to_4(fil_page_prev, prev);
mach_write_to_4(page + FIL_PAGE_PREV, prev); page_zip_write_header(&block->page.zip, fil_page_prev, 4, mtr);
page_zip_write_header(page_zip, page + FIL_PAGE_PREV, 4, mtr); }
} else { else
mlog_write_ulint(page + FIL_PAGE_PREV, prev, MLOG_4BYTES, mtr); mtr->write<4>(*block, fil_page_prev, prev);
}
} }
/**************************************************************//** /**************************************************************//**

View File

@ -101,11 +101,25 @@ class PageBulk
/** Insert a record in the page. /** Insert a record in the page.
@param[in] rec record @param[in] rec record
@param[in] offsets record offsets */ @param[in] offsets record offsets */
void insert(const rec_t* rec, ulint* offsets); inline void insert(const rec_t* rec, ulint* offsets);
private:
/** Page format */
enum format { REDUNDANT, DYNAMIC, COMPRESSED };
/** Mark end of insertion to the page. Scan all records to set page
dirs, and set page header members.
@tparam format the page format */
template<format> inline void finishPage();
/** Insert a record in the page.
@tparam format the page format
@param[in] rec record
@param[in] offsets record offsets */
template<format> inline void insertPage(const rec_t* rec,
ulint* offsets);
public:
/** Mark end of insertion to the page. Scan all records to set page /** Mark end of insertion to the page. Scan all records to set page
dirs, and set page header members. */ dirs, and set page header members. */
void finish(); inline void finish();
/** Commit mtr for a page /** Commit mtr for a page
@param[in] success Flag whether all inserts succeed. */ @param[in] success Flag whether all inserts succeed. */
@ -199,6 +213,8 @@ class PageBulk
return(m_err); return(m_err);
} }
void set_modified() { m_mtr.set_modified(); }
/* Memory heap for internal allocation */ /* Memory heap for internal allocation */
mem_heap_t* m_heap; mem_heap_t* m_heap;

View File

@ -646,8 +646,7 @@ to free the field. */
void void
btr_cur_disown_inherited_fields( btr_cur_disown_inherited_fields(
/*============================*/ /*============================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed buf_block_t* block, /*!< in/out: index page */
part will be updated, or NULL */
rec_t* rec, /*!< in/out: record in a clustered index */ rec_t* rec, /*!< in/out: record in a clustered index */
dict_index_t* index, /*!< in: index of the page */ dict_index_t* index, /*!< in: index of the page */
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
@ -722,12 +721,12 @@ btr_free_externally_stored_field(
page_zip_write_blob_ptr(), or NULL */ page_zip_write_blob_ptr(), or NULL */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index), const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
or NULL */ or NULL */
page_zip_des_t* page_zip, /*!< in: compressed page corresponding buf_block_t* block, /*!< in/out: page of field_ref */
to rec, or NULL if rec == NULL */
ulint i, /*!< in: field number of field_ref; ulint i, /*!< in: field number of field_ref;
ignored if rec == NULL */ ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */ bool rollback, /*!< in: performing rollback? */
mtr_t* local_mtr); /*!< in: mtr containing the latch */ mtr_t* local_mtr) /*!< in: mtr containing the latch */
MY_ATTRIBUTE((nonnull(1,2,5,8)));
/** Copies the prefix of an externally stored field of a record. /** Copies the prefix of an externally stored field of a record.
The clustered index record must be protected by a lock or a page latch. The clustered index record must be protected by a lock or a page latch.

View File

@ -716,16 +716,6 @@ inline void aligned_free(void *ptr)
#endif #endif
} }
/**********************************************************************//**
Gets the space id, page offset, and byte offset within page of a
pointer pointing to a buffer frame containing a file page. */
UNIV_INLINE
void
buf_ptr_get_fsp_addr(
/*=================*/
const void* ptr, /*!< in: pointer to a buffer frame */
ulint* space, /*!< out: space id */
fil_addr_t* addr); /*!< out: page offset and byte offset */
/**********************************************************************//** /**********************************************************************//**
Gets the hash value of a block. This can be used in searches in the Gets the hash value of a block. This can be used in searches in the
lock hash table. lock hash table.
@ -1094,9 +1084,9 @@ buf_block_get_frame(
Gets the compressed page descriptor corresponding to an uncompressed page Gets the compressed page descriptor corresponding to an uncompressed page
if applicable. */ if applicable. */
#define buf_block_get_page_zip(block) \ #define buf_block_get_page_zip(block) \
((block)->page.zip.data ? &(block)->page.zip : NULL) (UNIV_LIKELY_NULL((block)->page.zip.data) ? &(block)->page.zip : NULL)
#define is_buf_block_get_page_zip(block) \ #define is_buf_block_get_page_zip(block) \
((block)->page.zip.data != 0) UNIV_LIKELY_NULL((block)->page.zip.data)
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/** Get a buffer block from an adaptive hash index pointer. /** Get a buffer block from an adaptive hash index pointer.

View File

@ -758,25 +758,6 @@ buf_frame_align(
return(frame); return(frame);
} }
/**********************************************************************//**
Gets the space id, page offset, and byte offset within page of a
pointer pointing to a buffer frame containing a file page. */
UNIV_INLINE
void
buf_ptr_get_fsp_addr(
/*=================*/
const void* ptr, /*!< in: pointer to a buffer frame */
ulint* space, /*!< out: space id */
fil_addr_t* addr) /*!< out: page offset and byte offset */
{
const page_t* page = (const page_t*) ut_align_down(ptr,
srv_page_size);
*space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
addr->boffset = static_cast<uint16_t>(ut_align_offset(ptr, srv_page_size));
}
/**********************************************************************//** /**********************************************************************//**
Gets the hash value of the page the pointer is pointing to. This can be used Gets the hash value of the page the pointer is pointing to. This can be used
in searches in the lock hash table. in searches in the lock hash table.

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation. Copyright (c) 2018, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -33,15 +33,8 @@ Created 4/18/1996 Heikki Tuuri
#include "buf0buf.h" #include "buf0buf.h"
#include "dict0dict.h" #include "dict0dict.h"
typedef byte dict_hdr_t; /** @return the DICT_HDR block, x-latched */
buf_block_t *dict_hdr_get(mtr_t* mtr);
/**********************************************************************//**
Gets a pointer to the dictionary header and x-latches its page.
@return pointer to the dictionary header, page x-latched */
dict_hdr_t*
dict_hdr_get(
/*=========*/
mtr_t* mtr); /*!< in: mtr */
/**********************************************************************//** /**********************************************************************//**
Returns a new table, index, or space id. */ Returns a new table, index, or space id. */
void void

View File

@ -101,7 +101,6 @@ see the table in fsp0types.h @{ */
#define FSP_HEADER_OFFSET FIL_PAGE_DATA #define FSP_HEADER_OFFSET FIL_PAGE_DATA
/* The data structures in files are defined just as byte strings in C */ /* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t; typedef byte xdes_t;
/* SPACE HEADER /* SPACE HEADER
@ -207,7 +206,7 @@ typedef byte fseg_inode_t;
(16 + 3 * FLST_BASE_NODE_SIZE \ (16 + 3 * FLST_BASE_NODE_SIZE \
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE) + FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
#define FSEG_MAGIC_N_VALUE 97937874 static constexpr uint32_t FSEG_MAGIC_N_VALUE= 97937874;
#define FSEG_FILLFACTOR 8 /* If this value is x, then if #define FSEG_FILLFACTOR 8 /* If this value is x, then if
the number of unused but reserved the number of unused but reserved
@ -534,7 +533,7 @@ by repeatedly calling this function in different mini-transactions.
Doing the freeing in a single mini-transaction might result in Doing the freeing in a single mini-transaction might result in
too big a mini-transaction. too big a mini-transaction.
@return TRUE if freeing completed */ @return TRUE if freeing completed */
ibool bool
fseg_free_step_func( fseg_free_step_func(
fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header
resides on the first page of the frag list resides on the first page of the frag list
@ -554,8 +553,8 @@ fseg_free_step_func(
/**********************************************************************//** /**********************************************************************//**
Frees part of a segment. Differs from fseg_free_step because this function Frees part of a segment. Differs from fseg_free_step because this function
leaves the header page unfreed. leaves the header page unfreed.
@return TRUE if freeing completed, except the header page */ @return true if freeing completed, except the header page */
ibool bool
fseg_free_step_not_header_func( fseg_free_step_not_header_func(
fseg_header_t* header, /*!< in: segment header which must reside on fseg_header_t* header, /*!< in: segment header which must reside on
the first fragment page of the segment */ the first fragment page of the segment */

View File

@ -68,79 +68,91 @@ typedef byte flst_node_t;
@param[in,out] block file page @param[in,out] block file page
@param[in] ofs byte offset of the list base node @param[in] ofs byte offset of the list base node
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
inline void flst_init(buf_block_t* block, uint16_t ofs, mtr_t* mtr) inline void flst_init(const buf_block_t* block, uint16_t ofs, mtr_t* mtr)
{ {
ut_ad(0 == mach_read_from_2(FLST_LEN + ofs + block->frame)); ut_ad(!mach_read_from_2(FLST_LEN + ofs + block->frame));
ut_ad(0 == mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs ut_ad(!mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + block->frame));
+ block->frame)); ut_ad(!mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + block->frame));
ut_ad(0 == mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
+ block->frame)); mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
compile_time_assert(FIL_NULL == 0xffU * 0x1010101U); mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
} }
/** Write a null file address. /** Write a null file address.
@param[in,out] faddr file address to be zeroed otu @param[in] b file page
@param[in,out] mtr mini-transaction */ @param[in,out] addr file address to be zeroed out
inline void flst_zero_addr(fil_faddr_t* faddr, mtr_t* mtr) @param[in,out] mtr mini-transaction */
inline void flst_zero_addr(const buf_block_t& b, fil_faddr_t *addr, mtr_t *mtr)
{ {
if (mach_read_from_4(faddr + FIL_ADDR_PAGE) != FIL_NULL) { if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL)
mlog_memset(faddr + FIL_ADDR_PAGE, 4, 0xff, mtr); mlog_memset(&b, ulint(addr - b.frame) + FIL_ADDR_PAGE, 4, 0xff, mtr);
} mtr->write<2,mtr_t::OPT>(b, addr + FIL_ADDR_BYTE, 0U);
if (mach_read_from_2(faddr + FIL_ADDR_BYTE)) {
mlog_write_ulint(faddr + FIL_ADDR_BYTE, 0, MLOG_2BYTES, mtr);
}
} }
/********************************************************************//** /** Write a file address.
Initializes a list base node. */ @param[in] block file page
UNIV_INLINE @param[in,out] faddr file address location
void @param[in] addr file address to be written out
flst_init( @param[in,out] mtr mini-transaction */
/*======*/ inline void flst_write_addr(const buf_block_t& block, fil_faddr_t *faddr,
flst_base_node_t* base, /*!< in: pointer to base node */ fil_addr_t addr, mtr_t* mtr)
mtr_t* mtr); /*!< in: mini-transaction handle */ {
/********************************************************************//** ut_ad(mtr->memo_contains_page_flagged(faddr,
Adds a node as the last node in a list. */ MTR_MEMO_PAGE_X_FIX
void | MTR_MEMO_PAGE_SX_FIX));
flst_add_last( ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
/*==========*/ ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA);
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node, /*!< in: node to add */ mtr->write<4,mtr_t::OPT>(block, faddr + FIL_ADDR_PAGE, addr.page);
mtr_t* mtr); /*!< in: mini-transaction handle */ mtr->write<2,mtr_t::OPT>(block, faddr + FIL_ADDR_BYTE, addr.boffset);
/********************************************************************//** }
Adds a node as the first node in a list. */
void /** Initialize a list base node.
flst_add_first( @param[in] block file page
/*===========*/ @param[in,out] base base node
flst_base_node_t* base, /*!< in: pointer to base node of list */ @param[in,out] mtr mini-transaction */
flst_node_t* node, /*!< in: node to add */ inline void flst_init(const buf_block_t& block, byte *base, mtr_t *mtr)
mtr_t* mtr); /*!< in: mini-transaction handle */ {
/********************************************************************//** ut_ad(mtr->memo_contains_page_flagged(base, MTR_MEMO_PAGE_X_FIX |
Removes a node. */ MTR_MEMO_PAGE_SX_FIX));
void mtr->write<4,mtr_t::OPT>(block, base + FLST_LEN, 0U);
flst_remove( flst_zero_addr(block, base + FLST_FIRST, mtr);
/*========*/ flst_zero_addr(block, base + FLST_LAST, mtr);
flst_base_node_t* base, /*!< in: pointer to base node of list */ }
flst_node_t* node2, /*!< in: node to remove */
mtr_t* mtr); /*!< in: mini-transaction handle */ /** Append a file list node to a list.
/** Get the length of a list. @param[in,out] base base node block
@param[in] base base node @param[in] boffset byte offset of the base node
@return length */ @param[in,out] add block to be added
UNIV_INLINE @param[in] aoffset byte offset of the node to be added
uint32_t @param[in,outr] mtr mini-transaction */
flst_get_len( void flst_add_last(buf_block_t *base, uint16_t boffset,
const flst_base_node_t* base); buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
/********************************************************************//** MY_ATTRIBUTE((nonnull));
Writes a file address. */ /** Prepend a file list node to a list.
UNIV_INLINE @param[in,out] base base node block
void @param[in] boffset byte offset of the base node
flst_write_addr( @param[in,out] add block to be added
/*============*/ @param[in] aoffset byte offset of the node to be added
fil_faddr_t* faddr, /*!< in: pointer to file faddress */ @param[in,outr] mtr mini-transaction */
fil_addr_t addr, /*!< in: file address */ void flst_add_first(buf_block_t *base, uint16_t boffset,
mtr_t* mtr); /*!< in: mini-transaction handle */ buf_block_t *add, uint16_t aoffset, mtr_t *mtr)
MY_ATTRIBUTE((nonnull));
/** Remove a file list node.
@param[in,out] base base node block
@param[in] boffset byte offset of the base node
@param[in,out] cur block to be removed
@param[in] coffset byte offset of the current record to be removed
@param[in,outr] mtr mini-transaction */
void flst_remove(buf_block_t *base, uint16_t boffset,
buf_block_t *cur, uint16_t coffset, mtr_t *mtr)
MY_ATTRIBUTE((nonnull));
/** @return the length of a list */
inline uint32_t flst_get_len(const flst_base_node_t *base)
{
return mach_read_from_4(base + FLST_LEN);
}
/** @return a file address */ /** @return a file address */
inline fil_addr_t flst_read_addr(const fil_faddr_t *faddr) inline fil_addr_t flst_read_addr(const fil_faddr_t *faddr)
@ -176,16 +188,10 @@ inline fil_addr_t flst_get_prev_addr(const flst_node_t *node)
return flst_read_addr(node + FLST_PREV); return flst_read_addr(node + FLST_PREV);
} }
/********************************************************************//** #ifdef UNIV_DEBUG
Validates a file-based list. /** Validate a file-based list. */
@return TRUE if ok */ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr);
ibool #endif
flst_validate(
/*==========*/
const flst_base_node_t* base, /*!< in: pointer to base node of list */
mtr_t* mtr1); /*!< in: mtr */
#include "fut0lst.ic"
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */

View File

@ -1,80 +0,0 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
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/fut0lst.ic
File-based list utilities
Created 11/28/1995 Heikki Tuuri
***********************************************************************/
#include "buf0buf.h"
/********************************************************************//**
Writes a file address. */
UNIV_INLINE
void
flst_write_addr(
/*============*/
fil_faddr_t* faddr, /*!< in: pointer to file faddress */
fil_addr_t addr, /*!< in: file address */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
ut_ad(faddr && mtr);
ut_ad(mtr_memo_contains_page_flagged(mtr, faddr,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA);
mlog_write_ulint(faddr + FIL_ADDR_PAGE, addr.page, MLOG_4BYTES, mtr);
mlog_write_ulint(faddr + FIL_ADDR_BYTE, addr.boffset,
MLOG_2BYTES, mtr);
}
/********************************************************************//**
Initializes a list base node. */
UNIV_INLINE
void
flst_init(
/*======*/
flst_base_node_t* base, /*!< in: pointer to base node */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
ut_ad(mtr_memo_contains_page_flagged(mtr, base,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
if (mach_read_from_4(base + FLST_LEN)) {
mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
}
flst_zero_addr(base + FLST_FIRST, mtr);
flst_zero_addr(base + FLST_LAST, mtr);
}
/** Get the length of a list.
@param[in] base base node
@return length */
UNIV_INLINE
uint32_t
flst_get_len(
const flst_base_node_t* base)
{
return(mach_read_from_4(base + FLST_LEN));
}

View File

@ -33,26 +33,6 @@ Created 12/7/1995 Heikki Tuuri
// Forward declaration // Forward declaration
struct dict_index_t; struct dict_index_t;
/********************************************************//**
Writes 1, 2 or 4 bytes to a file page. Writes the corresponding log
record to the mini-transaction log if mtr is not NULL. */
void
mlog_write_ulint(
/*=============*/
byte* ptr, /*!< in: pointer where to write */
ulint val, /*!< in: value to write */
mlog_id_t type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//**
Writes 8 bytes to a file page. Writes the corresponding log
record to the mini-transaction log, only if mtr is not NULL */
void
mlog_write_ull(
/*===========*/
byte* ptr, /*!< in: pointer where to write */
ib_uint64_t val, /*!< in: value to write */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************//** /********************************************************//**
Writes a string to a file page buffered in the buffer pool. Writes the Writes a string to a file page buffered in the buffer pool. Writes the
corresponding log record to the mini-transaction log. */ corresponding log record to the mini-transaction log. */
@ -80,7 +60,7 @@ mlog_log_string(
@param[in] val the data byte to write @param[in] val the data byte to write
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void
mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr); mlog_memset(const buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr);
/** Initialize a string of bytes. /** Initialize a string of bytes.
@param[in,out] byte byte address @param[in,out] byte byte address
@ -124,14 +104,6 @@ mlog_catenate_ulint_compressed(
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
ulint val); /*!< in: value to write */ ulint val); /*!< in: value to write */
/********************************************************//** /********************************************************//**
Catenates a compressed 64-bit integer to mlog. */
UNIV_INLINE
void
mlog_catenate_ull_compressed(
/*=========================*/
mtr_t* mtr, /*!< in: mtr */
ib_uint64_t val); /*!< in: value to write */
/********************************************************//**
Opens a buffer to mlog. It must be closed with mlog_close. Opens a buffer to mlog. It must be closed with mlog_close.
@return buffer, NULL if log mode MTR_LOG_NONE */ @return buffer, NULL if log mode MTR_LOG_NONE */
UNIV_INLINE UNIV_INLINE
@ -151,6 +123,56 @@ mlog_close(
byte* ptr); /*!< in: buffer space from ptr up was byte* ptr); /*!< in: buffer space from ptr up was
not used */ not used */
/** Write 1, 2, 4, or 8 bytes to a file page.
@param[in] block file page
@param[in,out] ptr pointer in file page
@param[in] val value to write
@tparam l number of bytes to write
@tparam w write request type
@tparam V type of val */
template<unsigned l,mtr_t::write_type w,typename V>
inline void mtr_t::write(const buf_block_t &block, byte *ptr, V val)
{
ut_ad(ut_align_down(ptr, srv_page_size) == block.frame);
ut_ad(m_log_mode == MTR_LOG_NONE || m_log_mode == MTR_LOG_NO_REDO ||
!block.page.zip.data ||
/* written by fil_crypt_rotate_page() or innodb_make_page_dirty()? */
(w == FORCED && l == 1 && ptr == &block.frame[FIL_PAGE_SPACE_ID]) ||
mach_read_from_2(block.frame + FIL_PAGE_TYPE) <= FIL_PAGE_TYPE_ZBLOB2);
static_assert(l == 1 || l == 2 || l == 4 || l == 8, "wrong length");
switch (l) {
case 1:
if (w == OPT && mach_read_from_1(ptr) == val) return;
ut_ad(w != NORMAL || mach_read_from_1(ptr) != val);
mach_write_to_1(ptr, val);
break;
case 2:
if (w == OPT && mach_read_from_2(ptr) == val) return;
ut_ad(w != NORMAL || mach_read_from_2(ptr) != val);
mach_write_to_2(ptr, val);
break;
case 4:
if (w == OPT && mach_read_from_4(ptr) == val) return;
ut_ad(w != NORMAL || mach_read_from_4(ptr) != val);
mach_write_to_4(ptr, val);
break;
case 8:
if (w == OPT && mach_read_from_8(ptr) == val) return;
ut_ad(w != NORMAL || mach_read_from_8(ptr) != val);
mach_write_to_8(ptr, val);
break;
}
byte *log_ptr= mlog_open(this, 11 + 2 + (l == 8 ? 9 : 5));
if (!log_ptr)
return;
if (l == 8)
log_write(block, ptr, static_cast<mlog_id_t>(l), log_ptr, uint64_t{val});
else
log_write(block, ptr, static_cast<mlog_id_t>(l), log_ptr,
static_cast<uint32_t>(val));
}
/** Writes a log record about an operation. /** Writes a log record about an operation.
@param[in] type redo log record type @param[in] type redo log record type
@param[in] space_id tablespace identifier @param[in] space_id tablespace identifier
@ -195,7 +217,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */ ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */ ulint* page_no);/*!< out: page number */
/********************************************************//** /********************************************************//**
Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset. Parses a log record written by mtr_t::write(), mlog_memset().
@return parsed record end, NULL if not a complete record */ @return parsed record end, NULL if not a complete record */
const byte* const byte*
mlog_parse_nbytes( mlog_parse_nbytes(

View File

@ -141,30 +141,6 @@ mlog_catenate_ulint_compressed(
mlog_close(mtr, log_ptr); mlog_close(mtr, log_ptr);
} }
/********************************************************//**
Catenates a compressed 64-bit integer to mlog. */
UNIV_INLINE
void
mlog_catenate_ull_compressed(
/*=========================*/
mtr_t* mtr, /*!< in: mtr */
ib_uint64_t val) /*!< in: value to write */
{
byte* log_ptr;
log_ptr = mlog_open(mtr, 15);
/* If no logging is requested, we may return now */
if (log_ptr == NULL) {
return;
}
log_ptr += mach_u64_write_compressed(log_ptr, val);
mlog_close(mtr, log_ptr);
}
/** Writes a log record about an operation. /** Writes a log record about an operation.
@param[in] type redo log record type @param[in] type redo log record type
@param[in] space_id tablespace identifier @param[in] space_id tablespace identifier

View File

@ -425,7 +425,50 @@ struct mtr_t {
static inline bool is_block_dirtied(const buf_block_t* block) static inline bool is_block_dirtied(const buf_block_t* block)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/** Write request types */
enum write_type
{
/** the page is guaranteed to always change */
NORMAL= 0,
/** optional: the page contents might not change */
OPT,
/** force a write, even if the page contents is not changing */
FORCED
};
/** Write 1, 2, 4, or 8 bytes to a file page.
@param[in] block file page
@param[in,out] ptr pointer in file page
@param[in] val value to write
@tparam l number of bytes to write
@tparam w write request type
@tparam V type of val */
template<unsigned l,write_type w= NORMAL,typename V>
inline void write(const buf_block_t &block, byte *ptr, V val)
MY_ATTRIBUTE((nonnull));
private: private:
/**
Write a log record for writing 1, 2, or 4 bytes.
@param[in] block file page
@param[in,out] ptr pointer in file page
@param[in] l number of bytes to write
@param[in,out] log_ptr log record buffer
@param[in] val value to write */
void log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
byte *log_ptr, uint32_t val)
MY_ATTRIBUTE((nonnull));
/**
Write a log record for writing 8 bytes.
@param[in] block file page
@param[in,out] ptr pointer in file page
@param[in] l number of bytes to write (8)
@param[in,out] log_ptr log record buffer
@param[in] val value to write */
void log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
byte *log_ptr, uint64_t val)
MY_ATTRIBUTE((nonnull));
/** Prepare to write the mini-transaction log to the redo log buffer. /** Prepare to write the mini-transaction log to the redo log buffer.
@return number of bytes to write in finish_write() */ @return number of bytes to write in finish_write() */
inline ulint prepare_write(); inline ulint prepare_write();

View File

@ -52,7 +52,7 @@ enum mtr_log_t {
/** @name Log item types /** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val The log items are declared 'byte' so that the compiler can warn if val
and type parameters are switched in a call to mlog_write_ulint. NOTE! and type parameters are switched in a call to mlog_write. NOTE!
For 1 - 8 bytes, the flag value must give the length also! @{ */ For 1 - 8 bytes, the flag value must give the length also! @{ */
enum mlog_id_t { enum mlog_id_t {
/** if the mtr contains only one log record for one page, /** if the mtr contains only one log record for one page,

View File

@ -31,6 +31,7 @@ Created 2/2/1994 Heikki Tuuri
#include "fil0fil.h" #include "fil0fil.h"
#include "buf0buf.h" #include "buf0buf.h"
#include "rem0rec.h" #include "rem0rec.h"
#include "mach0data.h"
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
#include "dict0dict.h" #include "dict0dict.h"
#include "data0data.h" #include "data0data.h"
@ -42,8 +43,6 @@ Created 2/2/1994 Heikki Tuuri
Index page header starts at the first offset left free by the FIL-module */ Index page header starts at the first offset left free by the FIL-module */
typedef byte page_header_t; typedef byte page_header_t;
#else
# include "mach0data.h"
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */
#define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this #define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this
@ -393,13 +392,17 @@ inline
bool bool
page_rec_is_infimum(const rec_t* rec); page_rec_is_infimum(const rec_t* rec);
/*************************************************************//** /** Read PAGE_MAX_TRX_ID.
Returns the max trx id field value. */ @param[in] page index page
UNIV_INLINE @return the value of PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC */
trx_id_t inline trx_id_t page_get_max_trx_id(const page_t *page)
page_get_max_trx_id( {
/*================*/ static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
const page_t* page); /*!< in: page */ const byte *p= static_cast<const byte*>
(MY_ASSUME_ALIGNED(page + PAGE_HEADER + PAGE_MAX_TRX_ID, 8));
return mach_read_from_8(p);
}
/*************************************************************//** /*************************************************************//**
Sets the max trx id field value. */ Sets the max trx id field value. */
void void
@ -424,7 +427,6 @@ page_update_max_trx_id(
/** Persist the AUTO_INCREMENT value on a clustered index root page. /** Persist the AUTO_INCREMENT value on a clustered index root page.
@param[in,out] block clustered index root page @param[in,out] block clustered index root page
@param[in] index clustered index
@param[in] autoinc next available AUTO_INCREMENT value @param[in] autoinc next available AUTO_INCREMENT value
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@param[in] reset whether to reset the AUTO_INCREMENT @param[in] reset whether to reset the AUTO_INCREMENT
@ -433,7 +435,6 @@ page_update_max_trx_id(
void void
page_set_autoinc( page_set_autoinc(
buf_block_t* block, buf_block_t* block,
const dict_index_t* index MY_ATTRIBUTE((unused)),
ib_uint64_t autoinc, ib_uint64_t autoinc,
mtr_t* mtr, mtr_t* mtr,
bool reset) bool reset)
@ -517,17 +518,12 @@ page_header_set_ptr(
ulint field, /*!< in/out: PAGE_FREE, ... */ ulint field, /*!< in/out: PAGE_FREE, ... */
const byte* ptr); /*!< in: pointer or NULL*/ const byte* ptr); /*!< in: pointer or NULL*/
/*************************************************************//** /**
Resets the last insert info field in the page header. Writes to mlog Reset PAGE_LAST_INSERT.
about this operation. */ @param[in,out] block file page
UNIV_INLINE @param[in,out] mtr mini-transaction */
void inline void page_header_reset_last_insert(buf_block_t *block, mtr_t *mtr)
page_header_reset_last_insert( MY_ATTRIBUTE((nonnull));
/*==========================*/
page_t* page, /*!< in: page */
page_zip_des_t* page_zip,/*!< in/out: compressed page whose
uncompressed part will be updated, or NULL */
mtr_t* mtr); /*!< in: mtr */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
@ -663,14 +659,17 @@ ibool
page_rec_check( page_rec_check(
/*===========*/ /*===========*/
const rec_t* rec); /*!< in: record */ const rec_t* rec); /*!< in: record */
/***************************************************************//** /** Get the record pointed to by a directory slot.
Gets the record pointed to by a directory slot. @param[in] slot directory slot
@return pointer to record */ @return pointer to record */
UNIV_INLINE inline rec_t *page_dir_slot_get_rec(page_dir_slot_t *slot)
const rec_t* {
page_dir_slot_get_rec( return page_align(slot) + mach_read_from_2(slot);
/*==================*/ }
const page_dir_slot_t* slot); /*!< in: directory slot */ inline const rec_t *page_dir_slot_get_rec(const page_dir_slot_t *slot)
{
return page_dir_slot_get_rec(const_cast<rec_t*>(slot));
}
/***************************************************************//** /***************************************************************//**
This is used to set the record offset in a directory slot. */ This is used to set the record offset in a directory slot. */
UNIV_INLINE UNIV_INLINE

View File

@ -28,24 +28,10 @@ Created 2/2/1994 Heikki Tuuri
#define page0page_ic #define page0page_ic
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
#include "mach0data.h"
#include "rem0cmp.h" #include "rem0cmp.h"
#include "mtr0log.h" #include "mtr0log.h"
#include "page0zip.h" #include "page0zip.h"
/*************************************************************//**
Returns the max trx id field value. */
UNIV_INLINE
trx_id_t
page_get_max_trx_id(
/*================*/
const page_t* page) /*!< in: page */
{
ut_ad(page);
return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID));
}
/*************************************************************//** /*************************************************************//**
Sets the max trx id field value if trx_id is bigger than the previous Sets the max trx id field value if trx_id is bigger than the previous
value. */ value. */
@ -115,21 +101,16 @@ page_set_ssn_id(
node_seq_t ssn_id, /*!< in: transaction id */ node_seq_t ssn_id, /*!< in: transaction id */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
page_t* page = buf_block_get_frame(block);
ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block, ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block,
MTR_MEMO_PAGE_SX_FIX MTR_MEMO_PAGE_SX_FIX
| MTR_MEMO_PAGE_X_FIX)); | MTR_MEMO_PAGE_X_FIX));
if (page_zip) { byte* ssn = block->frame + FIL_RTREE_SPLIT_SEQ_NUM;
mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_write_header(page_zip, mach_write_to_8(ssn, ssn_id);
page + FIL_RTREE_SPLIT_SEQ_NUM, page_zip_write_header(page_zip, ssn, 8, mtr);
8, mtr);
} else if (mtr) {
mlog_write_ull(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id, mtr);
} else { } else {
mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); mtr->write<8,mtr_t::OPT>(*block, ssn, ssn_id);
} }
} }
@ -229,30 +210,21 @@ page_header_set_ptr(
page_header_set_field(page, page_zip, field, offs); page_header_set_field(page, page_zip, field, offs);
} }
/*************************************************************//** /**
Resets the last insert info field in the page header. Writes to mlog Reset PAGE_LAST_INSERT.
about this operation. */ @param[in,out] block file page
UNIV_INLINE @param[in,out] mtr mini-transaction */
void inline void page_header_reset_last_insert(buf_block_t *block, mtr_t *mtr)
page_header_reset_last_insert(
/*==========================*/
page_t* page, /*!< in/out: page */
page_zip_des_t* page_zip,/*!< in/out: compressed page whose
uncompressed part will be updated, or NULL */
mtr_t* mtr) /*!< in: mtr */
{ {
ut_ad(page != NULL); byte *b= &block->frame[PAGE_HEADER + PAGE_LAST_INSERT];
ut_ad(mtr != NULL);
if (page_zip) { if (UNIV_LIKELY_NULL(block->page.zip.data))
mach_write_to_2(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0); {
page_zip_write_header(page_zip, mach_write_to_2(b, 0);
page + (PAGE_HEADER + PAGE_LAST_INSERT), page_zip_write_header(&block->page.zip, b, 2, mtr);
2, mtr); }
} else { else
mlog_write_ulint(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0, mtr->write<2,mtr_t::OPT>(*block, b, 0U);
MLOG_2BYTES, mtr);
}
} }
/***************************************************************//** /***************************************************************//**
@ -541,18 +513,6 @@ page_rec_check(
return(TRUE); return(TRUE);
} }
/***************************************************************//**
Gets the record pointed to by a directory slot.
@return pointer to record */
UNIV_INLINE
const rec_t*
page_dir_slot_get_rec(
/*==================*/
const page_dir_slot_t* slot) /*!< in: directory slot */
{
return(page_align(slot) + mach_read_from_2(slot));
}
/***************************************************************//** /***************************************************************//**
This is used to set the record offset in a directory slot. */ This is used to set the record offset in a directory slot. */
UNIV_INLINE UNIV_INLINE

View File

@ -184,15 +184,15 @@ class purge_sys_t
to purge */ to purge */
trx_rseg_t* rseg; /*!< Rollback segment for the next undo trx_rseg_t* rseg; /*!< Rollback segment for the next undo
record to purge */ record to purge */
ulint page_no; /*!< Page number for the next undo uint32_t page_no; /*!< Page number for the next undo
record to purge, page number of the record to purge, page number of the
log header, if dummy record */ log header, if dummy record */
ulint offset; /*!< Page offset for the next undo uint32_t hdr_page_no; /*!< Header page of the undo log where
the next record to purge belongs */
uint16_t offset; /*!< Page offset for the next undo
record to purge, 0 if the dummy record to purge, 0 if the dummy
record */ record */
ulint hdr_page_no; /*!< Header page of the undo log where uint16_t hdr_offset; /*!< Header byte offset on the page */
the next record to purge belongs */
ulint hdr_offset; /*!< Header byte offset on the page */
TrxUndoRsegsIterator TrxUndoRsegsIterator

View File

@ -36,7 +36,7 @@ Created 3/26/1996 Heikki Tuuri
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */ @return rollback segment header, page x-latched */
UNIV_INLINE UNIV_INLINE
trx_rsegf_t* buf_block_t*
trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr); trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr);
/** Gets a newly created rollback segment header. /** Gets a newly created rollback segment header.
@ -45,29 +45,12 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr);
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */ @return rollback segment header, page x-latched */
UNIV_INLINE UNIV_INLINE
trx_rsegf_t* buf_block_t*
trx_rsegf_get_new( trx_rsegf_get_new(
ulint space, ulint space,
ulint page_no, ulint page_no,
mtr_t* mtr); mtr_t* mtr);
/***************************************************************//**
Sets the file page number of the nth undo log slot. */
UNIV_INLINE
void
trx_rsegf_set_nth_undo(
/*===================*/
trx_rsegf_t* rsegf, /*!< in: rollback segment header */
ulint n, /*!< in: index of slot */
ulint page_no,/*!< in: page number of the undo log segment */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************//**
Looks for a free slot for an undo log segment.
@return slot index or ULINT_UNDEFINED if not found */
UNIV_INLINE
ulint
trx_rsegf_undo_find_free(const trx_rsegf_t* rsegf);
/** Create a rollback segment header. /** Create a rollback segment header.
@param[in,out] space system, undo, or temporary tablespace @param[in,out] space system, undo, or temporary tablespace
@param[in] rseg_id rollback segment identifier @param[in] rseg_id rollback segment identifier
@ -155,10 +138,10 @@ struct trx_rseg_t {
/** Page number of the last not yet purged log header in the history /** Page number of the last not yet purged log header in the history
list; FIL_NULL if all list purged */ list; FIL_NULL if all list purged */
ulint last_page_no; uint32_t last_page_no;
/** Byte offset of the last not yet purged log header */ /** Byte offset of the last not yet purged log header */
ulint last_offset; uint16_t last_offset;
/** trx_t::no * 2 + old_insert of the last not yet purged log */ /** trx_t::no * 2 + old_insert of the last not yet purged log */
trx_id_t last_commit; trx_id_t last_commit;
@ -255,15 +238,13 @@ If no binlog information is present, the first byte is NUL. */
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*/
/** Read the page number of an undo log slot. /** Read the page number of an undo log slot.
@param[in] rsegf rollback segment header @param[in] rseg_header rollback segment header
@param[in] n slot number */ @param[in] n slot number */
inline inline uint32_t trx_rsegf_get_nth_undo(const buf_block_t *rseg_header, ulint n)
uint32_t
trx_rsegf_get_nth_undo(const trx_rsegf_t* rsegf, ulint n)
{ {
ut_ad(n < TRX_RSEG_N_SLOTS); ut_ad(n < TRX_RSEG_N_SLOTS);
return mach_read_from_4(rsegf + TRX_RSEG_UNDO_SLOTS return mach_read_from_4(TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
+ n * TRX_RSEG_SLOT_SIZE); n * TRX_RSEG_SLOT_SIZE + rseg_header->frame);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
@ -273,7 +254,7 @@ trx_rsegf_get_nth_undo(const trx_rsegf_t* rsegf, ulint n)
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void
trx_rseg_update_wsrep_checkpoint( trx_rseg_update_wsrep_checkpoint(
trx_rsegf_t* rseg_header, buf_block_t* rseg_header,
const XID* xid, const XID* xid,
mtr_t* mtr); mtr_t* mtr);
@ -295,7 +276,7 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid);
/** Upgrade a rollback segment header page to MariaDB 10.3 format. /** Upgrade a rollback segment header page to MariaDB 10.3 format.
@param[in,out] rseg_header rollback segment header page @param[in,out] rseg_header rollback segment header page
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr); void trx_rseg_format_upgrade(buf_block_t *rseg_header, mtr_t *mtr);
/** Update the offset information about the end of the binlog entry /** Update the offset information about the end of the binlog entry
which corresponds to the transaction just being committed. which corresponds to the transaction just being committed.
@ -304,8 +285,8 @@ up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header @param[in,out] rseg_header rollback segment header
@param[in] trx committing transaction @param[in] trx committing transaction
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr); mtr_t *mtr);
#include "trx0rseg.ic" #include "trx0rseg.ic"

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -33,7 +33,7 @@ Created 3/26/1996 Heikki Tuuri
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */ @return rollback segment header, page x-latched */
UNIV_INLINE UNIV_INLINE
trx_rsegf_t* buf_block_t*
trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr) trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
{ {
ut_ad(space == fil_system.sys_space || space == fil_system.temp_space ut_ad(space == fil_system.sys_space || space == fil_system.temp_space
@ -44,8 +44,7 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
0, RW_X_LATCH, mtr); 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER); buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
return block;
return TRX_RSEG + block->frame;
} }
/** Gets a newly created rollback segment header. /** Gets a newly created rollback segment header.
@ -54,14 +53,13 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */ @return rollback segment header, page x-latched */
UNIV_INLINE UNIV_INLINE
trx_rsegf_t* buf_block_t*
trx_rsegf_get_new( trx_rsegf_get_new(
ulint space, ulint space,
ulint page_no, ulint page_no,
mtr_t* mtr) mtr_t* mtr)
{ {
buf_block_t* block; buf_block_t* block;
trx_rsegf_t* header;
ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID
|| !srv_was_started); || !srv_was_started);
@ -70,54 +68,5 @@ trx_rsegf_get_new(
block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr); block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
return block;
header = TRX_RSEG + buf_block_get_frame(block);
return(header);
}
/***************************************************************//**
Sets the file page number of the nth undo log slot. */
UNIV_INLINE
void
trx_rsegf_set_nth_undo(
/*===================*/
trx_rsegf_t* rsegf, /*!< in: rollback segment header */
ulint n, /*!< in: index of slot */
ulint page_no,/*!< in: page number of the undo log segment */
mtr_t* mtr) /*!< in: mtr */
{
ut_a(n < TRX_RSEG_N_SLOTS);
mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
page_no, MLOG_4BYTES, mtr);
}
/****************************************************************//**
Looks for a free slot for an undo log segment.
@return slot index or ULINT_UNDEFINED if not found */
UNIV_INLINE
ulint
trx_rsegf_undo_find_free(const trx_rsegf_t* rsegf)
{
ulint i;
ulint page_no;
ulint max_slots = TRX_RSEG_N_SLOTS;
#ifdef UNIV_DEBUG
if (trx_rseg_n_slots_debug) {
max_slots = ut_min(static_cast<ulint>(trx_rseg_n_slots_debug),
static_cast<ulint>(TRX_RSEG_N_SLOTS));
}
#endif
for (i = 0; i < max_slots; i++) {
page_no = trx_rsegf_get_nth_undo(rsegf, i);
if (page_no == FIL_NULL) {
return(i);
}
}
return(ULINT_UNDEFINED);
} }

View File

@ -121,8 +121,6 @@ struct trx_savept_t{
/** File objects */ /** File objects */
/* @{ */ /* @{ */
/** Rollback segment header */
typedef byte trx_rsegf_t;
/** Undo segment header */ /** Undo segment header */
typedef byte trx_usegf_t; typedef byte trx_usegf_t;
/** Undo log header */ /** Undo log header */

View File

@ -46,10 +46,10 @@ UNIV_INLINE
roll_ptr_t roll_ptr_t
trx_undo_build_roll_ptr( trx_undo_build_roll_ptr(
/*====================*/ /*====================*/
ibool is_insert, /*!< in: TRUE if insert undo log */ bool is_insert, /*!< in: TRUE if insert undo log */
ulint rseg_id, /*!< in: rollback segment id */ ulint rseg_id, /*!< in: rollback segment id */
ulint page_no, /*!< in: page number */ uint32_t page_no, /*!< in: page number */
ulint offset); /*!< in: offset of the undo entry within page */ uint16_t offset); /*!< in: offset of the undo entry within page */
/***********************************************************************//** /***********************************************************************//**
Decodes a roll pointer. */ Decodes a roll pointer. */
UNIV_INLINE UNIV_INLINE
@ -57,16 +57,16 @@ void
trx_undo_decode_roll_ptr( trx_undo_decode_roll_ptr(
/*=====================*/ /*=====================*/
roll_ptr_t roll_ptr, /*!< in: roll pointer */ roll_ptr_t roll_ptr, /*!< in: roll pointer */
ibool* is_insert, /*!< out: TRUE if insert undo log */ bool* is_insert, /*!< out: TRUE if insert undo log */
ulint* rseg_id, /*!< out: rollback segment id */ ulint* rseg_id, /*!< out: rollback segment id */
ulint* page_no, /*!< out: page number */ uint32_t* page_no, /*!< out: page number */
ulint* offset); /*!< out: offset of the undo uint16_t* offset); /*!< out: offset of the undo
entry within page */ entry within page */
/***********************************************************************//** /***********************************************************************//**
Returns TRUE if the roll pointer is of the insert type. Determine if DB_ROLL_PTR is of the insert type.
@return TRUE if insert undo log */ @return true if insert */
UNIV_INLINE UNIV_INLINE
ibool bool
trx_undo_roll_ptr_is_insert( trx_undo_roll_ptr_is_insert(
/*========================*/ /*========================*/
roll_ptr_t roll_ptr); /*!< in: roll pointer */ roll_ptr_t roll_ptr); /*!< in: roll pointer */
@ -101,7 +101,7 @@ inline roll_ptr_t trx_read_roll_ptr(const byte* ptr)
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return pointer to page x-latched */ @return pointer to page x-latched */
UNIV_INLINE UNIV_INLINE
page_t* buf_block_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr); trx_undo_page_get(const page_id_t page_id, mtr_t* mtr);
/** Gets an undo log page and s-latches it. /** Gets an undo log page and s-latches it.
@ -109,56 +109,52 @@ trx_undo_page_get(const page_id_t page_id, mtr_t* mtr);
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return pointer to page s-latched */ @return pointer to page s-latched */
UNIV_INLINE UNIV_INLINE
page_t* buf_block_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr); trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr);
/******************************************************************//** /** Get the next record in an undo log.
Returns the next undo log record on the page in the specified log, or @param[in] undo_page undo log page
NULL if none exists. @param[in] rec undo record offset in the page
@return pointer to record, NULL if none */ @param[in] page_no undo log header page number
UNIV_INLINE @param[in] offset undo log header offset on page
trx_undo_rec_t* @return undo log record, the page latched, NULL if none */
trx_undo_page_get_next_rec( inline trx_undo_rec_t*
/*=======================*/ trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec,
trx_undo_rec_t* rec, /*!< in: undo log record */ uint32_t page_no, uint16_t offset);
ulint page_no,/*!< in: undo log header page number */ /** Get the previous record in an undo log.
ulint offset);/*!< in: undo log header offset on page */ @param[in,out] block undo log page
/***********************************************************************//** @param[in] rec undo record offset in the page
Gets the previous record in an undo log. @param[in] page_no undo log header page number
@return undo log record, the page s-latched, NULL if none */ @param[in] offset undo log header offset on page
trx_undo_rec_t* @param[in] shared latching mode: true=RW_S_LATCH, false=RW_X_LATCH
trx_undo_get_prev_rec( @param[in,out] mtr mini-transaction
/*==================*/
trx_undo_rec_t* rec, /*!< in: undo record */
ulint page_no,/*!< in: undo log header page number */
ulint offset, /*!< in: undo log header offset on page */
bool shared, /*!< in: true=S-latch, false=X-latch */
mtr_t* mtr); /*!< in: mtr */
/***********************************************************************//**
Gets the next record in an undo log.
@return undo log record, the page s-latched, NULL if none */
trx_undo_rec_t*
trx_undo_get_next_rec(
/*==================*/
trx_undo_rec_t* rec, /*!< in: undo record */
ulint page_no,/*!< in: undo log header page number */
ulint offset, /*!< in: undo log header offset on page */
mtr_t* mtr); /*!< in: mtr */
/** Gets the first record in an undo log.
@param[in] space undo log header space
@param[in] page_no undo log header page number
@param[in] offset undo log header offset on page
@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */ @return undo log record, the page latched, NULL if none */
trx_undo_rec_t* trx_undo_rec_t*
trx_undo_get_first_rec( trx_undo_get_prev_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
fil_space_t* space, uint16_t offset, bool shared, mtr_t *mtr);
ulint page_no, /** Get the next record in an undo log.
ulint offset, @param[in,out] block undo log page
ulint mode, @param[in] rec undo record offset in the page
mtr_t* mtr); @param[in] page_no undo log header page number
@param[in] offset undo log header offset on page
@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
trx_undo_get_next_rec(buf_block_t *&block, uint16_t rec, uint32_t page_no,
uint16_t offset, mtr_t *mtr);
/** Get the first record in an undo log.
@param[in] space undo log header space
@param[in] page_no undo log header page number
@param[in] offset undo log header offset on page
@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
@param[out] block undo log page
@param[in,out] mtr mini-transaction
@return undo log record, the page latched, NULL if none */
trx_undo_rec_t*
trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no,
uint16_t offset, ulint mode, buf_block_t*& block,
mtr_t *mtr);
/** Allocate an undo log page. /** Allocate an undo log page.
@param[in,out] undo undo log @param[in,out] undo undo log
@ -193,8 +189,8 @@ freed, but emptied, if all the records there are below the limit.
void void
trx_undo_truncate_start( trx_undo_truncate_start(
trx_rseg_t* rseg, trx_rseg_t* rseg,
ulint hdr_page_no, uint32_t hdr_page_no,
ulint hdr_offset, uint16_t hdr_offset,
undo_no_t limit); undo_no_t limit);
/** Mark that an undo log header belongs to a data dictionary transaction. /** Mark that an undo log header belongs to a data dictionary transaction.
@param[in] trx dictionary transaction @param[in] trx dictionary transaction
@ -227,7 +223,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
/******************************************************************//** /******************************************************************//**
Sets the state of the undo log segment at a transaction finish. Sets the state of the undo log segment at a transaction finish.
@return undo log segment header page, x-latched */ @return undo log segment header page, x-latched */
page_t* buf_block_t*
trx_undo_set_state_at_finish( trx_undo_set_state_at_finish(
/*=========================*/ /*=========================*/
trx_undo_t* undo, /*!< in: undo log memory copy */ trx_undo_t* undo, /*!< in: undo log memory copy */
@ -237,14 +233,10 @@ trx_undo_set_state_at_finish(
@param[in,out] trx transaction @param[in,out] trx transaction
@param[in,out] undo undo log @param[in,out] undo undo log
@param[in] rollback false=XA PREPARE, true=XA ROLLBACK @param[in] rollback false=XA PREPARE, true=XA ROLLBACK
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction */
@return undo log segment header page, x-latched */ void trx_undo_set_state_at_prepare(trx_t *trx, trx_undo_t *undo, bool rollback,
page_t* mtr_t *mtr)
trx_undo_set_state_at_prepare( MY_ATTRIBUTE((nonnull));
trx_t* trx,
trx_undo_t* undo,
bool rollback,
mtr_t* mtr);
/** Free an old insert or temporary undo log after commit or rollback. /** Free an old insert or temporary undo log after commit or rollback.
The information is not needed after a commit or rollback, therefore The information is not needed after a commit or rollback, therefore
@ -281,14 +273,14 @@ trx_undo_parse_page_header_reuse(
/** Parse the redo log entry of an undo log page header create. /** Parse the redo log entry of an undo log page header create.
@param[in] ptr redo log record @param[in] ptr redo log record
@param[in] end_ptr end of log buffer @param[in] end_ptr end of log buffer
@param[in,out] page page frame or NULL @param[in,out] block page frame or NULL
@param[in,out] mtr mini-transaction or NULL @param[in,out] mtr mini-transaction or NULL
@return end of log record or NULL */ @return end of log record or NULL */
byte* byte*
trx_undo_parse_page_header( trx_undo_parse_page_header(
const byte* ptr, const byte* ptr,
const byte* end_ptr, const byte* end_ptr,
page_t* page, buf_block_t* block,
mtr_t* mtr); mtr_t* mtr);
/** Read an undo log when starting up the database. /** Read an undo log when starting up the database.
@param[in,out] rseg rollback segment @param[in,out] rseg rollback segment
@ -296,9 +288,9 @@ trx_undo_parse_page_header(
@param[in] page_no undo log segment page number @param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID @param[in,out] max_trx_id the largest observed transaction ID
@return size of the undo log in pages */ @return size of the undo log in pages */
ulint uint32_t
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no, trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t& max_trx_id); trx_id_t &max_trx_id);
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */
@ -340,20 +332,20 @@ struct trx_undo_t {
id */ id */
trx_rseg_t* rseg; /*!< rseg where the undo log belongs */ trx_rseg_t* rseg; /*!< rseg where the undo log belongs */
/*-----------------------------*/ /*-----------------------------*/
ulint hdr_page_no; /*!< page number of the header page in uint32_t hdr_page_no; /*!< page number of the header page in
the undo log */ the undo log */
ulint hdr_offset; /*!< header offset of the undo log on uint32_t last_page_no; /*!< page number of the last page in the
the page */
ulint last_page_no; /*!< page number of the last page in the
undo log; this may differ from undo log; this may differ from
top_page_no during a rollback */ top_page_no during a rollback */
ulint size; /*!< current size in pages */ uint16_t hdr_offset; /*!< header offset of the undo log on
the page */
uint32_t size; /*!< current size in pages */
/*-----------------------------*/ /*-----------------------------*/
ulint top_page_no; /*!< page number where the latest undo uint32_t top_page_no; /*!< page number where the latest undo
log record was catenated; during log record was catenated; during
rollback the page from which the latest rollback the page from which the latest
undo record was chosen */ undo record was chosen */
ulint top_offset; /*!< offset of the latest undo record, uint16_t top_offset; /*!< offset of the latest undo record,
i.e., the topmost element in the undo i.e., the topmost element in the undo
log if we think of it as a stack */ log if we think of it as a stack */
undo_no_t top_undo_no; /*!< undo number of the latest record undo_no_t top_undo_no; /*!< undo number of the latest record

View File

@ -34,22 +34,17 @@ UNIV_INLINE
roll_ptr_t roll_ptr_t
trx_undo_build_roll_ptr( trx_undo_build_roll_ptr(
/*====================*/ /*====================*/
ibool is_insert, /*!< in: TRUE if insert undo log */ bool is_insert, /*!< in: TRUE if insert undo log */
ulint rseg_id, /*!< in: rollback segment id */ ulint rseg_id, /*!< in: rollback segment id */
ulint page_no, /*!< in: page number */ uint32_t page_no, /*!< in: page number */
ulint offset) /*!< in: offset of the undo entry within page */ uint16_t offset) /*!< in: offset of the undo entry within page */
{ {
roll_ptr_t roll_ptr; compile_time_assert(DATA_ROLL_PTR_LEN == 7);
compile_time_assert(DATA_ROLL_PTR_LEN == 7); ut_ad(rseg_id < TRX_SYS_N_RSEGS);
ut_ad(is_insert == 0 || is_insert == 1);
ut_ad(rseg_id < TRX_SYS_N_RSEGS);
ut_ad(offset < 65536);
roll_ptr = (roll_ptr_t) is_insert << ROLL_PTR_INSERT_FLAG_POS return roll_ptr_t{is_insert} << ROLL_PTR_INSERT_FLAG_POS |
| (roll_ptr_t) rseg_id << ROLL_PTR_RSEG_ID_POS roll_ptr_t{rseg_id} << ROLL_PTR_RSEG_ID_POS |
| (roll_ptr_t) page_no << ROLL_PTR_PAGE_POS roll_ptr_t{page_no} << ROLL_PTR_PAGE_POS | offset;
| offset;
return(roll_ptr);
} }
/***********************************************************************//** /***********************************************************************//**
@ -59,35 +54,32 @@ void
trx_undo_decode_roll_ptr( trx_undo_decode_roll_ptr(
/*=====================*/ /*=====================*/
roll_ptr_t roll_ptr, /*!< in: roll pointer */ roll_ptr_t roll_ptr, /*!< in: roll pointer */
ibool* is_insert, /*!< out: TRUE if insert undo log */ bool* is_insert, /*!< out: TRUE if insert undo log */
ulint* rseg_id, /*!< out: rollback segment id */ ulint* rseg_id, /*!< out: rollback segment id */
ulint* page_no, /*!< out: page number */ uint32_t* page_no, /*!< out: page number */
ulint* offset) /*!< out: offset of the undo uint16_t* offset) /*!< out: offset of the undo
entry within page */ entry within page */
{ {
compile_time_assert(DATA_ROLL_PTR_LEN == 7); compile_time_assert(DATA_ROLL_PTR_LEN == 7);
ut_ad(roll_ptr < (1ULL << 56)); ut_ad(roll_ptr < (1ULL << 56));
*offset = (ulint) roll_ptr & 0xFFFF; *offset= static_cast<uint16_t>(roll_ptr);
roll_ptr >>= 16; *page_no= static_cast<uint32_t>(roll_ptr >> 16);
*page_no = (ulint) roll_ptr & 0xFFFFFFFF; *rseg_id= static_cast<ulint>(roll_ptr >> 48 & 0x7F);
roll_ptr >>= 32; *is_insert= static_cast<bool>(roll_ptr >> 55);
*rseg_id = (ulint) roll_ptr & 0x7F;
roll_ptr >>= 7;
*is_insert = (ibool) roll_ptr; /* TRUE==1 */
} }
/***********************************************************************//** /***********************************************************************//**
Returns TRUE if the roll pointer is of the insert type. Determine if DB_ROLL_PTR is of the insert type.
@return TRUE if insert undo log */ @return true if insert */
UNIV_INLINE UNIV_INLINE
ibool bool
trx_undo_roll_ptr_is_insert( trx_undo_roll_ptr_is_insert(
/*========================*/ /*========================*/
roll_ptr_t roll_ptr) /*!< in: roll pointer */ roll_ptr_t roll_ptr) /*!< in: roll pointer */
{ {
compile_time_assert(DATA_ROLL_PTR_LEN == 7); compile_time_assert(DATA_ROLL_PTR_LEN == 7);
ut_ad(roll_ptr < (1ULL << (ROLL_PTR_INSERT_FLAG_POS + 1))); ut_ad(roll_ptr < (1ULL << (ROLL_PTR_INSERT_FLAG_POS + 1)));
return((ibool) (roll_ptr >> ROLL_PTR_INSERT_FLAG_POS)); return static_cast<bool>(roll_ptr >> ROLL_PTR_INSERT_FLAG_POS);
} }
/***********************************************************************//** /***********************************************************************//**
@ -108,14 +100,13 @@ trx_undo_trx_id_is_insert(
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return pointer to page x-latched */ @return pointer to page x-latched */
UNIV_INLINE UNIV_INLINE
page_t* buf_block_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr) trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
{ {
buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr); buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
return block;
return(buf_block_get_frame(block));
} }
/** Gets an undo log page and s-latches it. /** Gets an undo log page and s-latches it.
@ -123,14 +114,14 @@ trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
@param[in,out] mtr mini-transaction @param[in,out] mtr mini-transaction
@return pointer to page s-latched */ @return pointer to page s-latched */
UNIV_INLINE UNIV_INLINE
page_t* buf_block_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr) trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
{ {
buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr); buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
return(buf_block_get_frame(block)); return block;
} }
/** Determine the end offset of undo log records of an undo log page. /** Determine the end offset of undo log records of an undo log page.
@ -139,46 +130,29 @@ trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
@param[in] offset undo log header offset @param[in] offset undo log header offset
@return end offset */ @return end offset */
inline inline
uint16_t uint16_t trx_undo_page_get_end(const buf_block_t *undo_page, uint32_t page_no,
trx_undo_page_get_end(const page_t* undo_page, ulint page_no, ulint offset) uint16_t offset)
{ {
if (page_no == page_get_page_no(undo_page)) { if (page_no == undo_page->page.id.page_no())
if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG if (uint16_t end = mach_read_from_2(TRX_UNDO_NEXT_LOG + offset +
+ offset + undo_page)) { undo_page->frame))
return end; return end;
}
}
return mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE return mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
+ undo_page); undo_page->frame);
} }
/******************************************************************//** /** Get the next record in an undo log.
Returns the next undo log record on the page in the specified log, or @param[in] undo_page undo log page
NULL if none exists. @param[in] rec undo record offset in the page
@return pointer to record, NULL if none */ @param[in] page_no undo log header page number
UNIV_INLINE @param[in] offset undo log header offset on page
trx_undo_rec_t* @return undo log record, the page latched, NULL if none */
trx_undo_page_get_next_rec( inline trx_undo_rec_t*
/*=======================*/ trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec,
trx_undo_rec_t* rec, /*!< in: undo log record */ uint32_t page_no, uint16_t offset)
ulint page_no,/*!< in: undo log header page number */
ulint offset) /*!< in: undo log header offset on page */
{ {
page_t* undo_page; uint16_t end= trx_undo_page_get_end(undo_page, page_no, offset);
ulint end; uint16_t next= mach_read_from_2(undo_page->frame + rec);
ulint next; return next == end ? nullptr : undo_page->frame + next;
undo_page = (page_t*) ut_align_down(rec, srv_page_size);
end = trx_undo_page_get_end(undo_page, page_no, offset);
next = mach_read_from_2(rec);
if (next == end) {
return(NULL);
}
return(undo_page + next);
} }

View File

@ -62,7 +62,7 @@ General philosophy of InnoDB redo-logs:
through mtr, which in mtr_commit() writes log records through mtr, which in mtr_commit() writes log records
to the InnoDB redo log. to the InnoDB redo log.
2) Normally these changes are performed using a mlog_write_ulint() 2) Normally these changes are performed using a mlog_write()
or similar function. or similar function.
3) In some page level operations only a code number of a 3) In some page level operations only a code number of a

View File

@ -1619,7 +1619,7 @@ recv_parse_or_apply_log_rec_body(
break; break;
case MLOG_UNDO_HDR_CREATE: case MLOG_UNDO_HDR_CREATE:
ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG); ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG);
ptr = trx_undo_parse_page_header(ptr, end_ptr, page, mtr); ptr = trx_undo_parse_page_header(ptr, end_ptr, block, mtr);
break; break;
case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK: case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK:
ut_ad(!page || fil_page_type_is_index(page_type)); ut_ad(!page || fil_page_type_is_index(page_type));

View File

@ -90,7 +90,7 @@ mlog_parse_initial_log_record(
} }
/********************************************************//** /********************************************************//**
Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset. Parses a log record written by mtr_t::write(), mlog_memset().
@return parsed record end, NULL if not a complete record or a corrupt record */ @return parsed record end, NULL if not a complete record or a corrupt record */
const byte* const byte*
mlog_parse_nbytes( mlog_parse_nbytes(
@ -213,80 +213,58 @@ mlog_parse_nbytes(
return const_cast<byte*>(ptr); return const_cast<byte*>(ptr);
} }
/********************************************************//** /**
Writes 1, 2 or 4 bytes to a file page. Writes the corresponding log Write a log record for writing 1, 2, 4, or 8 bytes.
record to the mini-transaction log if mtr is not NULL. */ @param[in] block file page
void @param[in,out] ptr pointer in file page
mlog_write_ulint( @param[in] l number of bytes to write
/*=============*/ @param[in,out] log_ptr log record buffer
byte* ptr, /*!< in: pointer where to write */ @param[in,out] mtr mini-transaction */
ulint val, /*!< in: value to write */ static byte *
mlog_id_t type, /*!< in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */ mlog_log_write_low(const buf_block_t &block, byte *ptr, mlog_id_t l,
mtr_t* mtr) /*!< in: mini-transaction handle */ byte *log_ptr, mtr_t &mtr)
{ {
switch (type) { ut_ad(block.page.state == BUF_BLOCK_FILE_PAGE);
case MLOG_1BYTE: ut_ad(ptr >= block.frame + FIL_PAGE_OFFSET);
mach_write_to_1(ptr, val); ut_ad(ptr + unsigned(l) <= &block.frame[srv_page_size - FIL_PAGE_DATA_END]);
break; log_ptr= mlog_write_initial_log_record_low(l,
case MLOG_2BYTES: block.page.id.space(),
mach_write_to_2(ptr, val); block.page.id.page_no(),
break; log_ptr, &mtr);
case MLOG_4BYTES: mach_write_to_2(log_ptr, page_offset(ptr));
mach_write_to_4(ptr, val); return log_ptr + 2;
break;
default:
ut_error;
}
if (mtr != 0) {
byte* log_ptr = mlog_open(mtr, 11 + 2 + 5);
/* If no logging is requested, we may return now */
if (log_ptr != 0) {
log_ptr = mlog_write_initial_log_record_fast(
ptr, type, log_ptr, mtr);
mach_write_to_2(log_ptr, page_offset(ptr));
log_ptr += 2;
log_ptr += mach_write_compressed(log_ptr, val);
mlog_close(mtr, log_ptr);
}
}
} }
/********************************************************//** /**
Writes 8 bytes to a file page. Writes the corresponding log Write a log record for writing 1, 2, or 4 bytes.
record to the mini-transaction log, only if mtr is not NULL */ @param[in] block file page
void @param[in,out] ptr pointer in file page
mlog_write_ull( @param[in] l number of bytes to write
/*===========*/ @param[in,out] log_ptr log record buffer
byte* ptr, /*!< in: pointer where to write */ @param[in] val value to write */
ib_uint64_t val, /*!< in: value to write */ void mtr_t::log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
mtr_t* mtr) /*!< in: mini-transaction handle */ byte *log_ptr, uint32_t val)
{ {
mach_write_to_8(ptr, val); ut_ad(l == MLOG_1BYTE || l == MLOG_2BYTES || l == MLOG_4BYTES);
log_ptr= mlog_log_write_low(block, ptr, l, log_ptr, *this);
log_ptr+= mach_write_compressed(log_ptr, val);
mlog_close(this, log_ptr);
}
if (mtr != 0) { /**
byte* log_ptr = mlog_open(mtr, 11 + 2 + 9); Write a log record for writing 8 bytes.
@param[in] block file page
/* If no logging is requested, we may return now */ @param[in,out] ptr pointer in file page
if (log_ptr != 0) { @param[in] l number of bytes to write
@param[in,out] log_ptr log record buffer
log_ptr = mlog_write_initial_log_record_fast( @param[in] val value to write */
ptr, MLOG_8BYTES, log_ptr, mtr); void mtr_t::log_write(const buf_block_t &block, byte *ptr, mlog_id_t l,
byte *log_ptr, uint64_t val)
mach_write_to_2(log_ptr, page_offset(ptr)); {
log_ptr += 2; ut_ad(l == MLOG_8BYTES);
log_ptr= mlog_log_write_low(block, ptr, l, log_ptr, *this);
log_ptr += mach_u64_write_compressed(log_ptr, val); log_ptr+= mach_u64_write_compressed(log_ptr, val);
mlog_close(this, log_ptr);
mlog_close(mtr, log_ptr);
}
}
} }
/********************************************************//** /********************************************************//**
@ -402,7 +380,7 @@ mlog_parse_string(
@param[in] val the data byte to write @param[in] val the data byte to write
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void
mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr) mlog_memset(const buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr)
{ {
ut_ad(len); ut_ad(len);
ut_ad(ofs <= ulint(srv_page_size)); ut_ad(ofs <= ulint(srv_page_size));

View File

@ -196,24 +196,19 @@ page_set_max_trx_id(
trx_id_t trx_id, /*!< in: transaction id */ trx_id_t trx_id, /*!< in: transaction id */
mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */ mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */
{ {
page_t* page = buf_block_get_frame(block); ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); static_assert((PAGE_HEADER + PAGE_MAX_TRX_ID) % 8 == 0, "alignment");
byte *max_trx_id= static_cast<byte*>(MY_ASSUME_ALIGNED(PAGE_MAX_TRX_ID
+ PAGE_HEADER
+ block->frame, 8));
/* It is not necessary to write this change to the redo log, as if (UNIV_LIKELY_NULL(page_zip))
during a database recovery we assume that the max trx id of every {
page is the maximum trx id assigned before the crash. */ mach_write_to_8(max_trx_id, trx_id);
page_zip_write_header(page_zip, max_trx_id, 8, mtr);
if (page_zip) { }
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id); else
page_zip_write_header(page_zip, mtr->write<8>(*block, max_trx_id, trx_id);
page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
8, mtr);
} else if (mtr) {
mlog_write_ull(page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
trx_id, mtr);
} else {
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
}
} }
/** Persist the AUTO_INCREMENT value on a clustered index root page. /** Persist the AUTO_INCREMENT value on a clustered index root page.
@ -227,27 +222,23 @@ page_set_max_trx_id(
void void
page_set_autoinc( page_set_autoinc(
buf_block_t* block, buf_block_t* block,
const dict_index_t* index MY_ATTRIBUTE((unused)),
ib_uint64_t autoinc, ib_uint64_t autoinc,
mtr_t* mtr, mtr_t* mtr,
bool reset) bool reset)
{ {
ut_ad(mtr_memo_contains_flagged( ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX |
mtr, block, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); MTR_MEMO_PAGE_SX_FIX));
ut_ad(index->is_primary());
ut_ad(index->page == block->page.id.page_no());
ut_ad(index->table->space_id == block->page.id.space());
byte* field = PAGE_HEADER + PAGE_ROOT_AUTO_INC byte *field= PAGE_HEADER + PAGE_ROOT_AUTO_INC + block->frame;
+ buf_block_get_frame(block); if (!reset && mach_read_from_8(field) >= autoinc)
if (!reset && mach_read_from_8(field) >= autoinc) { /* nothing to update */;
/* nothing to update */ else if (page_zip_des_t* page_zip = buf_block_get_page_zip(block))
} else if (page_zip_des_t* page_zip = buf_block_get_page_zip(block)) { {
mach_write_to_8(field, autoinc); mach_write_to_8(field, autoinc);
page_zip_write_header(page_zip, field, 8, mtr); page_zip_write_header(page_zip, field, 8, mtr);
} else { }
mlog_write_ull(field, autoinc, mtr); else
} mtr->write<8,mtr_t::OPT>(*block, field, autoinc);
} }
/** The page infimum and supremum of an empty page in ROW_FORMAT=REDUNDANT */ /** The page infimum and supremum of an empty page in ROW_FORMAT=REDUNDANT */
@ -483,12 +474,12 @@ page_create_empty(
page_header_get_field(page, PAGE_LEVEL), page_header_get_field(page, PAGE_LEVEL),
max_trx_id, mtr); max_trx_id, mtr);
} else { } else {
page_create(block, mtr, page_is_comp(page), page_create(block, mtr, index->table->not_redundant(),
dict_index_is_spatial(index)); index->is_spatial());
if (max_trx_id) { if (max_trx_id) {
mlog_write_ull(PAGE_HEADER + PAGE_MAX_TRX_ID + page, mtr->write<8>(*block, PAGE_HEADER + PAGE_MAX_TRX_ID
max_trx_id, mtr); + block->frame, max_trx_id);
} }
} }
} }
@ -581,12 +572,13 @@ page_copy_rec_list_end(
{ {
page_t* new_page = buf_block_get_frame(new_block); page_t* new_page = buf_block_get_frame(new_block);
page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block); page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block);
page_t* page = page_align(rec); page_t* page = block->frame;
rec_t* ret = page_rec_get_next( rec_t* ret = page_rec_get_next(
page_get_infimum_rec(new_page)); page_get_infimum_rec(new_page));
ulint num_moved = 0; ulint num_moved = 0;
rtr_rec_move_t* rec_move = NULL; rtr_rec_move_t* rec_move = NULL;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ut_ad(page_align(rec) == page);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
if (new_page_zip) { if (new_page_zip) {
@ -810,8 +802,9 @@ page_copy_rec_list_start(
for MVCC. */ for MVCC. */
if (is_leaf && dict_index_is_sec_or_ibuf(index) if (is_leaf && dict_index_is_sec_or_ibuf(index)
&& !index->table->is_temporary()) { && !index->table->is_temporary()) {
page_update_max_trx_id(new_block, NULL, page_update_max_trx_id(new_block,
page_get_max_trx_id(page_align(rec)), new_page_zip,
page_get_max_trx_id(block->frame),
mtr); mtr);
} }
@ -979,7 +972,6 @@ page_delete_rec_list_end(
rec_t* prev_rec; rec_t* prev_rec;
ulint n_owned; ulint n_owned;
page_zip_des_t* page_zip = buf_block_get_page_zip(block); page_zip_des_t* page_zip = buf_block_get_page_zip(block);
page_t* page = page_align(rec);
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_; ulint* offsets = offsets_;
@ -987,8 +979,9 @@ page_delete_rec_list_end(
ut_ad(size == ULINT_UNDEFINED || size < srv_page_size); ut_ad(size == ULINT_UNDEFINED || size < srv_page_size);
ut_ad(!page_zip || page_rec_is_comp(rec)); ut_ad(!page_zip || page_rec_is_comp(rec));
ut_ad(page_align(rec) == block->frame);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index)); ut_a(!page_zip || page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
if (page_rec_is_supremum(rec)) { if (page_rec_is_supremum(rec)) {
@ -1006,19 +999,21 @@ page_delete_rec_list_end(
only be executed when applying redo log that was only be executed when applying redo log that was
generated by an older version of MySQL. */ generated by an older version of MySQL. */
} else if (page_rec_is_infimum(rec) } else if (page_rec_is_infimum(rec)
|| n_recs == page_get_n_recs(page)) { || n_recs == page_get_n_recs(block->frame)) {
delete_all: delete_all:
/* We are deleting all records. */ /* We are deleting all records. */
page_create_empty(block, index, mtr); page_create_empty(block, index, mtr);
return; return;
} else if (page_is_comp(page)) { } else if (page_is_comp(block->frame)) {
if (page_rec_get_next_low(page + PAGE_NEW_INFIMUM, 1) == rec) { if (page_rec_get_next_low(block->frame + PAGE_NEW_INFIMUM, 1)
== rec) {
/* We are deleting everything from the first /* We are deleting everything from the first
user record onwards. */ user record onwards. */
goto delete_all; goto delete_all;
} }
} else { } else {
if (page_rec_get_next_low(page + PAGE_OLD_INFIMUM, 0) == rec) { if (page_rec_get_next_low(block->frame + PAGE_OLD_INFIMUM, 0)
== rec) {
/* We are deleting everything from the first /* We are deleting everything from the first
user record onwards. */ user record onwards. */
goto delete_all; goto delete_all;
@ -1028,23 +1023,23 @@ page_delete_rec_list_end(
/* Reset the last insert info in the page header and increment /* Reset the last insert info in the page header and increment
the modify clock for the frame */ the modify clock for the frame */
page_header_set_ptr(page, page_zip, PAGE_LAST_INSERT, NULL); page_header_set_ptr(block->frame, page_zip, PAGE_LAST_INSERT, NULL);
/* The page gets invalid for optimistic searches: increment the /* The page gets invalid for optimistic searches: increment the
frame modify clock */ frame modify clock */
buf_block_modify_clock_inc(block); buf_block_modify_clock_inc(block);
page_delete_rec_list_write_log(rec, index, page_is_comp(page) page_delete_rec_list_write_log(rec, index, page_is_comp(block->frame)
? MLOG_COMP_LIST_END_DELETE ? MLOG_COMP_LIST_END_DELETE
: MLOG_LIST_END_DELETE, mtr); : MLOG_LIST_END_DELETE, mtr);
const bool is_leaf = page_is_leaf(page); const bool is_leaf = page_is_leaf(block->frame);
if (page_zip) { if (page_zip) {
mtr_log_t log_mode; mtr_log_t log_mode;
ut_a(page_is_comp(page)); ut_ad(page_is_comp(block->frame));
/* Individual deletes are not logged */ /* Individual deletes are not logged */
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE); log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
@ -1057,7 +1052,7 @@ page_delete_rec_list_end(
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
rec = rec_get_next_ptr(rec, TRUE); rec = rec_get_next_ptr(rec, TRUE);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
ut_a(page_zip_validate(page_zip, page, index)); ut_a(page_zip_validate(page_zip, block->frame, index));
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
page_cur_delete_rec(&cur, index, offsets, mtr); page_cur_delete_rec(&cur, index, offsets, mtr);
} while (page_offset(rec) != PAGE_NEW_SUPREMUM); } while (page_offset(rec) != PAGE_NEW_SUPREMUM);
@ -1074,7 +1069,7 @@ page_delete_rec_list_end(
prev_rec = page_rec_get_prev(rec); prev_rec = page_rec_get_prev(rec);
last_rec = page_rec_get_prev(page_get_supremum_rec(page)); last_rec = page_rec_get_prev(page_get_supremum_rec(block->frame));
bool scrub = srv_immediate_scrub_data_uncompressed; bool scrub = srv_immediate_scrub_data_uncompressed;
if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED) || if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED) ||
@ -1090,7 +1085,7 @@ page_delete_rec_list_end(
is_leaf, is_leaf,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
s = rec_offs_size(offsets); s = rec_offs_size(offsets);
ut_ad(ulint(rec2 - page) + s ut_ad(ulint(rec2 - block->frame) + s
- rec_offs_extra_size(offsets) - rec_offs_extra_size(offsets)
< srv_page_size); < srv_page_size);
ut_ad(size + s < srv_page_size); ut_ad(size + s < srv_page_size);
@ -1116,7 +1111,7 @@ page_delete_rec_list_end(
of the records owned by the supremum record, as it is allowed to be of the records owned by the supremum record, as it is allowed to be
less than PAGE_DIR_SLOT_MIN_N_OWNED */ less than PAGE_DIR_SLOT_MIN_N_OWNED */
if (page_is_comp(page)) { if (page_is_comp(block->frame)) {
rec_t* rec2 = rec; rec_t* rec2 = rec;
ulint count = 0; ulint count = 0;
@ -1131,7 +1126,7 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_new(rec2) - count; n_owned = rec_get_n_owned_new(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2); slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0); ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index); slot = page_dir_get_nth_slot(block->frame, slot_index);
} else { } else {
rec_t* rec2 = rec; rec_t* rec2 = rec;
ulint count = 0; ulint count = 0;
@ -1147,28 +1142,30 @@ page_delete_rec_list_end(
n_owned = rec_get_n_owned_old(rec2) - count; n_owned = rec_get_n_owned_old(rec2) - count;
slot_index = page_dir_find_owner_slot(rec2); slot_index = page_dir_find_owner_slot(rec2);
ut_ad(slot_index > 0); ut_ad(slot_index > 0);
slot = page_dir_get_nth_slot(page, slot_index); slot = page_dir_get_nth_slot(block->frame, slot_index);
} }
page_dir_slot_set_rec(slot, page_get_supremum_rec(page)); page_dir_slot_set_rec(slot, page_get_supremum_rec(block->frame));
page_dir_slot_set_n_owned(slot, NULL, n_owned); page_dir_slot_set_n_owned(slot, NULL, n_owned);
page_dir_set_n_slots(page, NULL, slot_index + 1); page_dir_set_n_slots(block->frame, NULL, slot_index + 1);
/* Remove the record chain segment from the record chain */ /* Remove the record chain segment from the record chain */
page_rec_set_next(prev_rec, page_get_supremum_rec(page)); page_rec_set_next(prev_rec, page_get_supremum_rec(block->frame));
/* Catenate the deleted chain segment to the page free list */ /* Catenate the deleted chain segment to the page free list */
page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE)); page_rec_set_next(last_rec, page_header_get_ptr(block->frame,
page_header_set_ptr(page, NULL, PAGE_FREE, rec); PAGE_FREE));
page_header_set_ptr(block->frame, NULL, PAGE_FREE, rec);
page_header_set_field(page, NULL, PAGE_GARBAGE, size page_header_set_field(block->frame, NULL, PAGE_GARBAGE, size
+ page_header_get_field(page, PAGE_GARBAGE)); + page_header_get_field(block->frame,
PAGE_GARBAGE));
ut_ad(page_get_n_recs(page) > n_recs); ut_ad(page_get_n_recs(block->frame) > n_recs);
page_header_set_field(page, NULL, PAGE_N_RECS, page_header_set_field(block->frame, NULL, PAGE_N_RECS,
(ulint)(page_get_n_recs(page) - n_recs)); ulint{page_get_n_recs(block->frame) - n_recs});
} }
/*************************************************************//** /*************************************************************//**

View File

@ -924,12 +924,11 @@ row_purge_upd_exist_or_extern_func(
if (dfield_is_ext(&ufield->new_val)) { if (dfield_is_ext(&ufield->new_val)) {
trx_rseg_t* rseg; trx_rseg_t* rseg;
buf_block_t* block; buf_block_t* block;
ulint internal_offset;
byte* data_field; byte* data_field;
ibool is_insert; bool is_insert;
ulint rseg_id; ulint rseg_id;
ulint page_no; uint32_t page_no;
ulint offset; uint16_t offset;
/* We use the fact that new_val points to /* We use the fact that new_val points to
undo_rec and get thus the offset of undo_rec and get thus the offset of
@ -937,7 +936,7 @@ row_purge_upd_exist_or_extern_func(
can calculate from node->roll_ptr the file can calculate from node->roll_ptr the file
address of the new_val data */ address of the new_val data */
internal_offset = ulint( const uint16_t internal_offset = uint16_t(
static_cast<const byte*> static_cast<const byte*>
(dfield_get_data(&ufield->new_val)) (dfield_get_data(&ufield->new_val))
- undo_rec); - undo_rec);
@ -989,7 +988,7 @@ row_purge_upd_exist_or_extern_func(
index, index,
data_field + dfield_get_len(&ufield->new_val) data_field + dfield_get_len(&ufield->new_val)
- BTR_EXTERN_FIELD_REF_SIZE, - BTR_EXTERN_FIELD_REF_SIZE,
NULL, NULL, NULL, 0, false, &mtr); NULL, NULL, block, 0, false, &mtr);
mtr.commit(); mtr.commit();
} }
} }

View File

@ -208,20 +208,22 @@ row_undo_ins_remove_clust_rec(
/* When rolling back the very first instant ADD COLUMN /* When rolling back the very first instant ADD COLUMN
operation, reset the root page to the basic state. */ operation, reset the root page to the basic state. */
ut_ad(!index->table->is_temporary()); ut_ad(!index->table->is_temporary());
if (page_t* root = btr_root_get(index, &mtr)) { if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH,
byte* page_type = root + FIL_PAGE_TYPE; &mtr)) {
byte* page_type = root->frame + FIL_PAGE_TYPE;
ut_ad(mach_read_from_2(page_type) ut_ad(mach_read_from_2(page_type)
== FIL_PAGE_TYPE_INSTANT == FIL_PAGE_TYPE_INSTANT
|| mach_read_from_2(page_type) || mach_read_from_2(page_type)
== FIL_PAGE_INDEX); == FIL_PAGE_INDEX);
mlog_write_ulint(page_type, FIL_PAGE_INDEX, mtr.write<2,mtr_t::OPT>(*root, page_type,
MLOG_2BYTES, &mtr); FIL_PAGE_INDEX);
byte* instant = PAGE_INSTANT + PAGE_HEADER + root; byte* instant = PAGE_INSTANT + PAGE_HEADER
mlog_write_ulint(instant, + root->frame;
page_ptr_get_direction(instant + 1), mtr.write<2,mtr_t::OPT>(
MLOG_2BYTES, &mtr); *root, instant,
rec_t* infimum = page_get_infimum_rec(root); page_ptr_get_direction(instant + 1));
rec_t* supremum = page_get_supremum_rec(root); rec_t* infimum = page_get_infimum_rec(root->frame);
rec_t* supremum = page_get_supremum_rec(root->frame);
static const byte str[8 + 8] = "supremuminfimum"; static const byte str[8 + 8] = "supremuminfimum";
if (memcmp(infimum, str + 8, 8) if (memcmp(infimum, str + 8, 8)
|| memcmp(supremum, str, 8)) { || memcmp(supremum, str, 8)) {

View File

@ -335,37 +335,30 @@ static bool row_undo_rec_get(undo_node_t* node)
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
page_t* undo_page = trx_undo_page_get_s_latched( buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(undo->rseg->space->id, undo->top_page_no), &mtr); page_id_t(undo->rseg->space->id, undo->top_page_no), &mtr);
ulint offset = undo->top_offset; uint16_t offset = undo->top_offset;
trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
undo_page + offset, undo->hdr_page_no, undo->hdr_offset,
true, &mtr);
if (prev_rec == NULL) {
undo->top_undo_no = IB_ID_MAX;
ut_ad(undo->empty());
} else {
page_t* prev_rec_page = page_align(prev_rec);
if (prev_rec_page != undo_page) {
buf_block_t* prev_page = undo_page;
if (trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
prev_page, offset, undo->hdr_page_no, undo->hdr_offset,
true, &mtr)) {
if (prev_page != undo_page) {
trx->pages_undone++; trx->pages_undone++;
} }
undo->top_page_no = page_get_page_no(prev_rec_page); undo->top_page_no = prev_page->page.id.page_no();
undo->top_offset = ulint(prev_rec - prev_rec_page); undo->top_offset = page_offset(prev_rec);
undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
ut_ad(!undo->empty()); ut_ad(!undo->empty());
} else {
undo->top_undo_no = IB_ID_MAX;
ut_ad(undo->empty());
} }
{ node->undo_rec = trx_undo_rec_copy(undo_page->frame + offset,
const trx_undo_rec_t* undo_rec = undo_page + offset; node->heap);
node->undo_rec = trx_undo_rec_copy(undo_rec, node->heap);
}
mtr.commit(); mtr.commit();
switch (trx_undo_rec_get_type(node->undo_rec)) { switch (trx_undo_rec_get_type(node->undo_rec)) {

View File

@ -2755,7 +2755,7 @@ row_upd_clust_rec_by_insert(
insert fails, then this disown will be undone insert fails, then this disown will be undone
when the operation is rolled back. */ when the operation is rolled back. */
btr_cur_disown_inherited_fields( btr_cur_disown_inherited_fields(
btr_cur_get_page_zip(btr_cur), btr_cur_get_block(btr_cur),
rec, index, offsets, node->update, rec, index, offsets, node->update,
mtr); mtr);
} }

View File

@ -1813,9 +1813,9 @@ dberr_t srv_start(bool create_new_db)
ut_ad(size == fil_system.sys_space ut_ad(size == fil_system.sys_space
->size_in_header); ->size_in_header);
size += sum_of_new_sizes; size += sum_of_new_sizes;
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE mtr.write<4>(*block,
+ block->frame, size, FSP_HEADER_OFFSET + FSP_SIZE
MLOG_4BYTES, &mtr); + block->frame, size);
fil_system.sys_space->size_in_header = size; fil_system.sys_space->size_in_header = size;
mtr.commit(); mtr.commit();
/* Immediately write the log record about /* Immediately write the log record about

View File

@ -211,15 +211,16 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|| undo == trx->rsegs.m_redo.old_insert); || undo == trx->rsegs.m_redo.old_insert);
trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_rseg_t* rseg = trx->rsegs.m_redo.rseg;
ut_ad(undo->rseg == rseg); ut_ad(undo->rseg == rseg);
trx_rsegf_t* rseg_header = trx_rsegf_get( buf_block_t* rseg_header = trx_rsegf_get(
rseg->space, rseg->page_no, mtr); rseg->space, rseg->page_no, mtr);
page_t* undo_page = trx_undo_set_state_at_finish( buf_block_t* undo_page = trx_undo_set_state_at_finish(
undo, mtr); undo, mtr);
trx_ulogf_t* undo_header = undo_page + undo->hdr_offset; trx_ulogf_t* undo_header = undo_page->frame + undo->hdr_offset;
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1); ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG_FORMAT + rseg_header))) { if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ rseg_header->frame))) {
/* This database must have been upgraded from /* This database must have been upgraded from
before MariaDB 10.3.5. */ before MariaDB 10.3.5. */
trx_rseg_format_upgrade(rseg_header, mtr); trx_rseg_format_upgrade(rseg_header, mtr);
@ -228,23 +229,27 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
if (undo->state != TRX_UNDO_CACHED) { if (undo->state != TRX_UNDO_CACHED) {
/* The undo log segment will not be reused */ /* The undo log segment will not be reused */
ut_a(undo->id < TRX_RSEG_N_SLOTS); ut_a(undo->id < TRX_RSEG_N_SLOTS);
trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr); compile_time_assert(FIL_NULL == 0xffffffff);
mlog_memset(TRX_RSEG + TRX_RSEG_UNDO_SLOTS
+ undo->id * TRX_RSEG_SLOT_SIZE
+ rseg_header->frame, 4, 0xff, mtr);
MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED); MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED);
uint32_t hist_size = mach_read_from_4(TRX_RSEG_HISTORY_SIZE uint32_t hist_size = mach_read_from_4(TRX_RSEG_HISTORY_SIZE
+ rseg_header); + TRX_RSEG
+ rseg_header->frame);
ut_ad(undo->size == flst_get_len(TRX_UNDO_SEG_HDR ut_ad(undo->size == flst_get_len(TRX_UNDO_SEG_HDR
+ TRX_UNDO_PAGE_LIST + TRX_UNDO_PAGE_LIST
+ undo_page)); + undo_page->frame));
mlog_write_ulint( mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_HISTORY_SIZE
rseg_header + TRX_RSEG_HISTORY_SIZE, + rseg_header->frame,
hist_size + undo->size, MLOG_4BYTES, mtr); hist_size + undo->size);
mtr->write<8>(*rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID
mlog_write_ull(rseg_header + TRX_RSEG_MAX_TRX_ID, + rseg_header->frame,
trx_sys.get_max_trx_id(), mtr); trx_sys.get_max_trx_id());
} }
/* After the purge thread has been given permission to exit, /* After the purge thread has been given permission to exit,
@ -287,16 +292,17 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
} }
/* Add the log as the first in the history list */ /* Add the log as the first in the history list */
flst_add_first(rseg_header + TRX_RSEG_HISTORY, flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY,
undo_header + TRX_UNDO_HISTORY_NODE, mtr); undo_page, undo->hdr_offset + TRX_UNDO_HISTORY_NODE,
mtr);
mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr); mtr->write<8>(*undo_page, undo_header + TRX_UNDO_TRX_NO, trx->no);
/* This is needed for upgrading old undo log pages from /* This is needed for upgrading old undo log pages from
before MariaDB 10.3.1. */ before MariaDB 10.3.1. */
if (UNIV_UNLIKELY(!mach_read_from_2(undo_header if (UNIV_UNLIKELY(!mach_read_from_2(undo_header
+ TRX_UNDO_NEEDS_PURGE))) { + TRX_UNDO_NEEDS_PURGE))) {
mlog_write_ulint(undo_header + TRX_UNDO_NEEDS_PURGE, 1, mtr->write<2>(*undo_page, undo_header + TRX_UNDO_NEEDS_PURGE,
MLOG_2BYTES, mtr); 1U);
} }
if (rseg->last_page_no == FIL_NULL) { if (rseg->last_page_no == FIL_NULL) {
@ -320,19 +326,16 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
} }
/** Remove undo log header from the history list. /** Remove undo log header from the history list.
@param[in,out] rseg_hdr rollback segment header @param[in,out] rseg rollback segment header page
@param[in] log_hdr undo log segment header @param[in] log undo log segment header page
@param[in,out] mtr mini transaction. */ @param[in] offset byte offset in the undo log segment header page
static @param[in,out] mtr mini-transaction */
void static void trx_purge_remove_log_hdr(buf_block_t *rseg, buf_block_t* log,
trx_purge_remove_log_hdr( uint16_t offset, mtr_t *mtr)
trx_rsegf_t* rseg_hdr,
trx_ulogf_t* log_hdr,
mtr_t* mtr)
{ {
flst_remove(rseg_hdr + TRX_RSEG_HISTORY, flst_remove(rseg, TRX_RSEG + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, mtr); log, offset + TRX_UNDO_HISTORY_NODE, mtr);
trx_sys.rseg_history_len--; trx_sys.rseg_history_len--;
} }
/** Free an undo log segment, and remove the header from the history list. /** Free an undo log segment, and remove the header from the history list.
@ -343,14 +346,12 @@ void
trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr) trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
{ {
mtr_t mtr; mtr_t mtr;
trx_rsegf_t* rseg_hdr;
page_t* undo_page;
mtr.start(); mtr.start();
mutex_enter(&rseg->mutex); mutex_enter(&rseg->mutex);
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); buf_block_t* rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
undo_page = trx_undo_page_get( buf_block_t* block = trx_undo_page_get(
page_id_t(rseg->space->id, hdr_addr.page), &mtr); page_id_t(rseg->space->id, hdr_addr.page), &mtr);
/* Mark the last undo log totally purged, so that if the /* Mark the last undo log totally purged, so that if the
@ -358,12 +359,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
again. The list of pages in the undo log tail gets again. The list of pages in the undo log tail gets
inconsistent during the freeing of the segment, and therefore inconsistent during the freeing of the segment, and therefore
purge should not try to access them again. */ purge should not try to access them again. */
mlog_write_ulint(undo_page + hdr_addr.boffset + TRX_UNDO_NEEDS_PURGE, mtr.write<2>(*block, block->frame + hdr_addr.boffset
0, MLOG_2BYTES, &mtr); + TRX_UNDO_NEEDS_PURGE, 0U);
while (!fseg_free_step_not_header( while (!fseg_free_step_not_header(
TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ undo_page, false, &mtr)) { + block->frame, false, &mtr)) {
mutex_exit(&rseg->mutex); mutex_exit(&rseg->mutex);
mtr.commit(); mtr.commit();
@ -373,7 +374,7 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
undo_page = trx_undo_page_get( block = trx_undo_page_get(
page_id_t(rseg->space->id, hdr_addr.page), &mtr); page_id_t(rseg->space->id, hdr_addr.page), &mtr);
} }
@ -381,15 +382,15 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
stored in the list base node tells us how big it was before we stored in the list base node tells us how big it was before we
started the freeing. */ started the freeing. */
const ulint seg_size = flst_get_len( const uint32_t seg_size = flst_get_len(
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + undo_page); TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->frame);
/* We may free the undo log segment header page; it must be freed /* We may free the undo log segment header page; it must be freed
within the same mtr as the undo log header is removed from the within the same mtr as the undo log header is removed from the
history list: otherwise, in case of a database crash, the segment history list: otherwise, in case of a database crash, the segment
could become inaccessible garbage in the file space. */ could become inaccessible garbage in the file space. */
trx_purge_remove_log_hdr(rseg_hdr, undo_page + hdr_addr.boffset, &mtr); trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset, &mtr);
do { do {
@ -399,14 +400,12 @@ trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
fsp0fsp.cc. */ fsp0fsp.cc. */
} while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER } while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
+ undo_page, false, &mtr)); + block->frame, false, &mtr));
const ulint hist_size = mach_read_from_4(rseg_hdr byte* hist = TRX_RSEG + TRX_RSEG_HISTORY_SIZE + rseg_hdr->frame;
+ TRX_RSEG_HISTORY_SIZE); ut_ad(mach_read_from_4(hist) >= seg_size);
ut_ad(hist_size >= seg_size);
mlog_write_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE, mtr.write<4>(*rseg_hdr, hist, mach_read_from_4(hist) - seg_size);
hist_size - seg_size, MLOG_4BYTES, &mtr);
ut_ad(rseg->curr_size >= seg_size); ut_ad(rseg->curr_size >= seg_size);
@ -428,10 +427,6 @@ trx_purge_truncate_rseg_history(
{ {
fil_addr_t hdr_addr; fil_addr_t hdr_addr;
fil_addr_t prev_hdr_addr; fil_addr_t prev_hdr_addr;
trx_rsegf_t* rseg_hdr;
page_t* undo_page;
trx_ulogf_t* log_hdr;
trx_usegf_t* seg_hdr;
mtr_t mtr; mtr_t mtr;
trx_id_t undo_trx_no; trx_id_t undo_trx_no;
@ -439,10 +434,10 @@ trx_purge_truncate_rseg_history(
ut_ad(rseg.is_persistent()); ut_ad(rseg.is_persistent());
mutex_enter(&rseg.mutex); mutex_enter(&rseg.mutex);
rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr); buf_block_t* rseg_hdr = trx_rsegf_get(rseg.space, rseg.page_no, &mtr);
hdr_addr = trx_purge_get_log_from_hist(flst_get_last(TRX_RSEG_HISTORY hdr_addr = trx_purge_get_log_from_hist(
+ rseg_hdr)); flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY + rseg_hdr->frame));
loop: loop:
if (hdr_addr.page == FIL_NULL) { if (hdr_addr.page == FIL_NULL) {
func_exit: func_exit:
@ -451,12 +446,11 @@ trx_purge_truncate_rseg_history(
return; return;
} }
undo_page = trx_undo_page_get(page_id_t(rseg.space->id, hdr_addr.page), buf_block_t* block = trx_undo_page_get(page_id_t(rseg.space->id,
&mtr); hdr_addr.page),
&mtr);
log_hdr = undo_page + hdr_addr.boffset; undo_trx_no = mach_read_from_8(block->frame + hdr_addr.boffset
+ TRX_UNDO_TRX_NO);
undo_trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
if (undo_trx_no >= limit.trx_no()) { if (undo_trx_no >= limit.trx_no()) {
if (undo_trx_no == limit.trx_no()) { if (undo_trx_no == limit.trx_no()) {
@ -469,12 +463,13 @@ trx_purge_truncate_rseg_history(
} }
prev_hdr_addr = trx_purge_get_log_from_hist( prev_hdr_addr = trx_purge_get_log_from_hist(
flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE)); flst_get_prev_addr(block->frame + hdr_addr.boffset
+ TRX_UNDO_HISTORY_NODE));
seg_hdr = undo_page + TRX_UNDO_SEG_HDR; if (mach_read_from_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + block->frame)
== TRX_UNDO_TO_PURGE
if ((mach_read_from_2(seg_hdr + TRX_UNDO_STATE) == TRX_UNDO_TO_PURGE) && !mach_read_from_2(block->frame + hdr_addr.boffset
&& (mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG) == 0)) { + TRX_UNDO_NEXT_LOG)) {
/* We can free the whole log segment */ /* We can free the whole log segment */
@ -486,7 +481,8 @@ trx_purge_truncate_rseg_history(
trx_purge_free_segment(&rseg, hdr_addr); trx_purge_free_segment(&rseg, hdr_addr);
} else { } else {
/* Remove the log hdr from the rseg history. */ /* Remove the log hdr from the rseg history. */
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr); trx_purge_remove_log_hdr(rseg_hdr, block, hdr_addr.boffset,
&mtr);
mutex_exit(&rseg.mutex); mutex_exit(&rseg.mutex);
mtr.commit(); mtr.commit();
@ -825,8 +821,6 @@ static void trx_purge_rseg_get_next_history_log(
ulint* n_pages_handled)/*!< in/out: number of UNDO pages ulint* n_pages_handled)/*!< in/out: number of UNDO pages
handled */ handled */
{ {
page_t* undo_page;
trx_ulogf_t* log_hdr;
fil_addr_t prev_log_addr; fil_addr_t prev_log_addr;
trx_id_t trx_no; trx_id_t trx_no;
mtr_t mtr; mtr_t mtr;
@ -841,11 +835,12 @@ static void trx_purge_rseg_get_next_history_log(
mtr.start(); mtr.start();
undo_page = trx_undo_page_get_s_latched( const buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(purge_sys.rseg->space->id, page_id_t(purge_sys.rseg->space->id,
purge_sys.rseg->last_page_no), &mtr); purge_sys.rseg->last_page_no), &mtr);
log_hdr = undo_page + purge_sys.rseg->last_offset; const trx_ulogf_t* log_hdr = undo_page->frame
+ purge_sys.rseg->last_offset;
/* Increase the purge page count by one for every handled log */ /* Increase the purge page count by one for every handled log */
@ -873,7 +868,7 @@ static void trx_purge_rseg_get_next_history_log(
log_hdr = trx_undo_page_get_s_latched( log_hdr = trx_undo_page_get_s_latched(
page_id_t(purge_sys.rseg->space->id, prev_log_addr.page), page_id_t(purge_sys.rseg->space->id, prev_log_addr.page),
&mtr) &mtr)->frame
+ prev_log_addr.boffset; + prev_log_addr.boffset;
trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);
@ -908,8 +903,8 @@ static
void void
trx_purge_read_undo_rec() trx_purge_read_undo_rec()
{ {
ulint offset; uint16_t offset;
ulint page_no; uint32_t page_no;
ib_uint64_t undo_no; ib_uint64_t undo_no;
purge_sys.hdr_offset = purge_sys.rseg->last_offset; purge_sys.hdr_offset = purge_sys.rseg->last_offset;
@ -918,13 +913,15 @@ trx_purge_read_undo_rec()
if (purge_sys.rseg->needs_purge) { if (purge_sys.rseg->needs_purge) {
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
buf_block_t* undo_page;
if (trx_undo_rec_t* undo_rec = trx_undo_get_first_rec( if (trx_undo_rec_t* undo_rec = trx_undo_get_first_rec(
purge_sys.rseg->space, purge_sys.hdr_page_no, *purge_sys.rseg->space, purge_sys.hdr_page_no,
purge_sys.hdr_offset, RW_S_LATCH, &mtr)) { purge_sys.hdr_offset, RW_S_LATCH,
undo_page, &mtr)) {
offset = page_offset(undo_rec); offset = page_offset(undo_rec);
undo_no = trx_undo_rec_get_undo_no(undo_rec); undo_no = trx_undo_rec_get_undo_no(undo_rec);
page_no = page_get_page_no(page_align(undo_rec)); page_no = undo_page->page.id.page_no();
} else { } else {
offset = 0; offset = 0;
undo_no = 0; undo_no = 0;
@ -974,22 +971,14 @@ trx_purge_get_next_rec(
handled */ handled */
mem_heap_t* heap) /*!< in: memory heap where copied */ mem_heap_t* heap) /*!< in: memory heap where copied */
{ {
trx_undo_rec_t* rec;
trx_undo_rec_t* rec_copy;
trx_undo_rec_t* rec2;
page_t* undo_page;
page_t* page;
ulint offset;
ulint page_no;
ulint space;
mtr_t mtr; mtr_t mtr;
ut_ad(purge_sys.next_stored); ut_ad(purge_sys.next_stored);
ut_ad(purge_sys.tail.trx_no() < purge_sys.view.low_limit_no()); ut_ad(purge_sys.tail.trx_no() < purge_sys.view.low_limit_no());
space = purge_sys.rseg->space->id; const ulint space = purge_sys.rseg->space->id;
page_no = purge_sys.page_no; const uint32_t page_no = purge_sys.page_no;
offset = purge_sys.offset; const uint16_t offset = purge_sys.offset;
if (offset == 0) { if (offset == 0) {
/* It is the dummy undo log record, which means that there is /* It is the dummy undo log record, which means that there is
@ -1006,16 +995,16 @@ trx_purge_get_next_rec(
mtr_start(&mtr); mtr_start(&mtr);
undo_page = trx_undo_page_get_s_latched(page_id_t(space, page_no), buf_block_t* undo_page = trx_undo_page_get_s_latched(
&mtr); page_id_t(space, page_no), &mtr);
buf_block_t* rec2_page = undo_page;
rec = undo_page + offset; const trx_undo_rec_t* rec2 = trx_undo_page_get_next_rec(
undo_page, offset, purge_sys.hdr_page_no, purge_sys.hdr_offset);
rec2 = trx_undo_page_get_next_rec(rec, purge_sys.hdr_page_no,
purge_sys.hdr_offset);
if (rec2 == NULL) { if (rec2 == NULL) {
rec2 = trx_undo_get_next_rec(rec, purge_sys.hdr_page_no, rec2 = trx_undo_get_next_rec(rec2_page, offset,
purge_sys.hdr_page_no,
purge_sys.hdr_offset, &mtr); purge_sys.hdr_offset, &mtr);
} }
@ -1032,22 +1021,19 @@ trx_purge_get_next_rec(
undo_page = trx_undo_page_get_s_latched( undo_page = trx_undo_page_get_s_latched(
page_id_t(space, page_no), &mtr); page_id_t(space, page_no), &mtr);
rec = undo_page + offset;
} else { } else {
page = page_align(rec2); purge_sys.offset = page_offset(rec2);
purge_sys.page_no = rec2_page->page.id.page_no();
purge_sys.offset = ulint(rec2 - page);
purge_sys.page_no = page_get_page_no(page);
purge_sys.tail.undo_no = trx_undo_rec_get_undo_no(rec2); purge_sys.tail.undo_no = trx_undo_rec_get_undo_no(rec2);
if (undo_page != page) { if (undo_page != rec2_page) {
/* We advance to a new page of the undo log: */ /* We advance to a new page of the undo log: */
(*n_pages_handled)++; (*n_pages_handled)++;
} }
} }
rec_copy = trx_undo_rec_copy(rec, heap); trx_undo_rec_t* rec_copy = trx_undo_rec_copy(undo_page->frame + offset,
heap);
mtr_commit(&mtr); mtr_commit(&mtr);

View File

@ -162,7 +162,7 @@ that was written to ptr. Update the first free value by the number of bytes
written for this undo record. written for this undo record.
@return offset of the inserted entry on the page if succeeded, 0 if fail */ @return offset of the inserted entry on the page if succeeded, 0 if fail */
static static
ulint uint16_t
trx_undo_page_set_next_prev_and_add( trx_undo_page_set_next_prev_and_add(
/*================================*/ /*================================*/
buf_block_t* undo_block, /*!< in/out: undo log page */ buf_block_t* undo_block, /*!< in/out: undo log page */
@ -170,30 +170,22 @@ trx_undo_page_set_next_prev_and_add(
written on this undo page. */ written on this undo page. */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
ulint first_free; /*!< offset within undo_page */ ut_ad(page_align(ptr) == undo_block->frame);
ulint end_of_rec; /*!< offset within undo_page */
byte* ptr_to_first_free;
/* pointer within undo_page
that points to the next free
offset value within undo_page.*/
ut_ad(ptr > undo_block->frame);
ut_ad(ptr < undo_block->frame + srv_page_size);
if (UNIV_UNLIKELY(trx_undo_left(undo_block, ptr) < 2)) { if (UNIV_UNLIKELY(trx_undo_left(undo_block, ptr) < 2)) {
return(0); return(0);
} }
ptr_to_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE byte* ptr_to_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ undo_block->frame; + undo_block->frame;
first_free = mach_read_from_2(ptr_to_first_free); uint16_t first_free = mach_read_from_2(ptr_to_first_free);
/* Write offset of the previous undo log record */ /* Write offset of the previous undo log record */
mach_write_to_2(ptr, first_free); mach_write_to_2(ptr, first_free);
ptr += 2; ptr += 2;
end_of_rec = ulint(ptr - undo_block->frame); uint16_t end_of_rec = uint16_t(ptr - undo_block->frame);
/* Write offset of the next undo log record */ /* Write offset of the next undo log record */
mach_write_to_2(undo_block->frame + first_free, end_of_rec); mach_write_to_2(undo_block->frame + first_free, end_of_rec);
@ -457,7 +449,7 @@ trx_undo_report_insert_virtual(
Reports in the undo log of an insert of a clustered index record. Reports in the undo log of an insert of a clustered index record.
@return offset of the inserted entry on the page if succeed, 0 if fail */ @return offset of the inserted entry on the page if succeed, 0 if fail */
static static
ulint uint16_t
trx_undo_page_report_insert( trx_undo_page_report_insert(
/*========================*/ /*========================*/
buf_block_t* undo_block, /*!< in: undo log page */ buf_block_t* undo_block, /*!< in: undo log page */
@ -467,10 +459,6 @@ trx_undo_page_report_insert(
inserted to the clustered index */ inserted to the clustered index */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
ulint first_free;
byte* ptr;
ulint i;
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
/* MariaDB 10.3.1+ in trx_undo_page_init() always initializes /* MariaDB 10.3.1+ in trx_undo_page_init() always initializes
TRX_UNDO_PAGE_TYPE as 0, but previous versions wrote TRX_UNDO_PAGE_TYPE as 0, but previous versions wrote
@ -479,9 +467,10 @@ trx_undo_page_report_insert(
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ undo_block->frame) <= 2); + undo_block->frame) <= 2);
first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE uint16_t first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR
+ undo_block->frame); + TRX_UNDO_PAGE_FREE
ptr = undo_block->frame + first_free; + undo_block->frame);
byte* ptr = undo_block->frame + first_free;
ut_ad(first_free <= srv_page_size); ut_ad(first_free <= srv_page_size);
@ -509,7 +498,7 @@ trx_undo_page_report_insert(
goto done; goto done;
} }
for (i = 0; i < dict_index_get_n_unique(index); i++) { for (unsigned i = 0; i < dict_index_get_n_unique(index); i++) {
const dfield_t* field = dtuple_get_nth_field(clust_entry, i); const dfield_t* field = dtuple_get_nth_field(clust_entry, i);
ulint flen = dfield_get_len(field); ulint flen = dfield_get_len(field);
@ -572,12 +561,14 @@ trx_undo_rec_get_pars(
*updated_extern = !!(type_cmpl & TRX_UNDO_UPD_EXTERN); *updated_extern = !!(type_cmpl & TRX_UNDO_UPD_EXTERN);
type_cmpl &= ~TRX_UNDO_UPD_EXTERN; type_cmpl &= ~TRX_UNDO_UPD_EXTERN;
*type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1); *type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1);
ut_ad(*type >= TRX_UNDO_RENAME_TABLE);
ut_ad(*type <= TRX_UNDO_DEL_MARK_REC);
*cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT; *cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT;
*undo_no = mach_read_next_much_compressed(&ptr); *undo_no = mach_read_next_much_compressed(&ptr);
*table_id = mach_read_next_much_compressed(&ptr); *table_id = mach_read_next_much_compressed(&ptr);
ut_ad(*table_id);
return(const_cast<byte*>(ptr)); return(const_cast<byte*>(ptr));
} }
@ -856,7 +847,7 @@ record.
@return byte offset of the inserted undo log entry on the page if @return byte offset of the inserted undo log entry on the page if
succeed, 0 if fail */ succeed, 0 if fail */
static static
ulint uint16_t
trx_undo_page_report_modify( trx_undo_page_report_modify(
/*========================*/ /*========================*/
buf_block_t* undo_block, /*!< in: undo log page */ buf_block_t* undo_block, /*!< in: undo log page */
@ -875,7 +866,6 @@ trx_undo_page_report_modify(
virtual column info */ virtual column info */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
ulint first_free;
byte* ptr; byte* ptr;
ut_ad(index->is_primary()); ut_ad(index->is_primary());
@ -887,8 +877,9 @@ trx_undo_page_report_modify(
ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ undo_block->frame) <= 2); + undo_block->frame) <= 2);
first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE uint16_t first_free = mach_read_from_2(TRX_UNDO_PAGE_HDR
+ undo_block->frame); + TRX_UNDO_PAGE_FREE
+ undo_block->frame);
ptr = undo_block->frame + first_free; ptr = undo_block->frame + first_free;
ut_ad(first_free <= srv_page_size); ut_ad(first_free <= srv_page_size);
@ -1953,13 +1944,13 @@ trx_undo_erase_page_end(page_t* undo_page)
@return byte offset of the undo log record @return byte offset of the undo log record
@retval 0 in case of failure */ @retval 0 in case of failure */
static static
ulint uint16_t
trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table, trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table,
buf_block_t* block, mtr_t* mtr) buf_block_t* block, mtr_t* mtr)
{ {
byte* ptr_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE byte* ptr_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE
+ block->frame; + block->frame;
ulint first_free = mach_read_from_2(ptr_first_free); uint16_t first_free = mach_read_from_2(ptr_first_free);
ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
ut_ad(first_free <= srv_page_size); ut_ad(first_free <= srv_page_size);
byte* start = block->frame + first_free; byte* start = block->frame + first_free;
@ -1985,7 +1976,7 @@ trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table,
ptr += len; ptr += len;
mach_write_to_2(ptr, first_free); mach_write_to_2(ptr, first_free);
ptr += 2; ptr += 2;
ulint offset = page_offset(ptr); uint16_t offset = page_offset(ptr);
mach_write_to_2(start, offset); mach_write_to_2(start, offset);
mach_write_to_2(ptr_first_free, offset); mach_write_to_2(ptr_first_free, offset);
@ -2014,7 +2005,7 @@ dberr_t trx_undo_report_rename(trx_t* trx, const dict_table_t* table)
ut_ad(loop_count++ < 2); ut_ad(loop_count++ < 2);
ut_ad(undo->last_page_no == block->page.id.page_no()); ut_ad(undo->last_page_no == block->page.id.page_no());
if (ulint offset = trx_undo_page_report_rename( if (uint16_t offset = trx_undo_page_report_rename(
trx, table, block, &mtr)) { trx, table, block, &mtr)) {
undo->withdraw_clock = buf_withdraw_clock; undo->withdraw_clock = buf_withdraw_clock;
undo->top_page_no = undo->last_page_no; undo->top_page_no = undo->last_page_no;
@ -2118,7 +2109,7 @@ trx_undo_report_row_operation(
ut_ad(undo != NULL); ut_ad(undo != NULL);
do { do {
ulint offset = !rec uint16_t offset = !rec
? trx_undo_page_report_insert( ? trx_undo_page_report_insert(
undo_block, trx, index, clust_entry, &mtr) undo_block, trx, index, clust_entry, &mtr)
: trx_undo_page_report_modify( : trx_undo_page_report_modify(
@ -2240,11 +2231,10 @@ trx_undo_get_undo_rec_low(
{ {
trx_undo_rec_t* undo_rec; trx_undo_rec_t* undo_rec;
ulint rseg_id; ulint rseg_id;
ulint page_no; uint32_t page_no;
ulint offset; uint16_t offset;
const page_t* undo_page;
trx_rseg_t* rseg; trx_rseg_t* rseg;
ibool is_insert; bool is_insert;
mtr_t mtr; mtr_t mtr;
trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no, trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
@ -2254,14 +2244,14 @@ trx_undo_get_undo_rec_low(
rseg = trx_sys.rseg_array[rseg_id]; rseg = trx_sys.rseg_array[rseg_id];
ut_ad(rseg->is_persistent()); ut_ad(rseg->is_persistent());
mtr_start(&mtr); mtr.start();
undo_page = trx_undo_page_get_s_latched( buf_block_t* undo_page = trx_undo_page_get_s_latched(
page_id_t(rseg->space->id, page_no), &mtr); page_id_t(rseg->space->id, page_no), &mtr);
undo_rec = trx_undo_rec_copy(undo_page + offset, heap); undo_rec = trx_undo_rec_copy(undo_page->frame + offset, heap);
mtr_commit(&mtr); mtr.commit();
return(undo_rec); return(undo_rec);
} }

View File

@ -49,7 +49,7 @@ static unsigned char wsrep_uuid[16];
@param[in,out] mtr mini transaction */ @param[in,out] mtr mini transaction */
static void static void
trx_rseg_write_wsrep_checkpoint( trx_rseg_write_wsrep_checkpoint(
trx_rsegf_t* rseg_header, buf_block_t* rseg_header,
const XID* xid, const XID* xid,
mtr_t* mtr) mtr_t* mtr)
{ {
@ -57,25 +57,27 @@ trx_rseg_write_wsrep_checkpoint(
DBUG_ASSERT(xid->bqual_length >= 0); DBUG_ASSERT(xid->bqual_length >= 0);
DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE); DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE);
mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_WSREP_XID_FORMAT
uint32_t(xid->formatID), + rseg_header->frame,
MLOG_4BYTES, mtr); uint32_t(xid->formatID));
mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_WSREP_XID_GTRID_LEN
uint32_t(xid->gtrid_length), + rseg_header->frame,
MLOG_4BYTES, mtr); uint32_t(xid->gtrid_length));
mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, mtr->write<4>(*rseg_header, TRX_RSEG + TRX_RSEG_WSREP_XID_BQUAL_LEN
uint32_t(xid->bqual_length), + rseg_header->frame,
MLOG_4BYTES, mtr); uint32_t(xid->bqual_length));
const ulint xid_length = static_cast<ulint>(xid->gtrid_length const ulint xid_length = static_cast<ulint>(xid->gtrid_length
+ xid->bqual_length); + xid->bqual_length);
mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, mlog_write_string(TRX_RSEG + TRX_RSEG_WSREP_XID_DATA
+ rseg_header->frame,
reinterpret_cast<const byte*>(xid->data), reinterpret_cast<const byte*>(xid->data),
xid_length, mtr); xid_length, mtr);
if (UNIV_LIKELY(xid_length < XIDDATASIZE)) { if (UNIV_LIKELY(xid_length < XIDDATASIZE)) {
mlog_memset(TRX_RSEG_WSREP_XID_DATA + rseg_header + xid_length, mlog_memset(TRX_RSEG + TRX_RSEG_WSREP_XID_DATA
+ rseg_header->frame + xid_length,
XIDDATASIZE - xid_length, 0, mtr); XIDDATASIZE - xid_length, 0, mtr);
} }
} }
@ -86,7 +88,7 @@ trx_rseg_write_wsrep_checkpoint(
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void
trx_rseg_update_wsrep_checkpoint( trx_rseg_update_wsrep_checkpoint(
trx_rsegf_t* rseg_header, buf_block_t* rseg_header,
const XID* xid, const XID* xid,
mtr_t* mtr) mtr_t* mtr)
{ {
@ -109,16 +111,13 @@ trx_rseg_update_wsrep_checkpoint(
} }
/** Clear the WSREP XID information from rollback segment header. /** Clear the WSREP XID information from rollback segment header.
@param[in,out] rseg_header Rollback segment header @param[in,out] block rollback segment header
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
static void static void trx_rseg_clear_wsrep_checkpoint(buf_block_t *block, mtr_t *mtr)
trx_rseg_clear_wsrep_checkpoint(
trx_rsegf_t* rseg_header,
mtr_t* mtr)
{ {
mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO, mlog_memset(block, TRX_RSEG + TRX_RSEG_WSREP_XID_INFO,
TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE - TRX_RSEG_WSREP_XID_INFO,
- TRX_RSEG_WSREP_XID_INFO, 0, mtr); 0, mtr);
} }
static void static void
@ -133,9 +132,10 @@ trx_rseg_update_wsrep_checkpoint(const XID* xid, mtr_t* mtr)
sizeof wsrep_uuid); sizeof wsrep_uuid);
const trx_rseg_t* rseg = trx_sys.rseg_array[0]; const trx_rseg_t* rseg = trx_sys.rseg_array[0];
trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, buf_block_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no,
mtr); mtr);
if (UNIV_UNLIKELY(mach_read_from_4(rseg_header + TRX_RSEG_FORMAT))) { if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ rseg_header->frame))) {
trx_rseg_format_upgrade(rseg_header, mtr); trx_rseg_format_upgrade(rseg_header, mtr);
} }
@ -178,25 +178,26 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid)
@param[out] xid Transaction XID @param[out] xid Transaction XID
@return whether the WSREP XID was present */ @return whether the WSREP XID was present */
static static
bool trx_rseg_read_wsrep_checkpoint(const trx_rsegf_t* rseg_header, XID& xid) bool trx_rseg_read_wsrep_checkpoint(const buf_block_t *rseg_header, XID &xid)
{ {
int formatID = static_cast<int>( int formatID = static_cast<int>(
mach_read_from_4( mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_FORMAT
TRX_RSEG_WSREP_XID_FORMAT + rseg_header)); + rseg_header->frame));
if (formatID == 0) { if (formatID == 0) {
return false; return false;
} }
xid.formatID = formatID; xid.formatID = formatID;
xid.gtrid_length = static_cast<int>( xid.gtrid_length = static_cast<int>(
mach_read_from_4( mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_GTRID_LEN
TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header)); + rseg_header->frame));
xid.bqual_length = static_cast<int>( xid.bqual_length = static_cast<int>(
mach_read_from_4( mach_read_from_4(TRX_RSEG + TRX_RSEG_WSREP_XID_BQUAL_LEN
TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header)); + rseg_header->frame));
memcpy(xid.data, TRX_RSEG_WSREP_XID_DATA + rseg_header, XIDDATASIZE); memcpy(xid.data, TRX_RSEG + TRX_RSEG_WSREP_XID_DATA
+ rseg_header->frame, XIDDATASIZE);
return true; return true;
} }
@ -252,10 +253,11 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
continue; continue;
} }
const trx_rsegf_t* rseg_header = trx_rsegf_get_new( const buf_block_t* rseg_header = trx_rsegf_get_new(
trx_sysf_rseg_get_space(sys, rseg_id), page_no, &mtr); trx_sysf_rseg_get_space(sys, rseg_id), page_no, &mtr);
if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT)) { if (mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ rseg_header->frame)) {
continue; continue;
} }
@ -279,17 +281,15 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid)
/** Upgrade a rollback segment header page to MariaDB 10.3 format. /** Upgrade a rollback segment header page to MariaDB 10.3 format.
@param[in,out] rseg_header rollback segment header page @param[in,out] rseg_header rollback segment header page
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr) void trx_rseg_format_upgrade(buf_block_t *rseg_header, mtr_t *mtr)
{ {
ut_ad(page_offset(rseg_header) == TRX_RSEG); mlog_memset(rseg_header, TRX_RSEG + TRX_RSEG_FORMAT, 4, 0, mtr);
byte* rseg_format = TRX_RSEG_FORMAT + rseg_header; /* Clear also possible garbage at the end of the page. Old
mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr); InnoDB versions did not initialize unused parts of pages. */
/* Clear also possible garbage at the end of the page. Old mlog_memset(rseg_header, TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8,
InnoDB versions did not initialize unused parts of pages. */ srv_page_size
mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header, - (FIL_PAGE_DATA_END + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8),
srv_page_size 0, mtr);
- (FIL_PAGE_DATA_END
+ TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr);
} }
/** Create a rollback segment header. /** Create a rollback segment header.
@ -337,16 +337,16 @@ trx_rseg_header_create(
/* Add the rollback segment info to the free slot in /* Add the rollback segment info to the free slot in
the trx system header */ the trx system header */
mlog_write_ulint(TRX_SYS + TRX_SYS_RSEGS mtr->write<4,mtr_t::OPT>(
+ TRX_SYS_RSEG_SPACE *sys_header,
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_SPACE
+ sys_header->frame, + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
space->id, MLOG_4BYTES, mtr); + sys_header->frame, space->id);
mlog_write_ulint(TRX_SYS + TRX_SYS_RSEGS mtr->write<4,mtr_t::OPT>(
+ TRX_SYS_RSEG_PAGE_NO *sys_header,
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO
+ sys_header->frame, + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
block->page.id.page_no(), MLOG_4BYTES, mtr); + sys_header->frame, block->page.id.page_no());
} }
return block; return block;
@ -410,29 +410,28 @@ trx_rseg_mem_create(ulint id, fil_space_t* space, ulint page_no)
} }
/** Read the undo log lists. /** Read the undo log lists.
@param[in,out] rseg rollback segment @param[in,out] rseg rollback segment
@param[in,out] max_trx_id maximum observed transaction identifier @param[in,out] max_trx_id maximum observed transaction identifier
@param[in] rseg_header rollback segment header @param[in] rseg_header rollback segment header
@return the combined size of undo log segments in pages */ @return the combined size of undo log segments in pages */
static static ulint trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
ulint const buf_block_t *rseg_header)
trx_undo_lists_init(trx_rseg_t* rseg, trx_id_t& max_trx_id,
const trx_rsegf_t* rseg_header)
{ {
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN); ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
ulint size = 0; ulint size= 0;
for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) { for (ulint i= 0; i < TRX_RSEG_N_SLOTS; i++)
ulint page_no = trx_rsegf_get_nth_undo(rseg_header, i); {
if (page_no != FIL_NULL) { uint32_t page_no= trx_rsegf_get_nth_undo(rseg_header, i);
size += trx_undo_mem_create_at_db_start( if (page_no != FIL_NULL)
rseg, i, page_no, max_trx_id); {
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED); size+= trx_undo_mem_create_at_db_start(rseg, i, page_no, max_trx_id);
} MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
} }
}
return(size); return size;
} }
/** Restore the state of a persistent rollback segment. /** Restore the state of a persistent rollback segment.
@ -443,20 +442,20 @@ static
void void
trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
{ {
trx_rsegf_t* rseg_header = trx_rsegf_get_new( buf_block_t* rseg_hdr = trx_rsegf_get_new(
rseg->space->id, rseg->page_no, mtr); rseg->space->id, rseg->page_no, mtr);
if (mach_read_from_4(rseg_header + TRX_RSEG_FORMAT) == 0) { if (!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT + rseg_hdr->frame)) {
trx_id_t id = mach_read_from_8(rseg_header trx_id_t id = mach_read_from_8(TRX_RSEG + TRX_RSEG_MAX_TRX_ID
+ TRX_RSEG_MAX_TRX_ID); + rseg_hdr->frame);
if (id > max_trx_id) { if (id > max_trx_id) {
max_trx_id = id; max_trx_id = id;
} }
if (rseg_header[TRX_RSEG_BINLOG_NAME]) { const char* binlog_name = TRX_RSEG + TRX_RSEG_BINLOG_NAME
const char* binlog_name = reinterpret_cast<const char*> + reinterpret_cast<const char*>(rseg_hdr->frame);
(rseg_header) + TRX_RSEG_BINLOG_NAME; if (*binlog_name) {
compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof compile_time_assert(TRX_RSEG_BINLOG_NAME_LEN == sizeof
trx_sys.recovered_binlog_filename); trx_sys.recovered_binlog_filename);
@ -468,7 +467,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
if (cmp >= 0) { if (cmp >= 0) {
uint64_t binlog_offset = mach_read_from_8( uint64_t binlog_offset = mach_read_from_8(
rseg_header + TRX_RSEG_BINLOG_OFFSET); TRX_RSEG + TRX_RSEG_BINLOG_OFFSET
+ rseg_hdr->frame);
if (cmp) { if (cmp) {
memcpy(trx_sys. memcpy(trx_sys.
recovered_binlog_filename, recovered_binlog_filename,
@ -485,7 +485,7 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
#ifdef WITH_WSREP #ifdef WITH_WSREP
trx_rseg_read_wsrep_checkpoint( trx_rseg_read_wsrep_checkpoint(
rseg_header, trx_sys.recovered_wsrep_xid); rseg_hdr, trx_sys.recovered_wsrep_xid);
#endif #endif
} }
} }
@ -499,32 +499,37 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
/* Initialize the undo log lists according to the rseg header */ /* Initialize the undo log lists according to the rseg header */
rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE) rseg->curr_size = mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE
+ 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header); + rseg_hdr->frame)
+ 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_hdr);
if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { if (auto len = flst_get_len(TRX_RSEG + TRX_RSEG_HISTORY
+ rseg_hdr->frame)) {
trx_sys.rseg_history_len += len; trx_sys.rseg_history_len += len;
fil_addr_t node_addr = trx_purge_get_log_from_hist( fil_addr_t node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY)); flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY
+ rseg_hdr->frame));
rseg->last_page_no = node_addr.page; rseg->last_page_no = node_addr.page;
rseg->last_offset = node_addr.boffset; rseg->last_offset = node_addr.boffset;
const trx_ulogf_t* undo_log_hdr = trx_undo_page_get( const buf_block_t* block = trx_undo_page_get(
page_id_t(rseg->space->id, node_addr.page), mtr) page_id_t(rseg->space->id, node_addr.page), mtr);
+ node_addr.boffset;
trx_id_t id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_ID); trx_id_t id = mach_read_from_8(block->frame + node_addr.boffset
+ TRX_UNDO_TRX_ID);
if (id > max_trx_id) { if (id > max_trx_id) {
max_trx_id = id; max_trx_id = id;
} }
id = mach_read_from_8(undo_log_hdr + TRX_UNDO_TRX_NO); id = mach_read_from_8(block->frame + node_addr.boffset
+ TRX_UNDO_TRX_NO);
if (id > max_trx_id) { if (id > max_trx_id) {
max_trx_id = id; max_trx_id = id;
} }
unsigned purge = mach_read_from_2( unsigned purge = mach_read_from_2(block->frame
undo_log_hdr + TRX_UNDO_NEEDS_PURGE); + node_addr.boffset
+ TRX_UNDO_NEEDS_PURGE);
ut_ad(purge <= 1); ut_ad(purge <= 1);
rseg->set_last_trx_no(id, purge != 0); rseg->set_last_trx_no(id, purge != 0);
rseg->needs_purge = purge != 0; rseg->needs_purge = purge != 0;
@ -638,8 +643,8 @@ trx_rseg_array_init()
} }
/* Finally, clear WSREP XID in TRX_SYS page. */ /* Finally, clear WSREP XID in TRX_SYS page. */
const buf_block_t* sys = trx_sysf_get(&mtr); mlog_memset(trx_sysf_get(&mtr),
mlog_memset(TRX_SYS + TRX_SYS_WSREP_XID_INFO + sys->frame, TRX_SYS + TRX_SYS_WSREP_XID_INFO,
TRX_SYS_WSREP_XID_LEN, 0, &mtr); TRX_SYS_WSREP_XID_LEN, 0, &mtr);
mtr.commit(); mtr.commit();
} }
@ -765,8 +770,8 @@ up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header @param[in,out] rseg_header rollback segment header
@param[in] trx committing transaction @param[in] trx committing transaction
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr) mtr_t *mtr)
{ {
DBUG_LOG("trx", "trx_mysql_binlog_offset: " << trx->mysql_log_offset); DBUG_LOG("trx", "trx_mysql_binlog_offset: " << trx->mysql_log_offset);
@ -778,9 +783,11 @@ trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr)
return; return;
} }
mlog_write_ull(rseg_header + TRX_RSEG_BINLOG_OFFSET, mtr->write<8,mtr_t::OPT>(*rseg_header,
trx->mysql_log_offset, mtr); TRX_RSEG + TRX_RSEG_BINLOG_OFFSET
byte* p = rseg_header + TRX_RSEG_BINLOG_NAME; + rseg_header->frame,
trx->mysql_log_offset);
byte* p = TRX_RSEG + TRX_RSEG_BINLOG_NAME + rseg_header->frame;
const byte* binlog_name = reinterpret_cast<const byte*> const byte* binlog_name = reinterpret_cast<const byte*>
(trx->mysql_log_file_name); (trx->mysql_log_file_name);

View File

@ -147,8 +147,6 @@ trx_sysf_create(
{ {
ulint slot_no; ulint slot_no;
buf_block_t* block; buf_block_t* block;
page_t* page;
byte* ptr;
ut_ad(mtr); ut_ad(mtr);
@ -167,30 +165,28 @@ trx_sysf_create(
ut_a(block->page.id.page_no() == TRX_SYS_PAGE_NO); ut_a(block->page.id.page_no() == TRX_SYS_PAGE_NO);
page = buf_block_get_frame(block); mtr->write<2>(*block, FIL_PAGE_TYPE + block->frame,
FIL_PAGE_TYPE_TRX_SYS);
mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS, ut_ad(!mach_read_from_4(block->frame
MLOG_2BYTES, mtr); + TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_MAGIC));
/* Reset the doublewrite buffer magic number to zero so that we
know that the doublewrite buffer has not yet been created (this
suppresses a Valgrind warning) */
mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
/* Reset the rollback segment slots. Old versions of InnoDB /* Reset the rollback segment slots. Old versions of InnoDB
(before MySQL 5.5) define TRX_SYS_N_RSEGS as 256 and expect (before MySQL 5.5) define TRX_SYS_N_RSEGS as 256 and expect
that the whole array is initialized. */ that the whole array is initialized. */
ptr = TRX_SYS + TRX_SYS_RSEGS + page;
compile_time_assert(256 >= TRX_SYS_N_RSEGS); compile_time_assert(256 >= TRX_SYS_N_RSEGS);
memset(ptr, 0xff, 256 * TRX_SYS_RSEG_SLOT_SIZE); compile_time_assert(TRX_SYS + TRX_SYS_RSEGS
ptr += 256 * TRX_SYS_RSEG_SLOT_SIZE; + 256 * TRX_SYS_RSEG_SLOT_SIZE
ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END)); <= UNIV_PAGE_SIZE_MIN - FIL_PAGE_DATA_END);
mlog_memset(block, TRX_SYS + TRX_SYS_RSEGS,
256 * TRX_SYS_RSEG_SLOT_SIZE, 0xff, mtr);
/* Initialize all of the page. This part used to be uninitialized. */ /* Initialize all of the page. This part used to be uninitialized. */
mlog_memset(block, ptr - page, mlog_memset(block, TRX_SYS + TRX_SYS_RSEGS
srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr), + 256 * TRX_SYS_RSEG_SLOT_SIZE,
srv_page_size
- (FIL_PAGE_DATA_END + TRX_SYS + TRX_SYS_RSEGS
+ 256 * TRX_SYS_RSEG_SLOT_SIZE),
0, mtr); 0, mtr);
/* Create the first rollback segment in the SYSTEM tablespace */ /* Create the first rollback segment in the SYSTEM tablespace */

View File

@ -565,8 +565,6 @@ trx_resurrect_table_locks(
const trx_undo_t* undo) /*!< in: undo log */ const trx_undo_t* undo) /*!< in: undo log */
{ {
mtr_t mtr; mtr_t mtr;
page_t* undo_page;
trx_undo_rec_t* undo_rec;
table_id_set tables; table_id_set tables;
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) ||
@ -581,11 +579,11 @@ trx_resurrect_table_locks(
/* trx_rseg_mem_create() may have acquired an X-latch on this /* trx_rseg_mem_create() may have acquired an X-latch on this
page, so we cannot acquire an S-latch. */ page, so we cannot acquire an S-latch. */
undo_page = trx_undo_page_get( buf_block_t* block = trx_undo_page_get(
page_id_t(trx->rsegs.m_redo.rseg->space->id, page_id_t(trx->rsegs.m_redo.rseg->space->id,
undo->top_page_no), &mtr); undo->top_page_no), &mtr);
buf_block_t* undo_block = block;
undo_rec = undo_page + undo->top_offset; trx_undo_rec_t* undo_rec = block->frame + undo->top_offset;
do { do {
ulint type; ulint type;
@ -594,11 +592,9 @@ trx_resurrect_table_locks(
ulint cmpl_info; ulint cmpl_info;
bool updated_extern; bool updated_extern;
page_t* undo_rec_page = page_align(undo_rec); if (undo_block != block) {
mtr.memo_release(undo_block, MTR_MEMO_PAGE_X_FIX);
if (undo_rec_page != undo_page) { undo_block = block;
mtr.release_page(undo_page, MTR_MEMO_PAGE_X_FIX);
undo_page = undo_rec_page;
} }
trx_undo_rec_get_pars( trx_undo_rec_get_pars(
@ -607,7 +603,7 @@ trx_resurrect_table_locks(
tables.insert(table_id); tables.insert(table_id);
undo_rec = trx_undo_get_prev_rec( undo_rec = trx_undo_get_prev_rec(
undo_rec, undo->hdr_page_no, block, page_offset(undo_rec), undo->hdr_page_no,
undo->hdr_offset, false, &mtr); undo->hdr_offset, false, &mtr);
} while (undo_rec); } while (undo_rec);

File diff suppressed because it is too large Load Diff