summaryrefslogtreecommitdiff
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.ic201
1 files changed, 116 insertions, 85 deletions
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 38ed2b51a4e..a53f8770cea 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -25,27 +25,17 @@ Created 12/9/1995 Heikki Tuuri
#include "os0file.h"
#include "mach0data.h"
-#include "mtr0mtr.h"
#include "srv0mon.h"
+#include "srv0srv.h"
+#include "ut0crc32.h"
-#ifdef UNIV_LOG_DEBUG
-/******************************************************//**
-Checks by parsing that the catenated log segment for a single mtr is
-consistent. */
-UNIV_INTERN
-ibool
-log_check_log_recs(
-/*===============*/
- const byte* buf, /*!< in: pointer to the start of
- the log segment in the
- log_sys->buf log buffer */
- ulint len, /*!< in: segment length in bytes */
- ib_uint64_t buf_start_lsn); /*!< in: buffer start lsn */
-#endif /* UNIV_LOG_DEBUG */
+#ifdef UNIV_LOG_LSN_DEBUG
+#include "mtr0types.h"
+#endif /* UNIV_LOG_LSN_DEBUG */
/************************************************************//**
Gets a log block flush bit.
-@return TRUE if this block was the first to be written in a log flush */
+@return TRUE if this block was the first to be written in a log flush */
UNIV_INLINE
ibool
log_block_get_flush_bit(
@@ -85,7 +75,7 @@ log_block_set_flush_bit(
/************************************************************//**
Gets a log block number stored in the header.
-@return log block number stored in the block header */
+@return log block number stored in the block header */
UNIV_INLINE
ulint
log_block_get_hdr_no(
@@ -115,7 +105,7 @@ log_block_set_hdr_no(
/************************************************************//**
Gets a log block data length.
-@return log block data length measured as a byte offset from the block start */
+@return log block data length measured as a byte offset from the block start */
UNIV_INLINE
ulint
log_block_get_data_len(
@@ -164,7 +154,7 @@ log_block_set_first_rec_group(
/************************************************************//**
Gets a log block checkpoint number field (4 lowest bytes).
-@return checkpoint no (4 lowest bytes) */
+@return checkpoint no (4 lowest bytes) */
UNIV_INLINE
ulint
log_block_get_checkpoint_no(
@@ -188,7 +178,7 @@ log_block_set_checkpoint_no(
/************************************************************//**
Converts a lsn to a log block number.
-@return log block number, it is > 0 and <= 1G */
+@return log block number, it is > 0 and <= 1G */
UNIV_INLINE
ulint
log_block_convert_lsn_to_no(
@@ -200,13 +190,24 @@ log_block_convert_lsn_to_no(
/************************************************************//**
Calculates the checksum for a log block.
-@return checksum */
+@return checksum */
UNIV_INLINE
ulint
log_block_calc_checksum(
/*====================*/
const byte* block) /*!< in: log block */
{
+ return(log_checksum_algorithm_ptr(block));
+}
+
+/** Calculate the checksum for a log block using the pre-5.7.9 algorithm.
+@param[in] block log block
+@return checksum */
+UNIV_INLINE
+ulint
+log_block_calc_checksum_format_0(
+ const byte* block)
+{
ulint sum;
ulint sh;
ulint i;
@@ -228,9 +229,31 @@ log_block_calc_checksum(
return(sum);
}
+/** Calculate the checksum for a log block using the MySQL 5.7 algorithm.
+@param[in] block log block
+@return checksum */
+UNIV_INLINE
+ulint
+log_block_calc_checksum_crc32(
+ const byte* block)
+{
+ return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE));
+}
+
+/** Calculates the checksum for a log block using the "no-op" algorithm.
+@param[in] block log block
+@return checksum */
+UNIV_INLINE
+ulint
+log_block_calc_checksum_none(
+ const byte* block)
+{
+ return(LOG_NO_CHECKSUM_MAGIC);
+}
+
/************************************************************//**
Gets a log block checksum field value.
-@return checksum */
+@return checksum */
UNIV_INLINE
ulint
log_block_get_checksum(
@@ -266,8 +289,6 @@ log_block_init(
{
ulint no;
- ut_ad(mutex_own(&(log_sys->mutex)));
-
no = log_block_convert_lsn_to_no(lsn);
log_block_set_hdr_no(log_block, no);
@@ -276,6 +297,7 @@ log_block_init(
log_block_set_first_rec_group(log_block, 0);
}
+#ifdef UNIV_HOTBACKUP
/************************************************************//**
Initializes a log block in the log buffer in the old format, where there
was no checksum yet. */
@@ -288,7 +310,7 @@ log_block_init_in_old_format(
{
ulint no;
- ut_ad(mutex_own(&(log_sys->mutex)));
+ ut_ad(log_mutex_own());
no = log_block_convert_lsn_to_no(lsn);
@@ -298,34 +320,47 @@ log_block_init_in_old_format(
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
log_block_set_first_rec_group(log_block, 0);
}
+#endif /* UNIV_HOTBACKUP */
#ifndef UNIV_HOTBACKUP
-/************************************************************//**
-Writes to the log the string given. The log must be released with
-log_release.
-@return end lsn of the log record, zero if did not succeed */
+/** 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, /*!< in: string */
- ulint len, /*!< in: string length */
- lsn_t* start_lsn)/*!< out: start lsn of the log record */
+ const void* str,
+ ulint len,
+ lsn_t* start_lsn)
{
- ulint data_len;
-#ifdef UNIV_LOG_LSN_DEBUG
- /* length of the LSN pseudo-record */
- ulint lsn_len;
-#endif /* UNIV_LOG_LSN_DEBUG */
+ ut_ad(log_mutex_own());
+ ut_ad(len > 0);
- mutex_enter(&log_sys->mutex);
#ifdef UNIV_LOG_LSN_DEBUG
- lsn_len = 1
+ /* Append a MLOG_LSN record after mtr_commit(), except when
+ the last bytes could be a MLOG_CHECKPOINT marker. We have special
+ handling when the log consists of only a single MLOG_CHECKPOINT
+ record since the latest checkpoint, and appending the
+ MLOG_LSN would ruin that.
+
+ Note that a longer redo log record could happen to end in what
+ looks like MLOG_CHECKPOINT, and we could be omitting MLOG_LSN
+ without reason. This is OK, because writing the MLOG_LSN is
+ just a 'best effort', aimed at finding log corruption due to
+ bugs in the redo log writing logic. */
+ const ulint lsn_len
+ = len >= SIZE_OF_MLOG_CHECKPOINT
+ && MLOG_CHECKPOINT == static_cast<const char*>(str)[
+ len - SIZE_OF_MLOG_CHECKPOINT]
+ ? 0
+ : 1
+ mach_get_compressed_size(log_sys->lsn >> 32)
+ mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL);
#endif /* UNIV_LOG_LSN_DEBUG */
- data_len = len
+ const ulint data_len = len
#ifdef UNIV_LOG_LSN_DEBUG
+ lsn_len
#endif /* UNIV_LOG_LSN_DEBUG */
@@ -336,39 +371,37 @@ log_reserve_and_write_fast(
/* The string does not fit within the current log block
or the log block would become full */
- mutex_exit(&log_sys->mutex);
-
return(0);
}
*start_lsn = log_sys->lsn;
#ifdef UNIV_LOG_LSN_DEBUG
- {
+ if (lsn_len) {
/* Write the LSN pseudo-record. */
byte* b = &log_sys->buf[log_sys->buf_free];
+
*b++ = MLOG_LSN | (MLOG_SINGLE_REC_FLAG & *(const byte*) str);
+
/* Write the LSN in two parts,
as a pseudo page number and space id. */
b += mach_write_compressed(b, log_sys->lsn >> 32);
b += mach_write_compressed(b, log_sys->lsn & 0xFFFFFFFFUL);
ut_a(b - lsn_len == &log_sys->buf[log_sys->buf_free]);
- memcpy(b, str, len);
+ ::memcpy(b, str, len);
+
len += lsn_len;
- }
-#else /* UNIV_LOG_LSN_DEBUG */
- memcpy(log_sys->buf + log_sys->buf_free, str, len);
+ } else
#endif /* UNIV_LOG_LSN_DEBUG */
+ 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_block_set_data_len((byte*) ut_align_down(log_sys->buf
- + log_sys->buf_free,
- OS_FILE_LOG_BLOCK_SIZE),
- data_len);
-#ifdef UNIV_LOG_DEBUG
- log_sys->old_buf_free = log_sys->buf_free;
- log_sys->old_lsn = log_sys->lsn;
-#endif
log_sys->buf_free += len;
ut_ad(log_sys->buf_free <= log_sys->buf_size);
@@ -378,27 +411,12 @@ log_reserve_and_write_fast(
MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE,
log_sys->lsn - log_sys->last_checkpoint_lsn);
-#ifdef UNIV_LOG_DEBUG
- log_check_log_recs(log_sys->buf + log_sys->old_buf_free,
- log_sys->buf_free - log_sys->old_buf_free,
- log_sys->old_lsn);
-#endif
return(log_sys->lsn);
}
-/***********************************************************************//**
-Releases the log mutex. */
-UNIV_INLINE
-void
-log_release(void)
-/*=============*/
-{
- mutex_exit(&(log_sys->mutex));
-}
-
/************************************************************//**
Gets the current lsn.
-@return current lsn */
+@return current lsn */
UNIV_INLINE
lsn_t
log_get_lsn(void)
@@ -406,11 +424,11 @@ log_get_lsn(void)
{
lsn_t lsn;
- mutex_enter(&(log_sys->mutex));
+ log_mutex_enter();
lsn = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
+ log_mutex_exit();
return(lsn);
}
@@ -421,15 +439,14 @@ Gets the last lsn that is fully flushed to disk.
UNIV_INLINE
ib_uint64_t
log_get_flush_lsn(void)
-/*=============*/
{
ib_uint64_t lsn;
- mutex_enter(&(log_sys->mutex));
+ log_mutex_enter();
lsn = log_sys->flushed_to_disk_lsn;
- mutex_exit(&(log_sys->mutex));
+ log_mutex_exit();
return(lsn);
}
@@ -440,7 +457,7 @@ Gets the current lsn with a trylock
UNIV_INLINE
lsn_t
log_get_lsn_nowait(void)
-/*=============*/
+/*====================*/
{
lsn_t lsn=0;
@@ -457,7 +474,7 @@ log_get_lsn_nowait(void)
/****************************************************************
Gets the log group capacity. It is OK to read the value without
holding log_sys->mutex because it is constant.
-@return log group capacity */
+@return log group capacity */
UNIV_INLINE
lsn_t
log_get_capacity(void)
@@ -469,7 +486,7 @@ log_get_capacity(void)
/****************************************************************
Get log_sys::max_modified_age_async. It is OK to read the value without
holding log_sys::mutex because it is constant.
-@return max_modified_age_async */
+@return max_modified_age_async */
UNIV_INLINE
lsn_t
log_get_max_modified_age_async(void)
@@ -488,10 +505,24 @@ void
log_free_check(void)
/*================*/
{
-
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(sync_thread_levels_empty_except_dict());
-#endif /* UNIV_SYNC_DEBUG */
+#ifdef UNIV_DEBUG
+ /* 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. */
+
+ static const latch_level_t latches[] = {
+ SYNC_DICT, /* dict_sys->mutex during
+ commit_try_rebuild() */
+ SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during
+ commit_try_rebuild() */
+ SYNC_INDEX_TREE /* index->lock */
+ };
+
+ sync_allowed_latches check(
+ latches, latches + sizeof(latches)/sizeof(*latches));
+
+ ut_ad(!sync_check_iterate(check));
+#endif /* UNIV_DEBUG */
if (log_sys->check_flush_or_checkpoint) {