Commit 5098d708 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.2 into 10.3

parents d103c5a4 2570cb8b
...@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0; ...@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
connection slave; connection slave;
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1595,1913] include/wait_for_slave_io_error.inc [errno=1595,1743]
connection master; connection master;
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
SET GLOBAL debug_dbug= ""; SET GLOBAL debug_dbug= "";
...@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1; ...@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
connection slave; connection slave;
SET GLOBAL debug_dbug="+d,corrupt_queue_event"; SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1595,1913] include/wait_for_slave_io_error.inc [errno=1595,1743]
SET GLOBAL debug_dbug="-d,corrupt_queue_event"; SET GLOBAL debug_dbug="-d,corrupt_queue_event";
# 6. Slave. Corruption in relay log # 6. Slave. Corruption in relay log
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char"; SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
......
...@@ -122,11 +122,11 @@ SET GLOBAL master_verify_checksum=0; ...@@ -122,11 +122,11 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
--connection slave --connection slave
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
# When the checksum error is detected, the slave sets error code 1913 # When the checksum error is detected, the slave sets error code 1743
# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately # (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately
# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io(). # sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io().
# So we usually get 1595, but it is occasionally possible to get 1913. # So we usually get 1595, but it is occasionally possible to get 1743.
let $slave_io_errno= 1595,1913; let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc --source include/wait_for_slave_io_error.inc
--connection master --connection master
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
...@@ -138,7 +138,7 @@ SET GLOBAL master_verify_checksum=1; ...@@ -138,7 +138,7 @@ SET GLOBAL master_verify_checksum=1;
--connection slave --connection slave
SET GLOBAL debug_dbug="+d,corrupt_queue_event"; SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
let $slave_io_errno= 1595,1913; let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc --source include/wait_for_slave_io_error.inc
SET GLOBAL debug_dbug="-d,corrupt_queue_event"; SET GLOBAL debug_dbug="-d,corrupt_queue_event";
......
...@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0; ...@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
connection slave; connection slave;
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1595,1913] include/wait_for_slave_io_error.inc [errno=1595,1743]
connection master; connection master;
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
SET GLOBAL debug_dbug= ""; SET GLOBAL debug_dbug= "";
...@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1; ...@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
connection slave; connection slave;
SET GLOBAL debug_dbug="+d,corrupt_queue_event"; SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD; START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1595,1913] include/wait_for_slave_io_error.inc [errno=1595,1743]
SET GLOBAL debug_dbug="-d,corrupt_queue_event"; SET GLOBAL debug_dbug="-d,corrupt_queue_event";
# 6. Slave. Corruption in relay log # 6. Slave. Corruption in relay log
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char"; SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. 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 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
...@@ -134,62 +134,7 @@ struct mtr_memo_slot_t { ...@@ -134,62 +134,7 @@ struct mtr_memo_slot_t {
/** Mini-transaction handle and buffer */ /** Mini-transaction handle and buffer */
struct mtr_t { struct mtr_t {
mtr_t() : m_state(MTR_STATE_INIT) {}
/** 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() { }
/** Start a mini-transaction. */ /** Start a mini-transaction. */
void start(); void start();
...@@ -211,14 +156,7 @@ struct mtr_t { ...@@ -211,14 +156,7 @@ struct mtr_t {
/** Return current size of the buffer. /** Return current size of the buffer.
@return savepoint */ @return savepoint */
ulint get_savepoint() const ulint get_savepoint() const {ut_ad(is_active()); return m_memo.size();}
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());
}
/** Release the (index tree) s-latch stored in an mtr memo after a /** Release the (index tree) s-latch stored in an mtr memo after a
savepoint. savepoint.
...@@ -255,11 +193,11 @@ struct mtr_t { ...@@ -255,11 +193,11 @@ struct mtr_t {
the same set of tablespaces as this one */ the same set of tablespaces as this one */
void set_spaces(const mtr_t& mtr) void set_spaces(const mtr_t& mtr)
{ {
ut_ad(!m_impl.m_user_space_id); ut_ad(!m_user_space_id);
ut_ad(!m_impl.m_user_space); ut_ad(!m_user_space);
ut_d(m_impl.m_user_space_id = mtr.m_impl.m_user_space_id); ut_d(m_user_space_id = mtr.m_user_space_id);
m_impl.m_user_space = mtr.m_impl.m_user_space; m_user_space = mtr.m_user_space;
} }
/** Set the tablespace associated with the mini-transaction /** Set the tablespace associated with the mini-transaction
...@@ -268,16 +206,16 @@ struct mtr_t { ...@@ -268,16 +206,16 @@ struct mtr_t {
@return the tablespace */ @return the tablespace */
fil_space_t* set_named_space_id(ulint space_id) fil_space_t* set_named_space_id(ulint space_id)
{ {
ut_ad(!m_impl.m_user_space_id); ut_ad(!m_user_space_id);
ut_d(m_impl.m_user_space_id = space_id); ut_d(m_user_space_id = space_id);
if (!space_id) { if (!space_id) {
return fil_system.sys_space; return fil_system.sys_space;
} else { } else {
ut_ad(m_impl.m_user_space_id == space_id); ut_ad(m_user_space_id == space_id);
ut_ad(!m_impl.m_user_space); ut_ad(!m_user_space);
m_impl.m_user_space = fil_space_get(space_id); m_user_space = fil_space_get(space_id);
ut_ad(m_impl.m_user_space); ut_ad(m_user_space);
return m_impl.m_user_space; return m_user_space;
} }
} }
...@@ -286,10 +224,10 @@ struct mtr_t { ...@@ -286,10 +224,10 @@ struct mtr_t {
@param[in] space user or system tablespace */ @param[in] space user or system tablespace */
void set_named_space(fil_space_t* space) void set_named_space(fil_space_t* space)
{ {
ut_ad(!m_impl.m_user_space_id); ut_ad(!m_user_space_id);
ut_d(m_impl.m_user_space_id = space->id); ut_d(m_user_space_id = space->id);
if (space->id) { if (space->id) {
m_impl.m_user_space = space; m_user_space = space;
} }
} }
...@@ -356,18 +294,12 @@ struct mtr_t { ...@@ -356,18 +294,12 @@ struct mtr_t {
void release_page(const void* ptr, mtr_memo_type_t type); void release_page(const void* ptr, mtr_memo_type_t type);
/** Note that the mini-transaction has modified data. */ /** Note that the mini-transaction has modified data. */
void set_modified() void set_modified() { m_modifications = true; }
{
m_impl.m_modifications = true;
}
/** Set the state to not-modified. This will not log the /** Set the state to not-modified. This will not log the
changes. This is only used during redo log apply, to avoid changes. This is only used during redo log apply, to avoid
logging the changes. */ logging the changes. */
void discard_modifications() void discard_modifications() { m_modifications = false; }
{
m_impl.m_modifications = false;
}
/** Get the LSN of commit(). /** Get the LSN of commit().
@return the commit LSN @return the commit LSN
...@@ -379,45 +311,28 @@ struct mtr_t { ...@@ -379,45 +311,28 @@ struct mtr_t {
} }
/** Note that we are inside the change buffer code. */ /** Note that we are inside the change buffer code. */
void enter_ibuf() void enter_ibuf() { m_inside_ibuf = true; }
{
m_impl.m_inside_ibuf = true;
}
/** Note that we have exited from the change buffer code. */ /** Note that we have exited from the change buffer code. */
void exit_ibuf() void exit_ibuf() { m_inside_ibuf = false; }
{
m_impl.m_inside_ibuf = false;
}
/** @return true if we are inside the change buffer code */ /** @return true if we are inside the change buffer code */
bool is_inside_ibuf() const bool is_inside_ibuf() const { return m_inside_ibuf; }
{
return(m_impl.m_inside_ibuf);
}
/* /*
@return true if the mini-transaction is active */ @return true if the mini-transaction is active */
bool is_active() const bool is_active() const { return m_state == MTR_STATE_ACTIVE; }
{
return(m_impl.m_state == MTR_STATE_ACTIVE);
}
/** Get flush observer /** Get flush observer
@return flush observer */ @return flush observer */
FlushObserver* get_flush_observer() const FlushObserver* get_flush_observer() const { return m_flush_observer; }
{
return(m_impl.m_flush_observer);
}
/** Set flush observer /** Set flush observer
@param[in] observer flush observer */ @param[in] observer flush observer */
void set_flush_observer(FlushObserver* observer) void set_flush_observer(FlushObserver* observer)
{ {
ut_ad(observer == NULL ut_ad(observer == NULL || m_log_mode == MTR_LOG_NO_REDO);
|| m_impl.m_log_mode == MTR_LOG_NO_REDO); m_flush_observer = observer;
m_impl.m_flush_observer = observer;
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -457,65 +372,31 @@ struct mtr_t { ...@@ -457,65 +372,31 @@ struct mtr_t {
void print() const; void print() const;
/** @return true if the mini-transaction has committed */ /** @return true if the mini-transaction has committed */
bool has_committed() const bool has_committed() const { return m_state == MTR_STATE_COMMITTED; }
{
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);
}
/** @return true if mini-transaction contains modifications. */ /** @return true if mini-transaction contains modifications. */
bool has_modifications() const bool has_modifications() const { return m_modifications; }
{
return(m_impl.m_modifications);
}
/** @return the memo stack */ /** @return the memo stack */
const mtr_buf_t* get_memo() const const mtr_buf_t* get_memo() const { return &m_memo; }
{
return(&m_impl.m_memo);
}
/** @return the memo stack */ /** @return the memo stack */
mtr_buf_t* get_memo() mtr_buf_t* get_memo() { return &m_memo; }
{
return(&m_impl.m_memo);
}
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** @return true if a record was added to the mini-transaction */ /** @return true if a record was added to the mini-transaction */
bool is_dirty() const bool is_dirty() const { return m_made_dirty; }
{
return(m_impl.m_made_dirty);
}
/** Note that a record has been added to the log */ /** Note that a record has been added to the log */
void added_rec() void added_rec() { ++m_n_log_recs; }
{
++m_impl.m_n_log_recs;
}
/** Get the buffered redo log of this mini-transaction. /** Get the buffered redo log of this mini-transaction.
@return redo log */ @return redo log */
const mtr_buf_t* get_log() const const mtr_buf_t* get_log() const { return &m_log; }
{
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
return(&m_impl.m_log);
}
/** Get the buffered redo log of this mini-transaction. /** Get the buffered redo log of this mini-transaction.
@return redo log */ @return redo log */
mtr_buf_t* get_log() mtr_buf_t* get_log() { return &m_log; }
{
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
return(&m_impl.m_log);
}
/** Push an object to an mtr memo stack. /** Push an object to an mtr memo stack.
@param object object @param object object
...@@ -529,15 +410,56 @@ struct mtr_t { ...@@ -529,15 +410,56 @@ struct mtr_t {
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
private: 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: /** Release the resources */
Impl m_impl; 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 */ /** LSN at commit time */
volatile lsn_t m_commit_lsn; lsn_t m_commit_lsn;
}; };
#include "mtr0mtr.ic" #include "mtr0mtr.ic"
......
...@@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) ...@@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
ut_ad(object != NULL); ut_ad(object != NULL);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_SX_LOCK); ut_ad(type <= MTR_MEMO_SX_LOCK);
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(ut_is_2pow(type)); ut_ad(ut_is_2pow(type));
/* If this mtr has x-fixed a clean page then we set /* 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) ...@@ -58,15 +57,13 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
can insert the dirtied page to the flush list. */ can insert the dirtied page to the flush list. */
if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) 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)); reinterpret_cast<const buf_block_t*>(object));
} }
mtr_memo_slot_t* slot; mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
slot->type = type; slot->type = type;
slot->object = object; slot->object = object;
...@@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint( ...@@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint(
rw_lock_t* lock) rw_lock_t* lock)
{ {
ut_ad(is_active()); ut_ad(is_active());
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(m_memo.size() > savepoint);
ut_ad(m_impl.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->object == lock);
ut_ad(slot->type == MTR_MEMO_S_LOCK); ut_ad(slot->type == MTR_MEMO_S_LOCK);
...@@ -104,8 +99,7 @@ mtr_t::sx_latch_at_savepoint( ...@@ -104,8 +99,7 @@ mtr_t::sx_latch_at_savepoint(
buf_block_t* block) buf_block_t* block)
{ {
ut_ad(is_active()); ut_ad(is_active());
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(m_memo.size() > savepoint);
ut_ad(m_impl.m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged( ut_ad(!memo_contains_flagged(
block, block,
...@@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint( ...@@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint(
| MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX)); | MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t* slot; mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block); ut_ad(slot->object == block);
...@@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint( ...@@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint(
rw_lock_sx_lock(&block->lock); rw_lock_sx_lock(&block->lock);
if (!m_impl.m_made_dirty) { if (!m_made_dirty) {
m_impl.m_made_dirty = is_block_dirtied(block); m_made_dirty = is_block_dirtied(block);
} }
slot->type = MTR_MEMO_PAGE_SX_FIX; slot->type = MTR_MEMO_PAGE_SX_FIX;
...@@ -140,8 +132,7 @@ mtr_t::x_latch_at_savepoint( ...@@ -140,8 +132,7 @@ mtr_t::x_latch_at_savepoint(
buf_block_t* block) buf_block_t* block)
{ {
ut_ad(is_active()); ut_ad(is_active());
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(m_memo.size() > savepoint);
ut_ad(m_impl.m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged( ut_ad(!memo_contains_flagged(
block, block,
...@@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint( ...@@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint(
| MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX)); | MTR_MEMO_PAGE_SX_FIX));
mtr_memo_slot_t* slot; mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block); ut_ad(slot->object == block);
...@@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint( ...@@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint(
rw_lock_x_lock(&block->lock); rw_lock_x_lock(&block->lock);
if (!m_impl.m_made_dirty) { if (!m_made_dirty) {
m_impl.m_made_dirty = is_block_dirtied(block); m_made_dirty = is_block_dirtied(block);
} }
slot->type = MTR_MEMO_PAGE_X_FIX; slot->type = MTR_MEMO_PAGE_X_FIX;
...@@ -176,11 +165,8 @@ mtr_t::release_block_at_savepoint( ...@@ -176,11 +165,8 @@ mtr_t::release_block_at_savepoint(
buf_block_t* block) buf_block_t* block)
{ {
ut_ad(is_active()); 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); ut_a(slot->object == block);
...@@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction. ...@@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction.
mtr_log_t mtr_log_t
mtr_t::get_log_mode() const mtr_t::get_log_mode() const
{ {
ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL); ut_ad(m_log_mode >= MTR_LOG_ALL);
ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS); 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) ...@@ -214,7 +200,7 @@ mtr_t::set_log_mode(mtr_log_t mode)
ut_ad(mode >= MTR_LOG_ALL); ut_ad(mode >= MTR_LOG_ALL);
ut_ad(mode <= MTR_LOG_SHORT_INSERTS); 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) { switch (old_mode) {
case MTR_LOG_NO_REDO: case MTR_LOG_NO_REDO:
...@@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode) ...@@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode)
case MTR_LOG_ALL: case MTR_LOG_ALL:
/* MTR_LOG_NO_REDO can only be set before generating /* MTR_LOG_NO_REDO can only be set before generating
any redo log records. */ any redo log records. */
ut_ad(mode != MTR_LOG_NO_REDO ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0);
|| m_impl.m_n_log_recs == 0); m_log_mode = mode;
m_impl.m_log_mode = mode;
return(old_mode); return(old_mode);
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. 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 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
...@@ -36,18 +36,18 @@ struct mtr_t; ...@@ -36,18 +36,18 @@ struct mtr_t;
/** Logging modes for a mini-transaction */ /** Logging modes for a mini-transaction */
enum mtr_log_t { enum mtr_log_t {
/** Default mode: log all operations modifying disk-based data */ /** 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. /** 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 Set when applying log in crash recovery or when a modification of a
ROW_FORMAT=COMPRESSED page is attempted. */ 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 */ /** 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 */ /** Inserts are logged in a shorter form */
MTR_LOG_SHORT_INSERTS = 24 MTR_LOG_SHORT_INSERTS
}; };
/** @name Log item types /** @name Log item types
...@@ -271,15 +271,10 @@ enum mtr_memo_type_t { ...@@ -271,15 +271,10 @@ enum mtr_memo_type_t {
}; };
#endif /* !UNIV_CHECKSUM */ #endif /* !UNIV_CHECKSUM */
#ifdef UNIV_DEBUG
# define MTR_MAGIC_N 54551
#endif /* UNIV_DEBUG */
enum mtr_state_t { enum mtr_state_t {
MTR_STATE_INIT = 0, MTR_STATE_INIT = 0,
MTR_STATE_ACTIVE = 12231, MTR_STATE_ACTIVE,
MTR_STATE_COMMITTING = 56456, MTR_STATE_COMMITTED
MTR_STATE_COMMITTED = 34676
}; };
#endif /* mtr0types_h */ #endif /* mtr0types_h */
...@@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri ...@@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri
#include "univ.i" #include "univ.i"
#include <vector>
#include <map> #include <map>
#include <string> #include <string>
#include <my_service_manager.h> #include <my_service_manager.h>
...@@ -3971,44 +3970,26 @@ recv_recovery_rollback_active(void) ...@@ -3971,44 +3970,26 @@ recv_recovery_rollback_active(void)
@param[in] page_no page number @param[in] page_no page number
@return page frame @return page frame
@retval NULL if no page was found */ @retval NULL if no page was found */
const byte* const byte*
recv_dblwr_t::find_page(ulint space_id, ulint page_no) recv_dblwr_t::find_page(ulint space_id, ulint page_no)
{ {
typedef std::vector<const byte*, ut_allocator<const byte*> > const byte *result= NULL;
matches_t; lsn_t max_lsn= 0;
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(); for (list::const_iterator i = pages.begin(); i != pages.end(); ++i)
i != matches.end(); {
++i) { const byte *page= *i;
if (page_get_page_no(page) != page_no ||
page_lsn = mach_read_from_8(*i + FIL_PAGE_LSN); page_get_space_id(page) != space_id)
continue;
if (page_lsn > max_lsn) { const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN);
max_lsn = page_lsn; if (lsn <= max_lsn)
result = *i; continue;
} max_lsn= lsn;
} result= page;
} }
return(result); return result;
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
......
...@@ -343,6 +343,7 @@ struct ReleaseAll { ...@@ -343,6 +343,7 @@ struct ReleaseAll {
} }
}; };
#ifdef UNIV_DEBUG
/** Check that all slots have been handled. */ /** Check that all slots have been handled. */
struct DebugCheck { struct DebugCheck {
/** @return true always. */ /** @return true always. */
...@@ -352,6 +353,7 @@ struct DebugCheck { ...@@ -352,6 +353,7 @@ struct DebugCheck {
return(true); return(true);
} }
}; };
#endif
/** Release a resource acquired by the mini-transaction. */ /** Release a resource acquired by the mini-transaction. */
struct ReleaseBlocks { struct ReleaseBlocks {
...@@ -404,59 +406,6 @@ struct ReleaseBlocks { ...@@ -404,59 +406,6 @@ struct ReleaseBlocks {
FlushObserver* m_flush_observer; 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 */ /** Write the block contents to the REDO log */
struct mtr_write_log_t { struct mtr_write_log_t {
/** Append a block to the redo log buffer. /** Append a block to the redo log buffer.
...@@ -490,48 +439,30 @@ mtr_write_log( ...@@ -490,48 +439,30 @@ mtr_write_log(
/** Start a mini-transaction. */ /** Start a mini-transaction. */
void mtr_t::start() void mtr_t::start()
{ {
UNIV_MEM_INVALID(this, sizeof(*this)); UNIV_MEM_INVALID(this, sizeof *this);
UNIV_MEM_INVALID(&m_impl, sizeof(m_impl)); new(&m_memo) mtr_buf_t();
new(&m_log) mtr_buf_t();
m_commit_lsn = 0;
m_made_dirty= false;
new(&m_impl.m_log) mtr_buf_t(); m_inside_ibuf= false;
new(&m_impl.m_memo) mtr_buf_t(); m_modifications= false;
m_n_log_recs= 0;
m_impl.m_mtr = this; m_log_mode= MTR_LOG_ALL;
m_impl.m_log_mode = MTR_LOG_ALL; ut_d(m_user_space_id= TRX_SYS_SPACE);
m_impl.m_inside_ibuf = false; m_user_space= NULL;
m_impl.m_modifications = false; m_state= MTR_STATE_ACTIVE;
m_impl.m_made_dirty = false; m_flush_observer= NULL;
m_impl.m_n_log_recs = 0; m_commit_lsn= 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);
} }
/** Release the resources */ /** Release the resources */
void inline void mtr_t::release_resources()
mtr_t::Command::release_resources()
{ {
ut_ad(m_impl->m_magic_n == MTR_MAGIC_N); ut_d(m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
m_log.erase();
/* Currently only used in commit */ m_memo.erase();
ut_ad(m_impl->m_state == MTR_STATE_COMMITTING); m_state= MTR_STATE_COMMITTED;
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;
} }
/** Commit a mini-transaction. */ /** Commit a mini-transaction. */
...@@ -540,26 +471,43 @@ mtr_t::commit() ...@@ -540,26 +471,43 @@ mtr_t::commit()
{ {
ut_ad(is_active()); ut_ad(is_active());
ut_ad(!is_inside_ibuf()); ut_ad(!is_inside_ibuf());
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
m_impl.m_state = MTR_STATE_COMMITTING;
/* This is a dirty read, for debugging. */ /* This is a dirty read, for debugging. */
ut_ad(!m_impl.m_modifications || !recv_no_log_write); 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 lsn_t start_lsn;
&& (m_impl.m_n_log_recs > 0
|| m_impl.m_log_mode == MTR_LOG_NO_REDO)) {
ut_ad(!srv_read_only_mode if (const ulint len= prepare_write())
|| m_impl.m_log_mode == MTR_LOG_NO_REDO); start_lsn= finish_write(len);
else
start_lsn= m_commit_lsn;
cmd.execute(); if (m_made_dirty)
} else { log_flush_order_mutex_enter();
cmd.release_all();
cmd.release_resources(); /* 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, /** Commit a mini-transaction that did not modify any pages,
...@@ -578,35 +526,31 @@ mtr_t::commit_checkpoint( ...@@ -578,35 +526,31 @@ mtr_t::commit_checkpoint(
ut_ad(log_mutex_own()); ut_ad(log_mutex_own());
ut_ad(is_active()); ut_ad(is_active());
ut_ad(!is_inside_ibuf()); 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(get_log_mode() == MTR_LOG_ALL);
ut_ad(!m_impl.m_made_dirty); ut_ad(!m_made_dirty);
ut_ad(m_impl.m_memo.size() == 0); ut_ad(m_memo.size() == 0);
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_d(m_impl.m_state = MTR_STATE_COMMITTING); ut_ad(write_mlog_checkpoint || m_n_log_recs > 1);
ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1);
switch (m_impl.m_n_log_recs) { switch (m_n_log_recs) {
case 0: case 0:
break; break;
case 1: case 1:
*m_impl.m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
break; break;
default: default:
mlog_catenate_ulint( mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
&m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
} }
if (write_mlog_checkpoint) { 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); compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8);
*ptr = MLOG_CHECKPOINT; *ptr = MLOG_CHECKPOINT;
mach_write_to_8(ptr + 1, checkpoint_lsn); mach_write_to_8(ptr + 1, checkpoint_lsn);
} }
Command cmd(this); finish_write(m_log.size());
cmd.finish_write(m_impl.m_log.size()); release_resources();
cmd.release_resources();
if (write_mlog_checkpoint) { if (write_mlog_checkpoint) {
DBUG_PRINT("ib_log", DBUG_PRINT("ib_log",
...@@ -623,8 +567,7 @@ mtr_t::commit_checkpoint( ...@@ -623,8 +567,7 @@ mtr_t::commit_checkpoint(
bool bool
mtr_t::is_named_space(ulint space) const mtr_t::is_named_space(ulint space) const
{ {
ut_ad(!m_impl.m_user_space ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
|| m_impl.m_user_space->id != TRX_SYS_SPACE);
switch (get_log_mode()) { switch (get_log_mode()) {
case MTR_LOG_NONE: case MTR_LOG_NONE:
...@@ -632,7 +575,7 @@ mtr_t::is_named_space(ulint space) const ...@@ -632,7 +575,7 @@ mtr_t::is_named_space(ulint space) const
return(true); return(true);
case MTR_LOG_ALL: case MTR_LOG_ALL:
case MTR_LOG_SHORT_INSERTS: case MTR_LOG_SHORT_INSERTS:
return(m_impl.m_user_space_id == space return(m_user_space_id == space
|| is_predefined_tablespace(space)); || is_predefined_tablespace(space));
} }
...@@ -645,8 +588,7 @@ mtr_t::is_named_space(ulint space) const ...@@ -645,8 +588,7 @@ mtr_t::is_named_space(ulint space) const
@return whether the mini-transaction is associated with the space */ @return whether the mini-transaction is associated with the space */
bool mtr_t::is_named_space(const fil_space_t* space) const bool mtr_t::is_named_space(const fil_space_t* space) const
{ {
ut_ad(!m_impl.m_user_space ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
|| m_impl.m_user_space->id != TRX_SYS_SPACE);
switch (get_log_mode()) { switch (get_log_mode()) {
case MTR_LOG_NONE: case MTR_LOG_NONE:
...@@ -654,8 +596,7 @@ bool mtr_t::is_named_space(const fil_space_t* space) const ...@@ -654,8 +596,7 @@ bool mtr_t::is_named_space(const fil_space_t* space) const
return true; return true;
case MTR_LOG_ALL: case MTR_LOG_ALL:
case MTR_LOG_SHORT_INSERTS: case MTR_LOG_SHORT_INSERTS:
return(m_impl.m_user_space == space return m_user_space == space || is_predefined_tablespace(space->id);
|| is_predefined_tablespace(space->id));
} }
ut_error; ut_error;
...@@ -674,12 +615,11 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) ...@@ -674,12 +615,11 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
{ {
fil_space_t* space; fil_space_t* space;
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_active()); ut_ad(is_active());
if (space_id == TRX_SYS_SPACE) { if (space_id == TRX_SYS_SPACE) {
space = fil_system.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 { } else {
space = fil_space_get(space_id); space = fil_space_get(space_id);
ut_ad(get_log_mode() != MTR_LOG_NO_REDO 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) ...@@ -703,16 +643,15 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
bool bool
mtr_t::memo_release(const void* object, ulint type) mtr_t::memo_release(const void* object, ulint type)
{ {
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_active()); ut_ad(is_active());
/* We cannot release a page that has been written to in the /* We cannot release a page that has been written to in the
middle of a mini-transaction. */ 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)); 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); memo_slot_release(iteration.functor.m_slot);
return(true); return(true);
} }
...@@ -726,16 +665,15 @@ mtr_t::memo_release(const void* object, ulint type) ...@@ -726,16 +665,15 @@ mtr_t::memo_release(const void* object, ulint type)
void void
mtr_t::release_page(const void* ptr, mtr_memo_type_t type) 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()); ut_ad(is_active());
/* We cannot release a page that has been written to in the /* We cannot release a page that has been written to in the
middle of a mini-transaction. */ 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)); 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()); memo_slot_release(iteration.functor.get_slot());
return; return;
} }
...@@ -746,27 +684,20 @@ mtr_t::release_page(const void* ptr, mtr_memo_type_t type) ...@@ -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. /** 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() */
ulint inline ulint mtr_t::prepare_write()
mtr_t::Command::prepare_write()
{ {
ut_ad(!recv_no_log_write); ut_ad(!recv_no_log_write);
switch (m_impl->m_log_mode) { if (UNIV_UNLIKELY(m_log_mode != MTR_LOG_ALL)) {
case MTR_LOG_SHORT_INSERTS: ut_ad(m_log_mode == MTR_LOG_NO_REDO);
ut_ad(0); ut_ad(m_log.size() == 0);
/* fall through */
case MTR_LOG_NO_REDO:
case MTR_LOG_NONE:
ut_ad(m_impl->m_log.size() == 0);
log_mutex_enter(); log_mutex_enter();
m_end_lsn = m_start_lsn = log_sys.lsn; m_commit_lsn = log_sys.lsn;
return(0); return 0;
case MTR_LOG_ALL:
break;
} }
ulint len = m_impl->m_log.size(); ulint len = m_log.size();
ulint n_recs = m_impl->m_n_log_recs; ulint n_recs = m_n_log_recs;
ut_ad(len > 0); ut_ad(len > 0);
ut_ad(n_recs > 0); ut_ad(n_recs > 0);
...@@ -774,9 +705,9 @@ mtr_t::Command::prepare_write() ...@@ -774,9 +705,9 @@ mtr_t::Command::prepare_write()
log_buffer_extend(ulong((len + 1) * 2)); 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)) { if (space != NULL && is_predefined_tablespace(space->id)) {
/* Omit MLOG_FILE_NAME for predefined tablespaces. */ /* Omit MLOG_FILE_NAME for predefined tablespaces. */
...@@ -785,34 +716,31 @@ mtr_t::Command::prepare_write() ...@@ -785,34 +716,31 @@ mtr_t::Command::prepare_write()
log_mutex_enter(); 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 mini-transaction was the first one to modify
this tablespace since the latest checkpoint, so this tablespace since the latest checkpoint, so
some MLOG_FILE_NAME records were appended to m_log. */ some MLOG_FILE_NAME records were appended to m_log. */
ut_ad(m_impl->m_n_log_recs > n_recs); ut_ad(m_n_log_recs > n_recs);
mlog_catenate_ulint( mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
&m_impl->m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); len = m_log.size();
len = m_impl->m_log.size();
} else { } else {
/* This was not the first time of dirtying a /* This was not the first time of dirtying a
tablespace since the latest checkpoint. */ 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) { if (n_recs <= 1) {
ut_ad(n_recs == 1); ut_ad(n_recs == 1);
/* Flag the single log record as the /* Flag the single log record as the
only record in this mini-transaction. */ only record in this mini-transaction. */
*m_impl->m_log.front()->begin() *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
|= MLOG_SINGLE_REC_FLAG;
} else { } else {
/* Because this mini-transaction comprises /* Because this mini-transaction comprises
multiple log records, append MLOG_MULTI_REC_END multiple log records, append MLOG_MULTI_REC_END
at the end. */ at the end. */
mlog_catenate_ulint( mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END,
&m_impl->m_log, MLOG_MULTI_REC_END,
MLOG_1BYTE); MLOG_1BYTE);
len++; len++;
} }
...@@ -825,98 +753,37 @@ mtr_t::Command::prepare_write() ...@@ -825,98 +753,37 @@ mtr_t::Command::prepare_write()
} }
/** Append the redo log records to the redo log buffer /** Append the redo log records to the redo log buffer
@param[in] len number of bytes to write */ @param[in] len number of bytes to write
void @return start_lsn */
mtr_t::Command::finish_write( inline lsn_t mtr_t::finish_write(ulint len)
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(log_mutex_own());
ut_ad(m_impl->m_log.size() == len); ut_ad(m_log.size() == len);
ut_ad(len > 0); ut_ad(len > 0);
if (m_impl->m_log.is_small()) { lsn_t start_lsn;
const mtr_buf_t::block_t* front = m_impl->m_log.front();
if (m_log.is_small()) {
const mtr_buf_t::block_t* front = m_log.front();
ut_ad(len <= front->used()); ut_ad(len <= front->used());
m_end_lsn = log_reserve_and_write_fast( m_commit_lsn = log_reserve_and_write_fast(front->begin(), len,
front->begin(), len, &m_start_lsn); &start_lsn);
if (m_end_lsn > 0) { if (m_commit_lsn) {
return; return start_lsn;
} }
} }
/* Open the database log for log_write_low */ /* 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; mtr_write_log_t write_log;
m_impl->m_log.for_each_block(write_log); 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>());
/* 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 m_commit_lsn = log_close();
flush_order mutex will ensure that we are the first one return start_lsn;
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();
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -1015,10 +882,9 @@ struct FlaggedCheck { ...@@ -1015,10 +882,9 @@ struct FlaggedCheck {
bool bool
mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
{ {
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active());
ut_ad(is_committing() || 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))); CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags)));
} }
...@@ -1034,7 +900,7 @@ mtr_t::memo_contains_page_flagged( ...@@ -1034,7 +900,7 @@ mtr_t::memo_contains_page_flagged(
ulint flags) const ulint flags) const
{ {
Iterate<FindPage> iteration(FindPage(ptr, flags)); 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(); ? NULL : iteration.functor.get_block();
} }
...@@ -1057,7 +923,7 @@ void ...@@ -1057,7 +923,7 @@ void
mtr_t::print() const mtr_t::print() const
{ {
ib::info() << "Mini-transaction handle: memo size " 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"; << get_log()->size() << " bytes";
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment