summaryrefslogtreecommitdiff
path: root/storage/innobase/include/mtr0mtr.inl
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/mtr0mtr.inl')
-rw-r--r--storage/innobase/include/mtr0mtr.inl229
1 files changed, 229 insertions, 0 deletions
diff --git a/storage/innobase/include/mtr0mtr.inl b/storage/innobase/include/mtr0mtr.inl
new file mode 100644
index 00000000000..c35de2bcbf9
--- /dev/null
+++ b/storage/innobase/include/mtr0mtr.inl
@@ -0,0 +1,229 @@
+/*****************************************************************************
+
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, 2021, MariaDB Corporation.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file include/mtr0mtr.ic
+Mini-transaction buffer
+
+Created 11/26/1995 Heikki Tuuri
+*******************************************************/
+
+#include "buf0buf.h"
+
+/** Check if a mini-transaction is dirtying a clean page.
+@return true if the mtr is dirtying a clean page. */
+bool
+mtr_t::is_block_dirtied(const buf_block_t* block)
+{
+ ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
+ ut_ad(block->page.buf_fix_count > 0);
+
+ /* It is OK to read oldest_modification because no
+ other thread can be performing a write of it and it
+ is only during write that the value is reset to 0. */
+ return(block->page.oldest_modification == 0);
+}
+
+/**
+Pushes an object to an mtr memo stack. */
+void
+mtr_t::memo_push(void* object, mtr_memo_type_t type)
+{
+ ut_ad(is_active());
+ ut_ad(object != NULL);
+ ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
+ ut_ad(type <= MTR_MEMO_SPACE_X_LOCK);
+ 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 to
+ grab log_sys.flush_order_mutex at mtr_t::commit() so that we
+ can insert the dirtied page into the flush list. */
+
+ if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX)
+ && !m_made_dirty) {
+
+ m_made_dirty = is_block_dirtied(
+ reinterpret_cast<const buf_block_t*>(object));
+ }
+
+ mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
+
+ slot->type = type;
+ slot->object = object;
+}
+
+/**
+Releases the (index tree) s-latch stored in an mtr memo after a
+savepoint. */
+void
+mtr_t::release_s_latch_at_savepoint(
+ ulint savepoint,
+ rw_lock_t* lock)
+{
+ ut_ad(is_active());
+ ut_ad(m_memo.size() > savepoint);
+
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
+
+ ut_ad(slot->object == lock);
+ ut_ad(slot->type == MTR_MEMO_S_LOCK);
+
+ rw_lock_s_unlock(lock);
+
+ slot->object = NULL;
+}
+
+/**
+SX-latches the not yet latched block after a savepoint. */
+
+void
+mtr_t::sx_latch_at_savepoint(
+ ulint savepoint,
+ buf_block_t* block)
+{
+ ut_ad(is_active());
+ ut_ad(m_memo.size() > savepoint);
+
+ ut_ad(!memo_contains_flagged(
+ block,
+ MTR_MEMO_PAGE_S_FIX
+ | MTR_MEMO_PAGE_X_FIX
+ | MTR_MEMO_PAGE_SX_FIX));
+
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
+
+ ut_ad(slot->object == block);
+
+ /* == RW_NO_LATCH */
+ ut_a(slot->type == MTR_MEMO_BUF_FIX);
+
+ rw_lock_sx_lock(&block->lock);
+
+ if (!m_made_dirty) {
+ m_made_dirty = is_block_dirtied(block);
+ }
+
+ slot->type = MTR_MEMO_PAGE_SX_FIX;
+}
+
+/**
+X-latches the not yet latched block after a savepoint. */
+
+void
+mtr_t::x_latch_at_savepoint(
+ ulint savepoint,
+ buf_block_t* block)
+{
+ ut_ad(is_active());
+ ut_ad(m_memo.size() > savepoint);
+
+ ut_ad(!memo_contains_flagged(
+ block,
+ MTR_MEMO_PAGE_S_FIX
+ | MTR_MEMO_PAGE_X_FIX
+ | MTR_MEMO_PAGE_SX_FIX));
+
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
+
+ ut_ad(slot->object == block);
+
+ /* == RW_NO_LATCH */
+ ut_a(slot->type == MTR_MEMO_BUF_FIX);
+
+ rw_lock_x_lock(&block->lock);
+
+ if (!m_made_dirty) {
+ m_made_dirty = is_block_dirtied(block);
+ }
+
+ slot->type = MTR_MEMO_PAGE_X_FIX;
+}
+
+/**
+Releases the block in an mtr memo after a savepoint. */
+
+void
+mtr_t::release_block_at_savepoint(
+ ulint savepoint,
+ buf_block_t* block)
+{
+ ut_ad(is_active());
+
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
+
+ ut_a(slot->object == block);
+
+ buf_page_release_latch(block, slot->type);
+
+ reinterpret_cast<buf_block_t*>(block)->unfix();
+
+ slot->object = NULL;
+}
+
+/**
+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_log_mode >= MTR_LOG_ALL);
+ ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS);
+
+ return 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_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_n_log_recs == 0);
+ m_log_mode = mode;
+ return(old_mode);
+ }
+
+ ut_ad(0);
+ return(old_mode);
+}