281 lines
7.5 KiB
Plaintext
281 lines
7.5 KiB
Plaintext
/*****************************************************************************
|
|
|
|
Copyright (c) 1995, 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/mtr0mtr.ic
|
|
Mini-transaction buffer
|
|
|
|
Created 11/26/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "buf0buf.h"
|
|
|
|
/**
|
|
Pushes an object to an mtr memo stack. */
|
|
void mtr_t::memo_push(void *object, mtr_memo_type_t type) {
|
|
ut_ad(is_active());
|
|
ut_ad(object != NULL);
|
|
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
|
|
ut_ad(type <= MTR_MEMO_SX_LOCK);
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
ut_ad(ut_is_2pow(type));
|
|
|
|
/* If this mtr has x-fixed a clean page then we set
|
|
the made_dirty flag. This tells us if we need
|
|
insert the dirtied page to the flush list in mtr_commit. */
|
|
|
|
if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) &&
|
|
!m_impl.m_made_dirty) {
|
|
m_impl.m_made_dirty =
|
|
is_block_dirtied(reinterpret_cast<const buf_block_t *>(object));
|
|
} else if (type == MTR_MEMO_BUF_FIX && !m_impl.m_made_dirty) {
|
|
if (reinterpret_cast<const buf_block_t *>(object)
|
|
->made_dirty_with_no_latch) {
|
|
m_impl.m_made_dirty = true;
|
|
}
|
|
}
|
|
|
|
mtr_memo_slot_t *slot;
|
|
|
|
slot = m_impl.m_memo.push<mtr_memo_slot_t *>(sizeof(*slot));
|
|
|
|
slot->type = type;
|
|
slot->object = object;
|
|
}
|
|
|
|
/**
|
|
Releases the (index tree) s-latch stored in an mtr memo after a
|
|
savepoint. */
|
|
void mtr_t::release_s_latch_at_savepoint(ulint savepoint, rw_lock_t *lock) {
|
|
#ifndef UNIV_HOTBACKUP
|
|
ut_ad(is_active());
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
|
|
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
|
|
mtr_memo_slot_t *slot = m_impl.m_memo.at<mtr_memo_slot_t *>(savepoint);
|
|
|
|
ut_ad(slot->object == lock);
|
|
ut_ad(slot->type == MTR_MEMO_S_LOCK);
|
|
|
|
rw_lock_s_unlock(lock);
|
|
|
|
slot->object = NULL;
|
|
#else /* !UNIV_HOTBACKUP */
|
|
UT_NOT_USED(savepoint);
|
|
UT_NOT_USED(lock);
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
}
|
|
|
|
void mtr_t::release_sx_latch_at_savepoint(ulint savepoint, rw_lock_t *lock) {
|
|
#ifndef UNIV_HOTBACKUP
|
|
ut_ad(is_active());
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
|
|
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
|
|
mtr_memo_slot_t *slot = m_impl.m_memo.at<mtr_memo_slot_t *>(savepoint);
|
|
|
|
ut_ad(slot->object == lock);
|
|
ut_ad(slot->type == MTR_MEMO_SX_LOCK);
|
|
|
|
rw_lock_sx_unlock(lock);
|
|
|
|
slot->object = NULL;
|
|
#else /* !UNIV_HOTBACKUP */
|
|
UT_NOT_USED(savepoint);
|
|
UT_NOT_USED(lock);
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
}
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**
|
|
SX-latches the not yet latched block after a savepoint. */
|
|
|
|
void mtr_t::sx_latch_at_savepoint(ulint savepoint, buf_block_t *block) {
|
|
ut_ad(is_active());
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
|
|
ut_ad(!memo_contains_flagged(
|
|
block, MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
|
|
|
|
mtr_memo_slot_t *slot;
|
|
|
|
slot = m_impl.m_memo.at<mtr_memo_slot_t *>(savepoint);
|
|
|
|
ut_ad(slot->object == block);
|
|
|
|
/* == RW_NO_LATCH */
|
|
ut_a(slot->type == MTR_MEMO_BUF_FIX);
|
|
|
|
rw_lock_sx_lock(&block->lock);
|
|
|
|
if (!m_impl.m_made_dirty) {
|
|
m_impl.m_made_dirty = is_block_dirtied(block);
|
|
}
|
|
|
|
slot->type = MTR_MEMO_PAGE_SX_FIX;
|
|
}
|
|
|
|
/**
|
|
X-latches the not yet latched block after a savepoint. */
|
|
|
|
void mtr_t::x_latch_at_savepoint(ulint savepoint, buf_block_t *block) {
|
|
ut_ad(is_active());
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
|
|
ut_ad(!memo_contains_flagged(
|
|
block, MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
|
|
|
|
mtr_memo_slot_t *slot;
|
|
|
|
slot = m_impl.m_memo.at<mtr_memo_slot_t *>(savepoint);
|
|
|
|
ut_ad(slot->object == block);
|
|
|
|
/* == RW_NO_LATCH */
|
|
ut_a(slot->type == MTR_MEMO_BUF_FIX);
|
|
|
|
rw_lock_x_lock(&block->lock);
|
|
|
|
if (!m_impl.m_made_dirty) {
|
|
m_impl.m_made_dirty = is_block_dirtied(block);
|
|
}
|
|
|
|
slot->type = MTR_MEMO_PAGE_X_FIX;
|
|
}
|
|
|
|
/**
|
|
Releases the block in an mtr memo after a savepoint. */
|
|
|
|
void mtr_t::release_block_at_savepoint(ulint savepoint, buf_block_t *block) {
|
|
ut_ad(is_active());
|
|
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
|
|
mtr_memo_slot_t *slot;
|
|
|
|
slot = m_impl.m_memo.at<mtr_memo_slot_t *>(savepoint);
|
|
|
|
ut_a(slot->object == block);
|
|
|
|
buf_block_unfix(reinterpret_cast<buf_block_t *>(block));
|
|
|
|
buf_page_release_latch(block, slot->type);
|
|
|
|
slot->object = NULL;
|
|
}
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/**
|
|
Gets the logging mode of a mini-transaction.
|
|
@return logging mode: MTR_LOG_NONE, ... */
|
|
|
|
mtr_log_t mtr_t::get_log_mode() const {
|
|
ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL);
|
|
ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS);
|
|
|
|
return (m_impl.m_log_mode);
|
|
}
|
|
|
|
/**
|
|
Changes the logging mode of a mini-transaction.
|
|
@return old mode */
|
|
|
|
mtr_log_t mtr_t::set_log_mode(mtr_log_t mode) {
|
|
ut_ad(mode >= MTR_LOG_ALL);
|
|
ut_ad(mode <= MTR_LOG_SHORT_INSERTS);
|
|
|
|
const mtr_log_t old_mode = m_impl.m_log_mode;
|
|
|
|
switch (old_mode) {
|
|
case MTR_LOG_NO_REDO:
|
|
/* Once this mode is set, it must not be changed. */
|
|
ut_ad(mode == MTR_LOG_NO_REDO || mode == MTR_LOG_NONE);
|
|
return (old_mode);
|
|
case MTR_LOG_NONE:
|
|
if (mode == old_mode || mode == MTR_LOG_SHORT_INSERTS) {
|
|
/* Keep MTR_LOG_NONE. */
|
|
return (old_mode);
|
|
}
|
|
/* fall through */
|
|
case MTR_LOG_SHORT_INSERTS:
|
|
ut_ad(mode == MTR_LOG_ALL);
|
|
/* fall through */
|
|
case MTR_LOG_ALL:
|
|
/* MTR_LOG_NO_REDO can only be set before generating
|
|
any redo log records. */
|
|
ut_ad(mode != MTR_LOG_NO_REDO || m_impl.m_n_log_recs == 0);
|
|
m_impl.m_log_mode = mode;
|
|
return (old_mode);
|
|
}
|
|
|
|
ut_ad(0);
|
|
return (old_mode);
|
|
}
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**
|
|
Locks a lock in s-mode. */
|
|
|
|
void mtr_t::s_lock(rw_lock_t *lock, const char *file, ulint line) {
|
|
rw_lock_s_lock_inline(lock, 0, file, line);
|
|
|
|
memo_push(lock, MTR_MEMO_S_LOCK);
|
|
}
|
|
|
|
/**
|
|
Locks a lock in x-mode. */
|
|
|
|
void mtr_t::x_lock(rw_lock_t *lock, const char *file, ulint line) {
|
|
rw_lock_x_lock_inline(lock, 0, file, line);
|
|
|
|
memo_push(lock, MTR_MEMO_X_LOCK);
|
|
}
|
|
|
|
/**
|
|
Locks a lock in sx-mode. */
|
|
|
|
void mtr_t::sx_lock(rw_lock_t *lock, const char *file, ulint line) {
|
|
rw_lock_sx_lock_inline(lock, 0, file, line);
|
|
|
|
memo_push(lock, MTR_MEMO_SX_LOCK);
|
|
}
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/**
|
|
Reads 1 - 4 bytes from a file page buffered in the buffer pool.
|
|
@return value read */
|
|
|
|
uint32_t mtr_t::read_ulint(const byte *ptr, mlog_id_t type) const {
|
|
ut_ad(is_active());
|
|
|
|
ut_ad(memo_contains_page_flagged(
|
|
ptr, MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
|
|
|
|
return (mach_read_ulint(ptr, type));
|
|
}
|