mirror of
https://github.com/MariaDB/server.git
synced 2026-05-07 23:54:31 +02:00
MDEV-36024 preparation: Shrink mtr_buf_t
mtr_t::get_log_size(): Remove. mtr_t::crc32c(): New function: compute CRC-32C and determine the size, including the sequence byte and the CRC-32C. mtr_t::encrypt(): Return the size, similar to crc32c(). mtr_t::log_file_op(): Return the size written. fil_name_write(): Remove. Let us invoke mtr_t::log_file_op() directly. fil_names_clear(): Keep track of the available size without invoking mtr_t::get_log_size(). mtr_buf_t::m_size: Remove. mtr_buf_t::list_t: Use ilist instead of sized_ilist. mtr_buf_t::for_each_block(): Remove. Let us allow iteration via begin() and end(), without any lambda function objects.
This commit is contained in:
parent
ad44e1b964
commit
1afc682932
5 changed files with 87 additions and 141 deletions
|
|
@ -1423,12 +1423,15 @@ fil_space_t *fil_space_t::get(uint32_t id) noexcept
|
|||
@param type file operation
|
||||
@param first_page_no first page number in the file
|
||||
@param path file path
|
||||
@param new_path new file path for type=FILE_RENAME */
|
||||
inline void mtr_t::log_file_op(mfile_type_t type, uint32_t space_id,
|
||||
const char *path, const char *new_path)
|
||||
@param new_path new file path for type=FILE_RENAME
|
||||
@return number of bytes written */
|
||||
inline size_t mtr_t::log_file_op(mfile_type_t type, uint32_t space_id,
|
||||
const char *path, const char *new_path)
|
||||
noexcept
|
||||
{
|
||||
ut_ad((new_path != nullptr) == (type == FILE_RENAME));
|
||||
ut_ad(!(byte(type) & 15));
|
||||
ut_ad(!is_predefined_tablespace(space_id));
|
||||
|
||||
/* fil_name_parse() requires that there be at least one path
|
||||
separator and that the file path end with ".ibd". */
|
||||
|
|
@ -1437,7 +1440,7 @@ inline void mtr_t::log_file_op(mfile_type_t type, uint32_t space_id,
|
|||
|
||||
m_modifications= true;
|
||||
if (!is_logged())
|
||||
return;
|
||||
return 0;
|
||||
m_last= nullptr;
|
||||
|
||||
const size_t len= strlen(path);
|
||||
|
|
@ -1469,7 +1472,7 @@ inline void mtr_t::log_file_op(mfile_type_t type, uint32_t space_id,
|
|||
|
||||
m_log.close(end);
|
||||
|
||||
if (new_path)
|
||||
if (new_len)
|
||||
{
|
||||
ut_ad(strchr(new_path, '/'));
|
||||
m_log.push(reinterpret_cast<const byte*>(path), uint32_t(len + 1));
|
||||
|
|
@ -1477,17 +1480,8 @@ inline void mtr_t::log_file_op(mfile_type_t type, uint32_t space_id,
|
|||
}
|
||||
else
|
||||
m_log.push(reinterpret_cast<const byte*>(path), uint32_t(len));
|
||||
}
|
||||
|
||||
/** Write FILE_MODIFY for a file.
|
||||
@param[in] space_id tablespace id
|
||||
@param[in] name tablespace file name
|
||||
@param[in,out] mtr mini-transaction */
|
||||
static void fil_name_write(uint32_t space_id, const char *name,
|
||||
mtr_t *mtr)
|
||||
{
|
||||
ut_ad(!is_predefined_tablespace(space_id));
|
||||
mtr->log_file_op(FILE_MODIFY, space_id, name);
|
||||
return end - log_ptr + len + new_len;
|
||||
}
|
||||
|
||||
fil_space_t *fil_space_t::drop(uint32_t id, pfs_os_file_t *detached_handle)
|
||||
|
|
@ -2986,9 +2980,8 @@ ATTRIBUTE_NOINLINE ATTRIBUTE_COLD void mtr_t::name_write() noexcept
|
|||
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
fil_name_write(m_user_space->id,
|
||||
UT_LIST_GET_FIRST(m_user_space->chain)->name,
|
||||
&mtr);
|
||||
mtr.log_file_op(FILE_MODIFY, m_user_space->id,
|
||||
UT_LIST_GET_FIRST(m_user_space->chain)->name);
|
||||
mtr.commit_files();
|
||||
}
|
||||
|
||||
|
|
@ -3005,14 +2998,18 @@ ATTRIBUTE_COLD lsn_t fil_names_clear(lsn_t lsn) noexcept
|
|||
ut_ad(log_sys.is_latest());
|
||||
|
||||
mtr.start();
|
||||
constexpr size_t budget = recv_sys.MTR_SIZE_MAX - (3 + 5);
|
||||
size_t budget_left = budget;
|
||||
|
||||
for (auto it = fil_system.named_spaces.begin();
|
||||
it != fil_system.named_spaces.end(); ) {
|
||||
if (mtr.get_log_size() + strlen(it->chain.start->name)
|
||||
>= recv_sys.MTR_SIZE_MAX - (3 + 5)) {
|
||||
const char* const name = it->chain.start->name;
|
||||
|
||||
if (strlen(name) >= budget_left) {
|
||||
/* Prevent log parse buffer overflow */
|
||||
mtr.commit_files();
|
||||
mtr.start();
|
||||
budget_left = budget;
|
||||
}
|
||||
|
||||
auto next = std::next(it);
|
||||
|
|
@ -3033,8 +3030,9 @@ ATTRIBUTE_COLD lsn_t fil_names_clear(lsn_t lsn) noexcept
|
|||
where max_lsn turned nonzero), we could avoid the
|
||||
fil_names_write() call if min_lsn > lsn. */
|
||||
ut_ad(UT_LIST_GET_LEN((*it).chain) == 1);
|
||||
fil_name_write((*it).id, UT_LIST_GET_FIRST((*it).chain)->name,
|
||||
&mtr);
|
||||
size_t s = mtr.log_file_op(FILE_MODIFY, (*it).id, name);
|
||||
ut_ad(s <= budget_left);
|
||||
budget_left -= s;
|
||||
it = next;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,13 +155,12 @@ public:
|
|||
friend class mtr_buf_t;
|
||||
};
|
||||
|
||||
typedef sized_ilist<block_t> list_t;
|
||||
typedef ilist<block_t> list_t;
|
||||
|
||||
/** Default constructor */
|
||||
mtr_buf_t()
|
||||
:
|
||||
m_heap(),
|
||||
m_size()
|
||||
m_heap()
|
||||
{
|
||||
push_back(&m_first_block);
|
||||
}
|
||||
|
|
@ -183,11 +182,10 @@ public:
|
|||
m_list.clear();
|
||||
m_list.push_back(m_first_block);
|
||||
} else {
|
||||
ut_ad(front() == &m_first_block);
|
||||
ut_ad(back() == &m_first_block);
|
||||
m_first_block.init();
|
||||
ut_ad(m_list.size() == 1);
|
||||
}
|
||||
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -217,13 +215,7 @@ public:
|
|||
void close(const byte* ptr)
|
||||
{
|
||||
ut_ad(!m_list.empty());
|
||||
block_t* block = back();
|
||||
|
||||
m_size -= block->used();
|
||||
|
||||
block->close(ptr);
|
||||
|
||||
m_size += block->used();
|
||||
back()->close(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -241,8 +233,6 @@ public:
|
|||
|
||||
block = has_space(size) ? back() : add_block();
|
||||
|
||||
m_size += size;
|
||||
|
||||
/* See ISO C++03 14.2/4 for why "template" is required. */
|
||||
|
||||
return(block->template push<Type>(size));
|
||||
|
|
@ -264,41 +254,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the size of the total stored data.
|
||||
@return data size in bytes */
|
||||
ulint size() const
|
||||
MY_ATTRIBUTE((warn_unused_result))
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint total_size = 0;
|
||||
|
||||
for (list_t::iterator it = m_list.begin(), end = m_list.end();
|
||||
it != end; ++it) {
|
||||
total_size += it->used();
|
||||
}
|
||||
|
||||
ut_ad(total_size == m_size);
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(m_size);
|
||||
}
|
||||
|
||||
/**
|
||||
Iterate over each block and call the functor.
|
||||
@return false if iteration was terminated. */
|
||||
template <typename Functor>
|
||||
bool for_each_block(const Functor& functor) const
|
||||
{
|
||||
for (list_t::iterator it = m_list.begin(), end = m_list.end();
|
||||
it != end; ++it) {
|
||||
|
||||
if (!functor(&*it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
list_t::const_iterator begin() const { return m_list.begin(); }
|
||||
list_t::const_iterator end() const { return m_list.end(); }
|
||||
|
||||
/**
|
||||
@return the first block */
|
||||
|
|
@ -377,9 +334,6 @@ private:
|
|||
/** Allocated blocks */
|
||||
list_t m_list;
|
||||
|
||||
/** Total size used by all blocks */
|
||||
ulint m_size;
|
||||
|
||||
/** The default block, should always be the first element. This
|
||||
is for backwards compatibility and to avoid an extra heap allocation
|
||||
for small REDO log records */
|
||||
|
|
|
|||
|
|
@ -435,10 +435,8 @@ public:
|
|||
m_memo.emplace_back(mtr_memo_slot_t{object, type});
|
||||
}
|
||||
|
||||
/** @return the size of the log is empty */
|
||||
size_t get_log_size() const { return m_log.size(); }
|
||||
/** @return whether the log and memo are empty */
|
||||
bool is_empty() const { return !get_savepoint() && !get_log_size(); }
|
||||
bool is_empty() const { return !get_savepoint() && m_log.empty(); }
|
||||
|
||||
/** Write an OPT_PAGE_CHECKSUM record. */
|
||||
inline void page_checksum(const buf_page_t &bpage);
|
||||
|
|
@ -618,10 +616,11 @@ public:
|
|||
@param type file operation
|
||||
@param space_id tablespace identifier
|
||||
@param path file path
|
||||
@param new_path new file path for type=FILE_RENAME */
|
||||
inline void log_file_op(mfile_type_t type, uint32_t space_id,
|
||||
const char *path,
|
||||
const char *new_path= nullptr);
|
||||
@param new_path new file path for type=FILE_RENAME
|
||||
@return number of bytes written */
|
||||
inline size_t log_file_op(mfile_type_t type, uint32_t space_id,
|
||||
const char *path,
|
||||
const char *new_path= nullptr) noexcept;
|
||||
|
||||
/** Add freed page numbers to freed_pages */
|
||||
void add_freed_offset(fil_space_t *space, uint32_t page)
|
||||
|
|
@ -692,8 +691,13 @@ private:
|
|||
tablespace was modified for the first time since fil_names_clear(). */
|
||||
ATTRIBUTE_NOINLINE ATTRIBUTE_COLD void name_write() noexcept;
|
||||
|
||||
/** Encrypt the log */
|
||||
ATTRIBUTE_NOINLINE void encrypt();
|
||||
/** Encrypt the log
|
||||
@return the total size in bytes, excluding the 8-byte nonce */
|
||||
ATTRIBUTE_NOINLINE size_t encrypt() noexcept;
|
||||
|
||||
/** Calculate m_crc of m_log.
|
||||
@return the total size in bytes, including the 5-byte trailer and CRC-32C */
|
||||
ATTRIBUTE_NOINLINE size_t crc32c() noexcept;
|
||||
|
||||
/** Commit the mini-transaction log.
|
||||
@tparam pmem log_sys.is_mmap()
|
||||
|
|
|
|||
|
|
@ -558,11 +558,10 @@ static size_t log_encrypt_buf(byte iv[MY_AES_BLOCK_SIZE],
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Encrypt the log */
|
||||
ATTRIBUTE_NOINLINE void mtr_t::encrypt()
|
||||
ATTRIBUTE_NOINLINE size_t mtr_t::encrypt() noexcept
|
||||
{
|
||||
ut_ad(log_sys.format == log_t::FORMAT_ENC_10_8);
|
||||
ut_ad(m_log.size());
|
||||
ut_ad(!m_log.empty());
|
||||
|
||||
alignas(8) byte iv[MY_AES_BLOCK_SIZE];
|
||||
|
||||
|
|
@ -572,18 +571,19 @@ ATTRIBUTE_NOINLINE void mtr_t::encrypt()
|
|||
byte *dst= static_cast<byte*>(alloca(srv_page_size));
|
||||
mach_write_to_8(iv, m_commit_lsn);
|
||||
mtr_buf_t::block_t *start= nullptr;
|
||||
size_t size= 0, start_size= 0;
|
||||
size_t size= 0, start_size= 0, log_size= 5;
|
||||
m_crc= 0;
|
||||
|
||||
m_log.for_each_block([&](mtr_buf_t::block_t *b)
|
||||
for (mtr_buf_t::block_t &b : m_log)
|
||||
{
|
||||
ut_ad(t - tmp + size <= srv_page_size);
|
||||
byte *buf= b->begin();
|
||||
log_size+= b.used();
|
||||
byte *buf= b.begin();
|
||||
if (!start)
|
||||
{
|
||||
parse:
|
||||
ut_ad(t == tmp);
|
||||
size= log_encrypt_buf(iv, t, buf, b->end());
|
||||
size= log_encrypt_buf(iv, t, buf, b.end());
|
||||
if (!size)
|
||||
{
|
||||
ut_ad(t == tmp);
|
||||
|
|
@ -591,16 +591,16 @@ ATTRIBUTE_NOINLINE void mtr_t::encrypt()
|
|||
}
|
||||
else
|
||||
{
|
||||
start= b;
|
||||
start= &b;
|
||||
start_size= t - tmp;
|
||||
}
|
||||
m_crc= my_crc32c(m_crc, buf, b->end() - buf - start_size);
|
||||
m_crc= my_crc32c(m_crc, buf, b.end() - buf - start_size);
|
||||
}
|
||||
else if (size > b->used())
|
||||
else if (size > b.used())
|
||||
{
|
||||
::memcpy(t, buf, b->used());
|
||||
t+= b->used();
|
||||
size-= b->used();
|
||||
::memcpy(t, buf, b.used());
|
||||
t+= b.used();
|
||||
size-= b.used();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -620,22 +620,22 @@ ATTRIBUTE_NOINLINE void mtr_t::encrypt()
|
|||
/* Copy the encrypted data back to the log snippets. */
|
||||
::memcpy(start->end() - start_size, dst, start_size);
|
||||
t= dst + start_size;
|
||||
for (ilist<mtr_buf_t::block_t>::iterator i(start); &*++i != b;)
|
||||
for (ilist<mtr_buf_t::block_t>::iterator i(start); &*++i != &b;)
|
||||
{
|
||||
const size_t l{i->used()};
|
||||
::memcpy(i->begin(), t, l);
|
||||
t+= l;
|
||||
}
|
||||
::memcpy(b->begin(), t, size);
|
||||
::memcpy(b.begin(), t, size);
|
||||
ut_ad(t + size == dst + len);
|
||||
t= tmp;
|
||||
start= nullptr;
|
||||
goto parse;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
ut_ad(t == tmp);
|
||||
ut_ad(!start);
|
||||
ut_ad(!size);
|
||||
return log_size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ static void insert_imported(buf_block_t *block)
|
|||
void mtr_t::release_unlogged()
|
||||
{
|
||||
ut_ad(m_log_mode == MTR_LOG_NO_REDO);
|
||||
ut_ad(m_log.size() == 0);
|
||||
ut_ad(m_log.empty());
|
||||
|
||||
process_freed_pages();
|
||||
|
||||
|
|
@ -658,13 +658,14 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name)
|
|||
ut_ad(!m_latch_ex);
|
||||
|
||||
m_latch_ex= true;
|
||||
m_commit_lsn= 0;
|
||||
|
||||
size_t size{crc32c()};
|
||||
|
||||
log_write_and_flush_prepare();
|
||||
|
||||
log_sys.latch.wr_lock(SRW_LOCK_CALL);
|
||||
|
||||
size_t size= m_log.size() + 5;
|
||||
|
||||
if (log_sys.is_encrypted())
|
||||
{
|
||||
/* We will not encrypt any FILE_ records, but we will reserve
|
||||
|
|
@ -672,12 +673,7 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name)
|
|||
size+= 8;
|
||||
m_commit_lsn= log_sys.get_flushed_lsn();
|
||||
}
|
||||
else
|
||||
m_commit_lsn= 0;
|
||||
|
||||
m_crc= 0;
|
||||
m_log.for_each_block([this](const mtr_buf_t::block_t *b)
|
||||
{ m_crc= my_crc32c(m_crc, b->begin(), b->used()); return true; });
|
||||
finish_write(size);
|
||||
|
||||
if (!name && space.max_lsn)
|
||||
|
|
@ -717,6 +713,18 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name)
|
|||
return success;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NOINLINE size_t mtr_t::crc32c() noexcept
|
||||
{
|
||||
m_crc= 0;
|
||||
size_t len= 5;
|
||||
for (const mtr_buf_t::block_t &b : m_log)
|
||||
{
|
||||
len+= b.used();
|
||||
m_crc= my_crc32c(m_crc, b.begin(), b.used());
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/** Commit a mini-transaction that did not modify any pages,
|
||||
but generated some redo log on a higher level, such as
|
||||
FILE_MODIFY records and an optional FILE_CHECKPOINT marker.
|
||||
|
|
@ -739,6 +747,7 @@ ATTRIBUTE_COLD lsn_t mtr_t::commit_files(lsn_t checkpoint_lsn)
|
|||
ut_ad(!m_latch_ex);
|
||||
|
||||
m_latch_ex= true;
|
||||
m_commit_lsn= 0;
|
||||
|
||||
if (checkpoint_lsn)
|
||||
{
|
||||
|
|
@ -748,7 +757,7 @@ ATTRIBUTE_COLD lsn_t mtr_t::commit_files(lsn_t checkpoint_lsn)
|
|||
mach_write_to_8(ptr + 3, checkpoint_lsn);
|
||||
}
|
||||
|
||||
size_t size= m_log.size() + 5;
|
||||
size_t size{crc32c()};
|
||||
|
||||
if (log_sys.is_encrypted())
|
||||
{
|
||||
|
|
@ -757,12 +766,7 @@ ATTRIBUTE_COLD lsn_t mtr_t::commit_files(lsn_t checkpoint_lsn)
|
|||
size+= 8;
|
||||
m_commit_lsn= log_sys.get_flushed_lsn();
|
||||
}
|
||||
else
|
||||
m_commit_lsn= 0;
|
||||
|
||||
m_crc= 0;
|
||||
m_log.for_each_block([this](const mtr_buf_t::block_t *b)
|
||||
{ m_crc= my_crc32c(m_crc, b->begin(), b->used()); return true; });
|
||||
finish_write(size);
|
||||
release_resources();
|
||||
|
||||
|
|
@ -1051,10 +1055,11 @@ std::pair<lsn_t,mtr_t::page_flush_ahead> mtr_t::do_write()
|
|||
{
|
||||
ut_ad(!recv_no_log_write);
|
||||
ut_ad(is_logged());
|
||||
ut_ad(m_log.size());
|
||||
ut_ad(!m_log.empty());
|
||||
ut_ad(!m_latch_ex || log_sys.latch_have_wr());
|
||||
ut_ad(!m_user_space ||
|
||||
(m_user_space->id > 0 && m_user_space->id < SRV_SPACE_ID_UPPER_BOUND));
|
||||
m_commit_lsn= 0;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
do
|
||||
|
|
@ -1072,22 +1077,7 @@ std::pair<lsn_t,mtr_t::page_flush_ahead> mtr_t::do_write()
|
|||
}
|
||||
while (0);
|
||||
#endif
|
||||
|
||||
size_t len= m_log.size() + 5;
|
||||
ut_ad(len > 5);
|
||||
|
||||
if (log_sys.is_encrypted())
|
||||
{
|
||||
len+= 8;
|
||||
encrypt();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_crc= 0;
|
||||
m_commit_lsn= 0;
|
||||
m_log.for_each_block([this](const mtr_buf_t::block_t *b)
|
||||
{ m_crc= my_crc32c(m_crc, b->begin(), b->used()); return true; });
|
||||
}
|
||||
const size_t len{log_sys.is_encrypted() ? 8 + encrypt() : crc32c()};
|
||||
|
||||
if (!m_latch_ex)
|
||||
log_sys.latch.rd_lock(SRW_LOCK_CALL);
|
||||
|
|
@ -1220,6 +1210,7 @@ mtr_t::finish_writer(mtr_t *mtr, size_t len)
|
|||
ut_ad(!recv_no_log_write);
|
||||
ut_ad(mtr->is_logged());
|
||||
ut_ad(mtr->m_latch_ex ? log_sys.latch_have_wr() : log_sys.latch_have_rd());
|
||||
ut_ad(len < recv_sys.MTR_SIZE_MAX);
|
||||
|
||||
const size_t size{mtr->m_commit_lsn ? 5U + 8U : 5U};
|
||||
std::pair<lsn_t, byte*> start=
|
||||
|
|
@ -1227,8 +1218,8 @@ mtr_t::finish_writer(mtr_t *mtr, size_t len)
|
|||
|
||||
if (!mmap)
|
||||
{
|
||||
mtr->m_log.for_each_block([&start](const mtr_buf_t::block_t *b)
|
||||
{ log_sys.append(start.second, b->begin(), b->used()); return true; });
|
||||
for (const mtr_buf_t::block_t &b : mtr->m_log)
|
||||
log_sys.append(start.second, b.begin(), b.used());
|
||||
|
||||
write_trailer:
|
||||
*start.second++= log_sys.get_sequence_bit(start.first + len - size);
|
||||
|
|
@ -1245,15 +1236,15 @@ mtr_t::finish_writer(mtr_t *mtr, size_t len)
|
|||
{
|
||||
if (UNIV_LIKELY(start.second + len <= &log_sys.buf[log_sys.file_size]))
|
||||
{
|
||||
mtr->m_log.for_each_block([&start](const mtr_buf_t::block_t *b)
|
||||
{ log_sys.append(start.second, b->begin(), b->used()); return true; });
|
||||
for (const mtr_buf_t::block_t &b : mtr->m_log)
|
||||
log_sys.append(start.second, b.begin(), b.used());
|
||||
goto write_trailer;
|
||||
}
|
||||
mtr->m_log.for_each_block([&start](const mtr_buf_t::block_t *b)
|
||||
for (const mtr_buf_t::block_t &b : mtr->m_log)
|
||||
{
|
||||
size_t size{b->used()};
|
||||
size_t size{b.used()};
|
||||
const size_t size_left(&log_sys.buf[log_sys.file_size] - start.second);
|
||||
const byte *src= b->begin();
|
||||
const byte *src= b.begin();
|
||||
if (size > size_left)
|
||||
{
|
||||
::memcpy(start.second, src, size_left);
|
||||
|
|
@ -1263,8 +1254,7 @@ mtr_t::finish_writer(mtr_t *mtr, size_t len)
|
|||
}
|
||||
::memcpy(start.second, src, size);
|
||||
start.second+= size;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
const size_t size_left(&log_sys.buf[log_sys.file_size] - start.second);
|
||||
if (size_left > size)
|
||||
goto write_trailer;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue