diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-11-12 16:30:57 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-11-12 16:42:58 +0200 |
commit | 5098d708a07f90484c9e13fe3ab58113a8a10191 (patch) | |
tree | 961759bb9b339d82a3d32b1e4cb35ee21c758769 /storage/innobase | |
parent | d103c5a489d1d96c967c90f25fefc4aa0083ed07 (diff) | |
parent | 2570cb8b91711b38e4a448cc92b95e49abb218b4 (diff) | |
download | mariadb-git-5098d708a07f90484c9e13fe3ab58113a8a10191.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/include/mtr0mtr.h | 238 | ||||
-rw-r--r-- | storage/innobase/include/mtr0mtr.ic | 55 | ||||
-rw-r--r-- | storage/innobase/include/mtr0types.h | 19 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 53 | ||||
-rw-r--r-- | storage/innobase/mtr/mtr0mtr.cc | 382 |
5 files changed, 248 insertions, 499 deletions
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 4b41506d339..3ca753d06e4 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 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 @@ -134,62 +134,7 @@ struct mtr_memo_slot_t { /** Mini-transaction handle and buffer */ struct mtr_t { - - /** State variables of the mtr */ - struct Impl { - - /** memo stack for locks etc. */ - mtr_buf_t m_memo; - - /** mini-transaction log */ - mtr_buf_t m_log; - - /** true if mtr has made at least one buffer pool page dirty */ - bool m_made_dirty; - - /** true if inside ibuf changes */ - bool m_inside_ibuf; - - /** true if the mini-transaction modified buffer pool pages */ - bool m_modifications; - - /** Count of how many page initial log records have been - written to the mtr log */ - ib_uint32_t m_n_log_recs; - - /** specifies which operations should be logged; default - value MTR_LOG_ALL */ - mtr_log_t m_log_mode; -#ifdef UNIV_DEBUG - /** Persistent user tablespace associated with the - mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ - ulint m_user_space_id; -#endif /* UNIV_DEBUG */ - /** User tablespace that is being modified by the - mini-transaction */ - fil_space_t* m_user_space; - - /** State of the transaction */ - mtr_state_t m_state; - - /** Flush Observer */ - FlushObserver* m_flush_observer; - -#ifdef UNIV_DEBUG - /** For checking corruption. */ - ulint m_magic_n; -#endif /* UNIV_DEBUG */ - - /** Owning mini-transaction */ - mtr_t* m_mtr; - }; - - mtr_t() - { - m_impl.m_state = MTR_STATE_INIT; - } - - ~mtr_t() { } + mtr_t() : m_state(MTR_STATE_INIT) {} /** Start a mini-transaction. */ void start(); @@ -211,14 +156,7 @@ struct mtr_t { /** Return current size of the buffer. @return savepoint */ - ulint get_savepoint() const - MY_ATTRIBUTE((warn_unused_result)) - { - ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(m_impl.m_memo.size()); - } + ulint get_savepoint() const {ut_ad(is_active()); return m_memo.size();} /** Release the (index tree) s-latch stored in an mtr memo after a savepoint. @@ -255,11 +193,11 @@ struct mtr_t { the same set of tablespaces as this one */ void set_spaces(const mtr_t& mtr) { - ut_ad(!m_impl.m_user_space_id); - ut_ad(!m_impl.m_user_space); + ut_ad(!m_user_space_id); + ut_ad(!m_user_space); - ut_d(m_impl.m_user_space_id = mtr.m_impl.m_user_space_id); - m_impl.m_user_space = mtr.m_impl.m_user_space; + ut_d(m_user_space_id = mtr.m_user_space_id); + m_user_space = mtr.m_user_space; } /** Set the tablespace associated with the mini-transaction @@ -268,16 +206,16 @@ struct mtr_t { @return the tablespace */ fil_space_t* set_named_space_id(ulint space_id) { - ut_ad(!m_impl.m_user_space_id); - ut_d(m_impl.m_user_space_id = space_id); + ut_ad(!m_user_space_id); + ut_d(m_user_space_id = space_id); if (!space_id) { return fil_system.sys_space; } else { - ut_ad(m_impl.m_user_space_id == space_id); - ut_ad(!m_impl.m_user_space); - m_impl.m_user_space = fil_space_get(space_id); - ut_ad(m_impl.m_user_space); - return m_impl.m_user_space; + ut_ad(m_user_space_id == space_id); + ut_ad(!m_user_space); + m_user_space = fil_space_get(space_id); + ut_ad(m_user_space); + return m_user_space; } } @@ -286,10 +224,10 @@ struct mtr_t { @param[in] space user or system tablespace */ void set_named_space(fil_space_t* space) { - ut_ad(!m_impl.m_user_space_id); - ut_d(m_impl.m_user_space_id = space->id); + ut_ad(!m_user_space_id); + ut_d(m_user_space_id = space->id); if (space->id) { - m_impl.m_user_space = space; + m_user_space = space; } } @@ -356,18 +294,12 @@ struct mtr_t { void release_page(const void* ptr, mtr_memo_type_t type); /** Note that the mini-transaction has modified data. */ - void set_modified() - { - m_impl.m_modifications = true; - } + void set_modified() { m_modifications = true; } /** Set the state to not-modified. This will not log the changes. This is only used during redo log apply, to avoid logging the changes. */ - void discard_modifications() - { - m_impl.m_modifications = false; - } + void discard_modifications() { m_modifications = false; } /** Get the LSN of commit(). @return the commit LSN @@ -379,45 +311,28 @@ struct mtr_t { } /** Note that we are inside the change buffer code. */ - void enter_ibuf() - { - m_impl.m_inside_ibuf = true; - } + void enter_ibuf() { m_inside_ibuf = true; } /** Note that we have exited from the change buffer code. */ - void exit_ibuf() - { - m_impl.m_inside_ibuf = false; - } + void exit_ibuf() { m_inside_ibuf = false; } /** @return true if we are inside the change buffer code */ - bool is_inside_ibuf() const - { - return(m_impl.m_inside_ibuf); - } + bool is_inside_ibuf() const { return m_inside_ibuf; } /* @return true if the mini-transaction is active */ - bool is_active() const - { - return(m_impl.m_state == MTR_STATE_ACTIVE); - } + bool is_active() const { return m_state == MTR_STATE_ACTIVE; } /** Get flush observer @return flush observer */ - FlushObserver* get_flush_observer() const - { - return(m_impl.m_flush_observer); - } + FlushObserver* get_flush_observer() const { return m_flush_observer; } /** Set flush observer @param[in] observer flush observer */ void set_flush_observer(FlushObserver* observer) { - ut_ad(observer == NULL - || m_impl.m_log_mode == MTR_LOG_NO_REDO); - - m_impl.m_flush_observer = observer; + ut_ad(observer == NULL || m_log_mode == MTR_LOG_NO_REDO); + m_flush_observer = observer; } #ifdef UNIV_DEBUG @@ -457,65 +372,31 @@ struct mtr_t { void print() const; /** @return true if the mini-transaction has committed */ - bool has_committed() const - { - return(m_impl.m_state == MTR_STATE_COMMITTED); - } - - /** @return true if the mini-transaction is committing */ - bool is_committing() const - { - return(m_impl.m_state == MTR_STATE_COMMITTING); - } + bool has_committed() const { return m_state == MTR_STATE_COMMITTED; } /** @return true if mini-transaction contains modifications. */ - bool has_modifications() const - { - return(m_impl.m_modifications); - } + bool has_modifications() const { return m_modifications; } /** @return the memo stack */ - const mtr_buf_t* get_memo() const - { - return(&m_impl.m_memo); - } + const mtr_buf_t* get_memo() const { return &m_memo; } /** @return the memo stack */ - mtr_buf_t* get_memo() - { - return(&m_impl.m_memo); - } + mtr_buf_t* get_memo() { return &m_memo; } #endif /* UNIV_DEBUG */ /** @return true if a record was added to the mini-transaction */ - bool is_dirty() const - { - return(m_impl.m_made_dirty); - } + bool is_dirty() const { return m_made_dirty; } /** Note that a record has been added to the log */ - void added_rec() - { - ++m_impl.m_n_log_recs; - } + void added_rec() { ++m_n_log_recs; } /** Get the buffered redo log of this mini-transaction. @return redo log */ - const mtr_buf_t* get_log() const - { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(&m_impl.m_log); - } + const mtr_buf_t* get_log() const { return &m_log; } /** Get the buffered redo log of this mini-transaction. @return redo log */ - mtr_buf_t* get_log() - { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(&m_impl.m_log); - } + mtr_buf_t* get_log() { return &m_log; } /** Push an object to an mtr memo stack. @param object object @@ -529,15 +410,56 @@ struct mtr_t { MY_ATTRIBUTE((warn_unused_result)); private: - class Command; + /** Prepare to write the mini-transaction log to the redo log buffer. + @return number of bytes to write in finish_write() */ + inline ulint prepare_write(); - friend class Command; + /** Append the redo log records to the redo log buffer. + @param[in] len number of bytes to write + @return start_lsn */ + inline lsn_t finish_write(ulint len); -private: - Impl m_impl; + /** Release the resources */ + inline void release_resources(); + + /** memo stack for locks etc. */ + mtr_buf_t m_memo; + + /** mini-transaction log */ + mtr_buf_t m_log; + + /** true if mtr has made at least one buffer pool page dirty */ + bool m_made_dirty; + + /** true if inside ibuf changes */ + bool m_inside_ibuf; + + /** true if the mini-transaction modified buffer pool pages */ + bool m_modifications; + + /** Count of how many page initial log records have been + written to the mtr log */ + ib_uint32_t m_n_log_recs; + + /** specifies which operations should be logged; default + value MTR_LOG_ALL */ + mtr_log_t m_log_mode; +#ifdef UNIV_DEBUG + /** Persistent user tablespace associated with the + mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ + ulint m_user_space_id; +#endif /* UNIV_DEBUG */ + /** User tablespace that is being modified by the mini-transaction */ + fil_space_t* m_user_space; + + /** State of the transaction */ + mtr_state_t m_state; + + /** Flush Observer */ + FlushObserver* m_flush_observer; /** LSN at commit time */ - volatile lsn_t m_commit_lsn; + lsn_t m_commit_lsn; }; #include "mtr0mtr.ic" diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 574d0de24a5..7175ede0d6a 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) 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 @@ -58,15 +57,13 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) can insert the dirtied page to the flush list. */ if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) - && !m_impl.m_made_dirty) { + && !m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied( + m_made_dirty = is_block_dirtied( reinterpret_cast<const buf_block_t*>(object)); } - mtr_memo_slot_t* slot; - - slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot)); + mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot)); slot->type = type; slot->object = object; @@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint( rw_lock_t* lock) { ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - ut_ad(m_impl.m_memo.size() > savepoint); + ut_ad(m_memo.size() > savepoint); - mtr_memo_slot_t* slot = m_impl.m_memo.at<mtr_memo_slot_t*>(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); @@ -104,8 +99,7 @@ mtr_t::sx_latch_at_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(m_memo.size() > savepoint); ut_ad(!memo_contains_flagged( block, @@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint( | 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); + mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint); ut_ad(slot->object == block); @@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint( rw_lock_sx_lock(&block->lock); - if (!m_impl.m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied(block); + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); } slot->type = MTR_MEMO_PAGE_SX_FIX; @@ -140,8 +132,7 @@ mtr_t::x_latch_at_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(m_memo.size() > savepoint); ut_ad(!memo_contains_flagged( block, @@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint( | 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); + mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint); ut_ad(slot->object == block); @@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint( rw_lock_x_lock(&block->lock); - if (!m_impl.m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied(block); + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); } slot->type = MTR_MEMO_PAGE_X_FIX; @@ -176,11 +165,8 @@ mtr_t::release_block_at_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); + mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint); ut_a(slot->object == block); @@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction. 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); + ut_ad(m_log_mode >= MTR_LOG_ALL); + ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS); - return(m_impl.m_log_mode); + return m_log_mode; } /** @@ -214,7 +200,7 @@ 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; + const mtr_log_t old_mode = m_log_mode; switch (old_mode) { case MTR_LOG_NO_REDO: @@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode) 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; + ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0); + m_log_mode = mode; return(old_mode); } diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index 29e6fd042ab..da6686d77c8 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, 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 the terms of the GNU General Public License as published by the Free Software @@ -36,18 +36,18 @@ struct mtr_t; /** Logging modes for a mini-transaction */ enum mtr_log_t { /** Default mode: log all operations modifying disk-based data */ - MTR_LOG_ALL = 21, + MTR_LOG_ALL = 0, /** Log no operations and dirty pages are not added to the flush list. Set when applying log in crash recovery or when a modification of a ROW_FORMAT=COMPRESSED page is attempted. */ - MTR_LOG_NONE = 22, + MTR_LOG_NONE, /** Don't generate REDO log but add dirty pages to flush list */ - MTR_LOG_NO_REDO = 23, + MTR_LOG_NO_REDO, /** Inserts are logged in a shorter form */ - MTR_LOG_SHORT_INSERTS = 24 + MTR_LOG_SHORT_INSERTS }; /** @name Log item types @@ -271,15 +271,10 @@ enum mtr_memo_type_t { }; #endif /* !UNIV_CHECKSUM */ -#ifdef UNIV_DEBUG -# define MTR_MAGIC_N 54551 -#endif /* UNIV_DEBUG */ - enum mtr_state_t { MTR_STATE_INIT = 0, - MTR_STATE_ACTIVE = 12231, - MTR_STATE_COMMITTING = 56456, - MTR_STATE_COMMITTED = 34676 + MTR_STATE_ACTIVE, + MTR_STATE_COMMITTED }; #endif /* mtr0types_h */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index c6908a61dc2..e8a890de406 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri #include "univ.i" -#include <vector> #include <map> #include <string> #include <my_service_manager.h> @@ -3971,44 +3970,26 @@ recv_recovery_rollback_active(void) @param[in] page_no page number @return page frame @retval NULL if no page was found */ - const byte* recv_dblwr_t::find_page(ulint space_id, ulint page_no) { - typedef std::vector<const byte*, ut_allocator<const byte*> > - matches_t; - - matches_t matches; - const byte* result = 0; - - for (list::iterator i = pages.begin(); i != pages.end(); ++i) { - if (page_get_space_id(*i) == space_id - && page_get_page_no(*i) == page_no) { - matches.push_back(*i); - } - } - - if (matches.size() == 1) { - result = matches[0]; - } else if (matches.size() > 1) { - - lsn_t max_lsn = 0; - lsn_t page_lsn = 0; - - for (matches_t::iterator i = matches.begin(); - i != matches.end(); - ++i) { - - page_lsn = mach_read_from_8(*i + FIL_PAGE_LSN); - - if (page_lsn > max_lsn) { - max_lsn = page_lsn; - result = *i; - } - } - } - - return(result); + const byte *result= NULL; + lsn_t max_lsn= 0; + + for (list::const_iterator i = pages.begin(); i != pages.end(); ++i) + { + const byte *page= *i; + if (page_get_page_no(page) != page_no || + page_get_space_id(page) != space_id) + continue; + const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); + if (lsn <= max_lsn) + continue; + max_lsn= lsn; + result= page; + } + + return result; } #ifndef DBUG_OFF diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 5504eb618fe..6a022da9e5b 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -343,6 +343,7 @@ struct ReleaseAll { } }; +#ifdef UNIV_DEBUG /** Check that all slots have been handled. */ struct DebugCheck { /** @return true always. */ @@ -352,6 +353,7 @@ struct DebugCheck { return(true); } }; +#endif /** Release a resource acquired by the mini-transaction. */ struct ReleaseBlocks { @@ -404,59 +406,6 @@ struct ReleaseBlocks { FlushObserver* m_flush_observer; }; -class mtr_t::Command { -public: - /** Constructor. - Takes ownership of the mtr->m_impl, is responsible for deleting it. - @param[in,out] mtr mini-transaction */ - explicit Command(mtr_t* mtr) : m_impl(&mtr->m_impl), m_locks_released() - {} - - /** Destructor */ - ~Command() - { - ut_ad(m_impl == 0); - } - - /** Write the redo log record, add dirty pages to the flush list and - release the resources. */ - void execute(); - - /** Release the blocks used in this mini-transaction. */ - void release_blocks(); - - /** Release the latches acquired by the mini-transaction. */ - void release_latches(); - - /** Release both the latches and blocks used in the mini-transaction. */ - void release_all(); - - /** Release the resources */ - void release_resources(); - - /** Append the redo log records to the redo log buffer. - @param[in] len number of bytes to write */ - void finish_write(ulint len); - -private: - /** Prepare to write the mini-transaction log to the redo log buffer. - @return number of bytes to write in finish_write() */ - ulint prepare_write(); - - /** The mini-transaction state. */ - mtr_t::Impl* m_impl; - - /** Set to 1 after the user thread releases the latches. The log - writer thread must wait for this to be set to 1. */ - volatile ulint m_locks_released; - - /** Start lsn of the possible log entry for this mtr */ - lsn_t m_start_lsn; - - /** End lsn of the possible log entry for this mtr */ - lsn_t m_end_lsn; -}; - /** Write the block contents to the REDO log */ struct mtr_write_log_t { /** Append a block to the redo log buffer. @@ -490,76 +439,75 @@ mtr_write_log( /** Start a mini-transaction. */ void mtr_t::start() { - UNIV_MEM_INVALID(this, sizeof(*this)); - - UNIV_MEM_INVALID(&m_impl, sizeof(m_impl)); - - m_commit_lsn = 0; - - new(&m_impl.m_log) mtr_buf_t(); - new(&m_impl.m_memo) mtr_buf_t(); - - m_impl.m_mtr = this; - m_impl.m_log_mode = MTR_LOG_ALL; - m_impl.m_inside_ibuf = false; - m_impl.m_modifications = false; - m_impl.m_made_dirty = false; - m_impl.m_n_log_recs = 0; - m_impl.m_state = MTR_STATE_ACTIVE; - ut_d(m_impl.m_user_space_id = TRX_SYS_SPACE); - m_impl.m_user_space = NULL; - m_impl.m_flush_observer = NULL; - - ut_d(m_impl.m_magic_n = MTR_MAGIC_N); + UNIV_MEM_INVALID(this, sizeof *this); + + new(&m_memo) mtr_buf_t(); + new(&m_log) mtr_buf_t(); + + m_made_dirty= false; + m_inside_ibuf= false; + m_modifications= false; + m_n_log_recs= 0; + m_log_mode= MTR_LOG_ALL; + ut_d(m_user_space_id= TRX_SYS_SPACE); + m_user_space= NULL; + m_state= MTR_STATE_ACTIVE; + m_flush_observer= NULL; + m_commit_lsn= 0; } /** Release the resources */ -void -mtr_t::Command::release_resources() +inline void mtr_t::release_resources() { - ut_ad(m_impl->m_magic_n == MTR_MAGIC_N); - - /* Currently only used in commit */ - ut_ad(m_impl->m_state == MTR_STATE_COMMITTING); - - ut_d(m_impl->m_memo.for_each_block_in_reverse(CIterate<DebugCheck>())); - - /* Reset the mtr buffers */ - m_impl->m_log.erase(); - - m_impl->m_memo.erase(); - - m_impl->m_state = MTR_STATE_COMMITTED; - - m_impl = 0; + ut_d(m_memo.for_each_block_in_reverse(CIterate<DebugCheck>())); + m_log.erase(); + m_memo.erase(); + m_state= MTR_STATE_COMMITTED; } /** Commit a mini-transaction. */ void mtr_t::commit() { - ut_ad(is_active()); - ut_ad(!is_inside_ibuf()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - m_impl.m_state = MTR_STATE_COMMITTING; + ut_ad(is_active()); + ut_ad(!is_inside_ibuf()); - /* This is a dirty read, for debugging. */ - ut_ad(!m_impl.m_modifications || !recv_no_log_write); + /* This is a dirty read, for debugging. */ + ut_ad(!m_modifications || !recv_no_log_write); + ut_ad(!m_modifications || m_log_mode != MTR_LOG_NONE); - Command cmd(this); + if (m_modifications + && (m_n_log_recs || m_log_mode == MTR_LOG_NO_REDO)) + { + ut_ad(!srv_read_only_mode || m_log_mode == MTR_LOG_NO_REDO); - if (m_impl.m_modifications - && (m_impl.m_n_log_recs > 0 - || m_impl.m_log_mode == MTR_LOG_NO_REDO)) { + lsn_t start_lsn; - ut_ad(!srv_read_only_mode - || m_impl.m_log_mode == MTR_LOG_NO_REDO); + if (const ulint len= prepare_write()) + start_lsn= finish_write(len); + else + start_lsn= m_commit_lsn; - cmd.execute(); - } else { - cmd.release_all(); - cmd.release_resources(); - } + if (m_made_dirty) + log_flush_order_mutex_enter(); + + /* It is now safe to release the log mutex because the + flush_order mutex will ensure that we are the first one + to insert into the flush list. */ + log_mutex_exit(); + + m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks> + (ReleaseBlocks(start_lsn, m_commit_lsn, + m_flush_observer))); + if (m_made_dirty) + log_flush_order_mutex_exit(); + + m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>()); + } + else + m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>()); + + release_resources(); } /** Commit a mini-transaction that did not modify any pages, @@ -578,35 +526,31 @@ mtr_t::commit_checkpoint( ut_ad(log_mutex_own()); ut_ad(is_active()); ut_ad(!is_inside_ibuf()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(get_log_mode() == MTR_LOG_ALL); - ut_ad(!m_impl.m_made_dirty); - ut_ad(m_impl.m_memo.size() == 0); + ut_ad(!m_made_dirty); + ut_ad(m_memo.size() == 0); ut_ad(!srv_read_only_mode); - ut_d(m_impl.m_state = MTR_STATE_COMMITTING); - ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1); + ut_ad(write_mlog_checkpoint || m_n_log_recs > 1); - switch (m_impl.m_n_log_recs) { + switch (m_n_log_recs) { case 0: break; case 1: - *m_impl.m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; + *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; break; default: - mlog_catenate_ulint( - &m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); } if (write_mlog_checkpoint) { - byte* ptr = m_impl.m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT); + byte* ptr = m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT); compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8); *ptr = MLOG_CHECKPOINT; mach_write_to_8(ptr + 1, checkpoint_lsn); } - Command cmd(this); - cmd.finish_write(m_impl.m_log.size()); - cmd.release_resources(); + finish_write(m_log.size()); + release_resources(); if (write_mlog_checkpoint) { DBUG_PRINT("ib_log", @@ -623,8 +567,7 @@ mtr_t::commit_checkpoint( bool mtr_t::is_named_space(ulint space) const { - ut_ad(!m_impl.m_user_space - || m_impl.m_user_space->id != TRX_SYS_SPACE); + ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE); switch (get_log_mode()) { case MTR_LOG_NONE: @@ -632,7 +575,7 @@ mtr_t::is_named_space(ulint space) const return(true); case MTR_LOG_ALL: case MTR_LOG_SHORT_INSERTS: - return(m_impl.m_user_space_id == space + return(m_user_space_id == space || is_predefined_tablespace(space)); } @@ -645,21 +588,19 @@ mtr_t::is_named_space(ulint space) const @return whether the mini-transaction is associated with the space */ bool mtr_t::is_named_space(const fil_space_t* space) const { - ut_ad(!m_impl.m_user_space - || m_impl.m_user_space->id != TRX_SYS_SPACE); - - switch (get_log_mode()) { - case MTR_LOG_NONE: - case MTR_LOG_NO_REDO: - return true; - case MTR_LOG_ALL: - case MTR_LOG_SHORT_INSERTS: - return(m_impl.m_user_space == space - || is_predefined_tablespace(space->id)); - } - - ut_error; - return false; + ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE); + + switch (get_log_mode()) { + case MTR_LOG_NONE: + case MTR_LOG_NO_REDO: + return true; + case MTR_LOG_ALL: + case MTR_LOG_SHORT_INSERTS: + return m_user_space == space || is_predefined_tablespace(space->id); + } + + ut_error; + return false; } #endif /* UNIV_DEBUG */ @@ -674,12 +615,11 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) { fil_space_t* space; - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); if (space_id == TRX_SYS_SPACE) { space = fil_system.sys_space; - } else if ((space = m_impl.m_user_space) && space_id == space->id) { + } else if ((space = m_user_space) && space_id == space->id) { } else { space = fil_space_get(space_id); ut_ad(get_log_mode() != MTR_LOG_NO_REDO @@ -703,16 +643,15 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) bool mtr_t::memo_release(const void* object, ulint type) { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); /* We cannot release a page that has been written to in the middle of a mini-transaction. */ - ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); + ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX); Iterate<Find> iteration(Find(object, type)); - if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) { + if (!m_memo.for_each_block_in_reverse(iteration)) { memo_slot_release(iteration.functor.m_slot); return(true); } @@ -726,16 +665,15 @@ mtr_t::memo_release(const void* object, ulint type) void mtr_t::release_page(const void* ptr, mtr_memo_type_t type) { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); /* We cannot release a page that has been written to in the middle of a mini-transaction. */ - ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); + ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX); Iterate<FindPage> iteration(FindPage(ptr, type)); - if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) { + if (!m_memo.for_each_block_in_reverse(iteration)) { memo_slot_release(iteration.functor.get_slot()); return; } @@ -746,27 +684,20 @@ mtr_t::release_page(const void* ptr, mtr_memo_type_t type) /** Prepare to write the mini-transaction log to the redo log buffer. @return number of bytes to write in finish_write() */ -ulint -mtr_t::Command::prepare_write() +inline ulint mtr_t::prepare_write() { ut_ad(!recv_no_log_write); - switch (m_impl->m_log_mode) { - case MTR_LOG_SHORT_INSERTS: - ut_ad(0); - /* fall through */ - case MTR_LOG_NO_REDO: - case MTR_LOG_NONE: - ut_ad(m_impl->m_log.size() == 0); + if (UNIV_UNLIKELY(m_log_mode != MTR_LOG_ALL)) { + ut_ad(m_log_mode == MTR_LOG_NO_REDO); + ut_ad(m_log.size() == 0); log_mutex_enter(); - m_end_lsn = m_start_lsn = log_sys.lsn; - return(0); - case MTR_LOG_ALL: - break; + m_commit_lsn = log_sys.lsn; + return 0; } - ulint len = m_impl->m_log.size(); - ulint n_recs = m_impl->m_n_log_recs; + ulint len = m_log.size(); + ulint n_recs = m_n_log_recs; ut_ad(len > 0); ut_ad(n_recs > 0); @@ -774,9 +705,9 @@ mtr_t::Command::prepare_write() log_buffer_extend(ulong((len + 1) * 2)); } - ut_ad(m_impl->m_n_log_recs == n_recs); + ut_ad(m_n_log_recs == n_recs); - fil_space_t* space = m_impl->m_user_space; + fil_space_t* space = m_user_space; if (space != NULL && is_predefined_tablespace(space->id)) { /* Omit MLOG_FILE_NAME for predefined tablespaces. */ @@ -785,35 +716,32 @@ mtr_t::Command::prepare_write() log_mutex_enter(); - if (fil_names_write_if_was_clean(space, m_impl->m_mtr)) { + if (fil_names_write_if_was_clean(space, this)) { /* This mini-transaction was the first one to modify this tablespace since the latest checkpoint, so some MLOG_FILE_NAME records were appended to m_log. */ - ut_ad(m_impl->m_n_log_recs > n_recs); - mlog_catenate_ulint( - &m_impl->m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); - len = m_impl->m_log.size(); + ut_ad(m_n_log_recs > n_recs); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); + len = m_log.size(); } else { /* This was not the first time of dirtying a tablespace since the latest checkpoint. */ - ut_ad(n_recs == m_impl->m_n_log_recs); + ut_ad(n_recs == m_n_log_recs); if (n_recs <= 1) { ut_ad(n_recs == 1); /* Flag the single log record as the only record in this mini-transaction. */ - *m_impl->m_log.front()->begin() - |= MLOG_SINGLE_REC_FLAG; + *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; } else { /* Because this mini-transaction comprises multiple log records, append MLOG_MULTI_REC_END at the end. */ - mlog_catenate_ulint( - &m_impl->m_log, MLOG_MULTI_REC_END, - MLOG_1BYTE); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, + MLOG_1BYTE); len++; } } @@ -825,98 +753,37 @@ mtr_t::Command::prepare_write() } /** Append the redo log records to the redo log buffer -@param[in] len number of bytes to write */ -void -mtr_t::Command::finish_write( - ulint len) +@param[in] len number of bytes to write +@return start_lsn */ +inline lsn_t mtr_t::finish_write(ulint len) { - ut_ad(m_impl->m_log_mode == MTR_LOG_ALL); + ut_ad(m_log_mode == MTR_LOG_ALL); ut_ad(log_mutex_own()); - ut_ad(m_impl->m_log.size() == len); + ut_ad(m_log.size() == len); ut_ad(len > 0); - if (m_impl->m_log.is_small()) { - const mtr_buf_t::block_t* front = m_impl->m_log.front(); + lsn_t start_lsn; + + if (m_log.is_small()) { + const mtr_buf_t::block_t* front = m_log.front(); ut_ad(len <= front->used()); - m_end_lsn = log_reserve_and_write_fast( - front->begin(), len, &m_start_lsn); + m_commit_lsn = log_reserve_and_write_fast(front->begin(), len, + &start_lsn); - if (m_end_lsn > 0) { - return; + if (m_commit_lsn) { + return start_lsn; } } /* Open the database log for log_write_low */ - m_start_lsn = log_reserve_and_open(len); + start_lsn = log_reserve_and_open(len); mtr_write_log_t write_log; - m_impl->m_log.for_each_block(write_log); - - m_end_lsn = log_close(); -} - -/** Release the latches and blocks acquired by this mini-transaction */ -void -mtr_t::Command::release_all() -{ - m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>()); - - /* Note that we have released the latches. */ - m_locks_released = 1; -} - -/** Release the latches acquired by this mini-transaction */ -void -mtr_t::Command::release_latches() -{ - m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>()); + m_log.for_each_block(write_log); - /* Note that we have released the latches. */ - m_locks_released = 1; -} - -/** Release the blocks used in this mini-transaction */ -void -mtr_t::Command::release_blocks() -{ - m_impl->m_memo.for_each_block_in_reverse( - CIterate<const ReleaseBlocks>( - ReleaseBlocks(m_start_lsn, m_end_lsn, - m_impl->m_flush_observer))); -} - -/** Write the redo log record, add dirty pages to the flush list and release -the resources. */ -void -mtr_t::Command::execute() -{ - ut_ad(m_impl->m_log_mode != MTR_LOG_NONE); - - if (const ulint len = prepare_write()) { - finish_write(len); - } - - if (m_impl->m_made_dirty) { - log_flush_order_mutex_enter(); - } - - /* It is now safe to release the log mutex because the - flush_order mutex will ensure that we are the first one - to insert into the flush list. */ - log_mutex_exit(); - - m_impl->m_mtr->m_commit_lsn = m_end_lsn; - - release_blocks(); - - if (m_impl->m_made_dirty) { - log_flush_order_mutex_exit(); - } - - release_latches(); - - release_resources(); + m_commit_lsn = log_close(); + return start_lsn; } #ifdef UNIV_DEBUG @@ -1015,10 +882,9 @@ struct FlaggedCheck { bool mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - ut_ad(is_committing() || is_active()); + ut_ad(is_active()); - return !m_impl.m_memo.for_each_block_in_reverse( + return !m_memo.for_each_block_in_reverse( CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags))); } @@ -1034,7 +900,7 @@ mtr_t::memo_contains_page_flagged( ulint flags) const { Iterate<FindPage> iteration(FindPage(ptr, flags)); - return m_impl.m_memo.for_each_block_in_reverse(iteration) + return m_memo.for_each_block_in_reverse(iteration) ? NULL : iteration.functor.get_block(); } @@ -1057,7 +923,7 @@ void mtr_t::print() const { ib::info() << "Mini-transaction handle: memo size " - << m_impl.m_memo.size() << " bytes log size " + << m_memo.size() << " bytes log size " << get_log()->size() << " bytes"; } |