summaryrefslogtreecommitdiffstats
path: root/storage/innobase/include/log0log.ic
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/log0log.ic')
-rw-r--r--storage/innobase/include/log0log.ic326
1 files changed, 326 insertions, 0 deletions
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
new file mode 100644
index 00000000..d503e3ff
--- /dev/null
+++ b/storage/innobase/include/log0log.ic
@@ -0,0 +1,326 @@
+/*****************************************************************************
+
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, 2020, MariaDB Corporation.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file include/log0log.ic
+Database log
+
+Created 12/9/1995 Heikki Tuuri
+*******************************************************/
+
+#include "mach0data.h"
+#include "assume_aligned.h"
+#include "ut0crc32.h"
+
+extern ulong srv_log_buffer_size;
+
+/************************************************************//**
+Gets a log block flush bit.
+@return TRUE if this block was the first to be written in a log flush */
+UNIV_INLINE
+ibool
+log_block_get_flush_bit(
+/*====================*/
+ const byte* log_block) /*!< in: log block */
+{
+ static_assert(LOG_BLOCK_HDR_NO == 0, "compatibility");
+ static_assert(LOG_BLOCK_FLUSH_BIT_MASK == 0x80000000, "compatibility");
+
+ return *log_block & 0x80;
+}
+
+/************************************************************//**
+Sets the log block flush bit. */
+UNIV_INLINE
+void
+log_block_set_flush_bit(
+/*====================*/
+ byte* log_block, /*!< in/out: log block */
+ ibool val) /*!< in: value to set */
+{
+ static_assert(LOG_BLOCK_HDR_NO == 0, "compatibility");
+ static_assert(LOG_BLOCK_FLUSH_BIT_MASK == 0x80000000, "compatibility");
+
+ if (val)
+ *log_block|= 0x80;
+ else
+ *log_block&= 0x7f;
+}
+
+/************************************************************//**
+Gets a log block number stored in the header.
+@return log block number stored in the block header */
+UNIV_INLINE
+ulint
+log_block_get_hdr_no(
+/*=================*/
+ const byte* log_block) /*!< in: log block */
+{
+ static_assert(LOG_BLOCK_HDR_NO == 0, "compatibility");
+ return mach_read_from_4(my_assume_aligned<4>(log_block)) &
+ ~LOG_BLOCK_FLUSH_BIT_MASK;
+}
+
+/************************************************************//**
+Sets the log block number stored in the header; NOTE that this must be set
+before the flush bit! */
+UNIV_INLINE
+void
+log_block_set_hdr_no(
+/*=================*/
+ byte* log_block, /*!< in/out: log block */
+ ulint n) /*!< in: log block number: must be > 0 and
+ < LOG_BLOCK_FLUSH_BIT_MASK */
+{
+ static_assert(LOG_BLOCK_HDR_NO == 0, "compatibility");
+ ut_ad(n > 0);
+ ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK);
+
+ mach_write_to_4(my_assume_aligned<4>(log_block), n);
+}
+
+/************************************************************//**
+Gets a log block data length.
+@return log block data length measured as a byte offset from the block start */
+UNIV_INLINE
+ulint
+log_block_get_data_len(
+/*===================*/
+ const byte* log_block) /*!< in: log block */
+{
+ return mach_read_from_2(my_assume_aligned<2>
+ (log_block + LOG_BLOCK_HDR_DATA_LEN));
+}
+
+/************************************************************//**
+Sets the log block data length. */
+UNIV_INLINE
+void
+log_block_set_data_len(
+/*===================*/
+ byte* log_block, /*!< in/out: log block */
+ ulint len) /*!< in: data length */
+{
+ mach_write_to_2(my_assume_aligned<2>(log_block + LOG_BLOCK_HDR_DATA_LEN),
+ len);
+}
+
+/************************************************************//**
+Gets a log block first mtr log record group offset.
+@return first mtr log record group byte offset from the block start, 0
+if none */
+UNIV_INLINE
+ulint
+log_block_get_first_rec_group(
+/*==========================*/
+ const byte* log_block) /*!< in: log block */
+{
+ return mach_read_from_2(my_assume_aligned<2>
+ (log_block + LOG_BLOCK_FIRST_REC_GROUP));
+}
+
+/************************************************************//**
+Sets the log block first mtr log record group offset. */
+UNIV_INLINE
+void
+log_block_set_first_rec_group(
+/*==========================*/
+ byte* log_block, /*!< in/out: log block */
+ ulint offset) /*!< in: offset, 0 if none */
+{
+ mach_write_to_2(my_assume_aligned<2>
+ (log_block + LOG_BLOCK_FIRST_REC_GROUP), offset);
+}
+
+/************************************************************//**
+Gets a log block checkpoint number field (4 lowest bytes).
+@return checkpoint no (4 lowest bytes) */
+UNIV_INLINE
+ulint
+log_block_get_checkpoint_no(
+/*========================*/
+ const byte* log_block) /*!< in: log block */
+{
+ return mach_read_from_4(my_assume_aligned<4>
+ (log_block + LOG_BLOCK_CHECKPOINT_NO));
+}
+
+/************************************************************//**
+Sets a log block checkpoint number field (4 lowest bytes). */
+UNIV_INLINE
+void
+log_block_set_checkpoint_no(
+/*========================*/
+ byte* log_block, /*!< in/out: log block */
+ ib_uint64_t no) /*!< in: checkpoint no */
+{
+ mach_write_to_4(my_assume_aligned<4>(log_block + LOG_BLOCK_CHECKPOINT_NO),
+ static_cast<uint32_t>(no));
+}
+
+/************************************************************//**
+Converts a lsn to a log block number.
+@return log block number, it is > 0 and <= 1G */
+UNIV_INLINE
+ulint
+log_block_convert_lsn_to_no(
+/*========================*/
+ lsn_t lsn) /*!< in: lsn of a byte within the block */
+{
+ return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) &
+ DBUG_EVALUATE_IF("innodb_small_log_block_no_limit",
+ 0xFUL, 0x3FFFFFFFUL)) + 1);
+}
+
+/** Calculate the CRC-32C checksum of a log block.
+@param[in] block log block
+@return checksum */
+inline ulint log_block_calc_checksum_crc32(const byte* block)
+{
+ return ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM);
+}
+
+/************************************************************//**
+Gets a log block checksum field value.
+@return checksum */
+UNIV_INLINE
+ulint
+log_block_get_checksum(
+/*===================*/
+ const byte* log_block) /*!< in: log block */
+{
+ return mach_read_from_4(my_assume_aligned<4>
+ (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM +
+ log_block));
+}
+
+/************************************************************//**
+Sets a log block checksum field value. */
+UNIV_INLINE
+void
+log_block_set_checksum(
+/*===================*/
+ byte* log_block, /*!< in/out: log block */
+ ulint checksum) /*!< in: checksum */
+{
+ mach_write_to_4(my_assume_aligned<4>
+ (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM +
+ log_block), checksum);
+}
+
+/************************************************************//**
+Initializes a log block in the log buffer. */
+UNIV_INLINE
+void
+log_block_init(
+/*===========*/
+ byte* log_block, /*!< in: pointer to the log buffer */
+ lsn_t lsn) /*!< in: lsn within the log block */
+{
+ ulint no;
+
+ no = log_block_convert_lsn_to_no(lsn);
+
+ log_block_set_hdr_no(log_block, no);
+
+ log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
+ log_block_set_first_rec_group(log_block, 0);
+}
+
+/** Append a string to the log.
+@param[in] str string
+@param[in] len string length
+@param[out] start_lsn start LSN of the log record
+@return end lsn of the log record, zero if did not succeed */
+UNIV_INLINE
+lsn_t
+log_reserve_and_write_fast(
+ const void* str,
+ ulint len,
+ lsn_t* start_lsn)
+{
+ mysql_mutex_assert_owner(&log_sys.mutex);
+ ut_ad(len > 0);
+
+ const ulint data_len = len
+ + log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
+
+ if (data_len >= log_sys.trailer_offset()) {
+
+ /* The string does not fit within the current log block
+ or the log block would become full */
+
+ return(0);
+ }
+
+ lsn_t lsn = log_sys.get_lsn();
+ *start_lsn = lsn;
+
+ memcpy(log_sys.buf + log_sys.buf_free, str, len);
+
+ log_block_set_data_len(
+ reinterpret_cast<byte*>(ut_align_down(
+ log_sys.buf + log_sys.buf_free,
+ OS_FILE_LOG_BLOCK_SIZE)),
+ data_len);
+
+ log_sys.buf_free += len;
+
+ ut_ad(log_sys.buf_free <= size_t{srv_log_buffer_size});
+
+ lsn += len;
+ log_sys.set_lsn(lsn);
+
+ return lsn;
+}
+
+/***********************************************************************//**
+Checks if there is need for a log buffer flush or a new checkpoint, and does
+this if yes. Any database operation should call this when it has modified
+more than about 4 pages. NOTE that this function may only be called when the
+OS thread owns no synchronization objects except the dictionary mutex. */
+UNIV_INLINE
+void
+log_free_check(void)
+/*================*/
+{
+ /* During row_log_table_apply(), this function will be called while we
+ are holding some latches. This is OK, as long as we are not holding
+ any latches on buffer blocks. */
+
+#ifdef UNIV_DEBUG
+ static const latch_level_t latches[] = {
+ SYNC_DICT, /* dict_sys.mutex during
+ commit_try_rebuild() */
+ SYNC_DICT_OPERATION, /* dict_sys.latch X-latch during
+ commit_try_rebuild() */
+ SYNC_FTS_CACHE, /* fts_cache_t::lock */
+ SYNC_INDEX_TREE /* index->lock */
+ };
+#endif /* UNIV_DEBUG */
+
+ ut_ad(!sync_check_iterate(
+ sync_allowed_latches(latches,
+ latches + UT_ARR_SIZE(latches))));
+
+ if (log_sys.check_flush_or_checkpoint()) {
+
+ log_check_margins();
+ }
+}