polardbxengine/storage/innobase/include/trx0rseg.ic

234 lines
7.8 KiB
Plaintext

/*****************************************************************************
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License, version 2.0, as published by the
Free Software Foundation.
This program is also distributed with certain software (including but not
limited to OpenSSL) that is licensed under separate terms, as designated in a
particular file or component or in included license documentation. The authors
of MySQL hereby grant you an additional permission to link the program and
your derivative works with the separately licensed software that they have
included with MySQL.
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, version 2.0,
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
/** @file include/trx0rseg.ic
Rollback segment
Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "mtr0log.h"
#include "srv0srv.h"
#include "trx0purge.h"
#include "trx0sys.h"
/** Gets a rollback segment header.
@param[in] space space where placed
@param[in] page_no page number of the header
@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
trx_rsegf_t *trx_rsegf_get(space_id_t space, page_no_t page_no,
const page_size_t &page_size, mtr_t *mtr) {
buf_block_t *block;
trx_rsegf_t *header;
block = buf_page_get(page_id_t(space, page_no), page_size, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
header = TRX_RSEG + buf_block_get_frame(block);
return (header);
}
/** Gets a newly created rollback segment header.
@param[in] space space where placed
@param[in] page_no page number of the header
@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return rollback segment header, page x-latched */
UNIV_INLINE
trx_rsegf_t *trx_rsegf_get_new(space_id_t space, page_no_t page_no,
const page_size_t &page_size, mtr_t *mtr) {
buf_block_t *block;
trx_rsegf_t *header;
block = buf_page_get(page_id_t(space, page_no), page_size, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
header = TRX_RSEG + buf_block_get_frame(block);
return (header);
}
/** Gets the file page number of the nth undo log slot.
@return page number of the undo log segment */
UNIV_INLINE
page_no_t trx_rsegf_get_nth_undo(
trx_rsegf_t *rsegf, /*!< in: rollback segment header */
ulint n, /*!< in: index of slot */
mtr_t *mtr) /*!< in: mtr */
{
ut_a(n < TRX_RSEG_N_SLOTS);
return (mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
MLOG_4BYTES, 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 */
page_no_t 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(
trx_rsegf_t *rsegf, /*!< in: rollback segment header */
mtr_t *mtr) /*!< in: mtr */
{
ulint i;
page_no_t 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, mtr);
if (page_no == FIL_NULL) {
return (i);
}
}
return (ULINT_UNDEFINED);
}
/** Convert a 7-bit ID stored in a rollback pointer to an undo space ID.
Before 8.0, this ID is called an rseg_id and is a slot in the TRX_SYS page
where the space_id can be read.
After 8.0 this is an undo space number which can be converted directly to
an undo space ID.
@param[in] id a 7-bit ID from a rollback pointer
@param[in] is_temp true if rseg from Temp Tablespace else false.
@return undo tablespace ID containing the rollback segment */
inline space_id_t trx_rseg_id_to_space_id(ulint id, bool is_temp) {
/* The rseg_id must be an undo_space_num between 0 and 127. */
ut_ad(id < TRX_SYS_N_RSEGS);
/* MySQL versions before v5.7.2 used the first 32 slots in the
TRX_SYS page for redo rollback segments. v5.7.2 uses these seg_ids
for no-redo rollback segments in the temporary tablespace.
v8 will once again use them for durable/redo rollback segments. */
if (is_temp) {
return (srv_tmp_space.space_id());
}
/* If the ID is 0 then use the system tablespace. */
if (id == 0) {
return (TRX_SYS_SPACE);
}
if (srv_upgrade_old_undo_found) {
/* Interpret the id as a slot in the TRX_SYS page. */
trx_rseg_t *rseg = trx_sys->rsegs.find(id);
return (rseg->space_id);
}
/* We assume at this point that all undo tablespaces have
reserved space_ids and RSEG_ARRAY pages. */
ut_ad(!undo::spaces->empty());
/* The space_id_bank for this slot cannot change since this call is done
by purge or MVCC. This space_id can only change during truncate when
there are no more undo logs in this undo tablespace. */
space_id_t space_id = undo::num2id(static_cast<space_id_t>(id));
ut_ad(space_id != SPACE_UNKNOWN);
return (space_id);
}
/** Get a pointer to the rollback segment directory header and x-latches its
page.
@param[in] space_id Undo Tablespace ID
@param[in] mtr mtr
@return pointer to rollback segment directory header with page x-latched. */
inline trx_rsegsf_t *trx_rsegsf_get(space_id_t space_id, mtr_t *mtr) {
buf_block_t *block;
trx_rsegsf_t *rsegs_header;
ut_ad(mtr != nullptr);
ut_ad(undo::is_reserved(space_id));
block = buf_page_get(page_id_t(space_id, FSP_RSEG_ARRAY_PAGE_NO),
univ_page_size, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_ARRAY_HEADER);
rsegs_header = RSEG_ARRAY_HEADER + buf_block_get_frame(block);
return (rsegs_header);
}
/** Get the page number of the nth rollback segment slot in the
RSEG_ARRAY page for this undo tablespace.
@param[in] rsegs_header rollback segment array page header
@param[in] slot slot index == rseg id
@param[in] mtr mtr
@return page number, FIL_NULL if slot unused */
inline page_no_t trx_rsegsf_get_page_no(trx_rsegsf_t *rsegs_header, ulint slot,
mtr_t *mtr) {
ut_ad(rsegs_header != nullptr);
ut_ad(mtr != nullptr);
ut_ad(slot < FSP_MAX_ROLLBACK_SEGMENTS);
return (mtr_read_ulint(
rsegs_header + RSEG_ARRAY_PAGES_OFFSET + slot * RSEG_ARRAY_SLOT_SIZE,
MLOG_4BYTES, mtr));
}
/** Sets the page number of the nth rollback segment slot in the
independent undo tablespace.
@param[in] rsegs_header rollback segment array page header
@param[in] slot slot number on page == rseg id
@param[in] page_no rollback regment header page number
@param[in] mtr mtr */
UNIV_INLINE
void trx_rsegsf_set_page_no(trx_rsegsf_t *rsegs_header, ulint slot,
page_no_t page_no, mtr_t *mtr) {
ut_ad(rsegs_header);
mlog_write_ulint(
rsegs_header + RSEG_ARRAY_PAGES_OFFSET + slot * RSEG_ARRAY_SLOT_SIZE,
page_no, MLOG_4BYTES, mtr);
}