Commit baa5a43d authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-16045: Replace log_group_t with log_t::files

There is only one log_sys and only one log_sys.log.

log_t::files::create(): Replaces log_init().

log_t::files::close(): Replaces log_group_close(), log_group_close_all().

fil_close_log_files(): if (free) log_sys.log_close();
The callers that passed free=true used to call log_group_close_all().

log_header_read(): Replaces log_group_header_read().

log_t::files::file_header_bufs_ptr: Use a single allocation.

log_t::files::file_header_bufs[]: Statically allocate the pointers.

log_t::files::set_fields(): Replaces log_group_set_fields().

log_t::files::calc_lsn_offset(): Replaces log_group_calc_lsn_offset().
Simplify the computation by using fewer variables.

log_t::files::read_log_seg(): Replaces log_group_read_log_seg().

log_sys_t::complete_checkpoint(): Replaces log_io_complete_checkpoint().

fil_aio_wait(): Move the logic from log_io_complete().
parent d73a898d
...@@ -2544,8 +2544,7 @@ xtrabackup_copy_logfile(copy_logfile copy) ...@@ -2544,8 +2544,7 @@ xtrabackup_copy_logfile(copy_logfile copy)
lsn_t lsn= start_lsn; lsn_t lsn= start_lsn;
for(int retries= 0; retries < 100; retries++) { for(int retries= 0; retries < 100; retries++) {
if (log_group_read_log_seg(log_sys.buf, &log_sys.log, if (log_sys.log.read_log_seg(&lsn, end_lsn)) {
&lsn, end_lsn)){
break; break;
} }
msg("Retrying read of a redo log block"); msg("Retrying read of a redo log block");
...@@ -3819,7 +3818,7 @@ xtrabackup_backup_func() ...@@ -3819,7 +3818,7 @@ xtrabackup_backup_func()
SRV_MAX_N_PENDING_SYNC_IOS); SRV_MAX_N_PENDING_SYNC_IOS);
log_sys.create(); log_sys.create();
log_init(srv_n_log_files); log_sys.log.create(srv_n_log_files);
fil_space_t* space = fil_space_create( fil_space_t* space = fil_space_create(
"innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0, "innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0,
FIL_TYPE_LOG, NULL); FIL_TYPE_LOG, NULL);
...@@ -3924,7 +3923,7 @@ xtrabackup_backup_func() ...@@ -3924,7 +3923,7 @@ xtrabackup_backup_func()
ut_ad(!((log_sys.log.format ^ LOG_HEADER_FORMAT_CURRENT) ut_ad(!((log_sys.log.format ^ LOG_HEADER_FORMAT_CURRENT)
& ~LOG_HEADER_FORMAT_ENCRYPTED)); & ~LOG_HEADER_FORMAT_ENCRYPTED));
log_group_header_read(&log_sys.log, max_cp_field); log_header_read(max_cp_field);
if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) { if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
goto reread_log_header; goto reread_log_header;
......
...@@ -2007,6 +2007,10 @@ fil_close_log_files( ...@@ -2007,6 +2007,10 @@ fil_close_log_files(
} }
mutex_exit(&fil_system.mutex); mutex_exit(&fil_system.mutex);
if (free) {
log_sys.log.close();
}
} }
/*******************************************************************//** /*******************************************************************//**
...@@ -4685,7 +4689,26 @@ fil_aio_wait( ...@@ -4685,7 +4689,26 @@ fil_aio_wait(
switch (purpose) { switch (purpose) {
case FIL_TYPE_LOG: case FIL_TYPE_LOG:
srv_set_io_thread_op_info(segment, "complete io for log"); srv_set_io_thread_op_info(segment, "complete io for log");
log_io_complete(static_cast<log_group_t*>(message)); /* We use synchronous writing of the logs
and can only end up here when writing a log checkpoint! */
ut_a(ptrdiff_t(message) == 1);
/* It was a checkpoint write */
switch (srv_file_flush_method) {
case SRV_O_DSYNC:
case SRV_NOSYNC:
break;
case SRV_FSYNC:
case SRV_LITTLESYNC:
case SRV_O_DIRECT:
case SRV_O_DIRECT_NO_FSYNC:
#ifdef _WIN32
case SRV_ALL_O_DIRECT_FSYNC:
#endif
fil_flush(SRV_LOG_SPACE_FIRST_ID);
}
DBUG_PRINT("ib_log", ("checkpoint info written"));
log_sys.complete_checkpoint();
return; return;
case FIL_TYPE_TABLESPACE: case FIL_TYPE_TABLESPACE:
case FIL_TYPE_TEMPORARY: case FIL_TYPE_TEMPORARY:
......
...@@ -41,8 +41,8 @@ Created 12/9/1995 Heikki Tuuri ...@@ -41,8 +41,8 @@ Created 12/9/1995 Heikki Tuuri
#include "os0event.h" #include "os0event.h"
#include "os0file.h" #include "os0file.h"
/** Redo log group */ /** Maximum number of srv_n_log_files, or innodb_log_files_in_group */
struct log_group_t; #define SRV_N_LOG_FILES_MAX 100
/** Magic value to use instead of log checksums when they are disabled */ /** Magic value to use instead of log checksums when they are disabled */
#define LOG_NO_CHECKSUM_MAGIC 0xDEADBEEFUL #define LOG_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
...@@ -151,10 +151,6 @@ lsn_t ...@@ -151,10 +151,6 @@ lsn_t
log_get_max_modified_age_async(void); log_get_max_modified_age_async(void);
/*================================*/ /*================================*/
/** Initialize the redo log.
@param[in] n_files number of files */
void
log_init(ulint n_files);
/** Calculate the recommended highest values for lsn - last_checkpoint_lsn /** Calculate the recommended highest values for lsn - last_checkpoint_lsn
and lsn - buf_get_oldest_modification(). and lsn - buf_get_oldest_modification().
@param[in] file_size requested innodb_log_file_size @param[in] file_size requested innodb_log_file_size
...@@ -166,12 +162,6 @@ log_set_capacity(ulonglong file_size) ...@@ -166,12 +162,6 @@ log_set_capacity(ulonglong file_size)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/******************************************************//** /******************************************************//**
Completes an i/o to a log file. */
void
log_io_complete(
/*============*/
log_group_t* group); /*!< in: log group */
/******************************************************//**
This function is called, e.g., when a transaction wants to commit. It checks This function is called, e.g., when a transaction wants to commit. It checks
that the log has been written to the log file up to the last log entry written that the log has been written to the log file up to the last log entry written
by the transaction. If there is a flush running, it waits and checks if the by the transaction. If there is a flush running, it waits and checks if the
...@@ -231,12 +221,8 @@ void ...@@ -231,12 +221,8 @@ void
logs_empty_and_mark_files_at_shutdown(void); logs_empty_and_mark_files_at_shutdown(void);
/*=======================================*/ /*=======================================*/
/** Read a log group header page to log_sys.checkpoint_buf. /** Read a log group header page to log_sys.checkpoint_buf.
@param[in] group log group @param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 */
@param[in] header 0 or LOG_CHEKCPOINT_1 or LOG_CHECKPOINT2 */ void log_header_read(ulint header);
void
log_group_header_read(
const log_group_t* group,
ulint header);
/** Write checkpoint info to the log header and invoke log_mutex_exit(). /** Write checkpoint info to the log header and invoke log_mutex_exit().
@param[in] sync whether to wait for the write to complete @param[in] sync whether to wait for the write to complete
@param[in] end_lsn start LSN of the MLOG_CHECKPOINT mini-transaction */ @param[in] end_lsn start LSN of the MLOG_CHECKPOINT mini-transaction */
...@@ -257,16 +243,6 @@ objects! */ ...@@ -257,16 +243,6 @@ objects! */
void void
log_check_margins(void); log_check_margins(void);
/********************************************************//**
Sets the field values in group to correspond to a given lsn. For this function
to work, the values must already be correctly initialized to correspond to
some lsn, for instance, a checkpoint lsn. */
void
log_group_set_fields(
/*=================*/
log_group_t* group, /*!< in/out: group */
lsn_t lsn); /*!< in: lsn for which the values should be
set */
/************************************************************//** /************************************************************//**
Gets a log block flush bit. 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 */
...@@ -398,11 +374,6 @@ Refreshes the statistics used to print per-second averages. */ ...@@ -398,11 +374,6 @@ Refreshes the statistics used to print per-second averages. */
void void
log_refresh_stats(void); log_refresh_stats(void);
/*===================*/ /*===================*/
/********************************************************//**
Closes all log groups. */
void
log_group_close_all(void);
/*=====================*/
/** Whether to generate and require checksums on the redo log pages */ /** Whether to generate and require checksums on the redo log pages */
extern my_bool innodb_log_checksums; extern my_bool innodb_log_checksums;
...@@ -536,50 +507,6 @@ enum log_group_state_t { ...@@ -536,50 +507,6 @@ enum log_group_state_t {
typedef ib_mutex_t LogSysMutex; typedef ib_mutex_t LogSysMutex;
typedef ib_mutex_t FlushOrderMutex; typedef ib_mutex_t FlushOrderMutex;
/** Log group consists of a number of log files, each of the same size; a log
group is implemented as a space in the sense of the module fil0fil.
Currently, this is only protected by log_sys.mutex. However, in the case
of log_write_up_to(), we will access some members only with the protection
of log_sys.write_mutex, which should affect nothing for now. */
struct log_group_t{
/** number of files in the group */
ulint n_files;
/** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */
ulint format;
/** individual log file size in bytes, including the header */
lsn_t file_size;
/** corruption status */
log_group_state_t state;
/** lsn used to fix coordinates within the log group */
lsn_t lsn;
/** the byte offset of the above lsn */
lsn_t lsn_offset;
/** unaligned buffers */
byte** file_header_bufs_ptr;
/** buffers for each file header in the group */
byte** file_header_bufs;
/** used only in recovery: recovery scan succeeded up to this
lsn in this log group */
lsn_t scanned_lsn;
/** unaligned checkpoint header */
byte* checkpoint_buf_ptr;
/** buffer for writing a checkpoint header */
byte* checkpoint_buf;
/** @return whether the redo log is encrypted */
bool is_encrypted() const
{
return((format & LOG_HEADER_FORMAT_ENCRYPTED) != 0);
}
/** @return capacity in bytes */
inline lsn_t capacity() const
{
return((file_size - LOG_FILE_HDR_SIZE) * n_files);
}
};
/** Redo log buffer */ /** Redo log buffer */
struct log_t{ struct log_t{
MY_ALIGNED(CACHE_LINE_SIZE) MY_ALIGNED(CACHE_LINE_SIZE)
...@@ -590,8 +517,7 @@ struct log_t{ ...@@ -590,8 +517,7 @@ struct log_t{
MY_ALIGNED(CACHE_LINE_SIZE) MY_ALIGNED(CACHE_LINE_SIZE)
LogSysMutex mutex; /*!< mutex protecting the log */ LogSysMutex mutex; /*!< mutex protecting the log */
MY_ALIGNED(CACHE_LINE_SIZE) MY_ALIGNED(CACHE_LINE_SIZE)
LogSysMutex write_mutex; /*!< mutex protecting writing to log LogSysMutex write_mutex; /*!< mutex protecting writing to log */
file and accessing to log_group_t */
MY_ALIGNED(CACHE_LINE_SIZE) MY_ALIGNED(CACHE_LINE_SIZE)
FlushOrderMutex log_flush_order_mutex;/*!< mutex to serialize access to FlushOrderMutex log_flush_order_mutex;/*!< mutex to serialize access to
the flush list when we are putting the flush list when we are putting
...@@ -626,8 +552,67 @@ struct log_t{ ...@@ -626,8 +552,67 @@ struct log_t{
max_checkpoint_age; this flag is max_checkpoint_age; this flag is
peeked at by log_free_check(), which peeked at by log_free_check(), which
does not reserve the log mutex */ does not reserve the log mutex */
/** the redo log */
log_group_t log; /** Log files. Protected by mutex or write_mutex. */
struct files {
/** number of files */
ulint n_files;
/** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */
ulint format;
/** individual log file size in bytes, including the header */
lsn_t file_size;
/** corruption status */
log_group_state_t state;
/** lsn used to fix coordinates within the log group */
lsn_t lsn;
/** the byte offset of the above lsn */
lsn_t lsn_offset;
/** unaligned buffers */
byte* file_header_bufs_ptr;
/** buffers for each file header in the group */
byte* file_header_bufs[SRV_N_LOG_FILES_MAX];
/** used only in recovery: recovery scan succeeded up to this
lsn in this log group */
lsn_t scanned_lsn;
/** @return whether the redo log is encrypted */
bool is_encrypted() const { return format & LOG_HEADER_FORMAT_ENCRYPTED; }
/** @return capacity in bytes */
lsn_t capacity() const{ return (file_size - LOG_FILE_HDR_SIZE) * n_files; }
/** Calculate the offset of a log sequence number.
@param[in] lsn log sequence number
@return offset within the log */
inline lsn_t calc_lsn_offset(lsn_t lsn) const;
/** Set the field values to correspond to a given lsn. */
void set_fields(lsn_t lsn)
{
lsn_offset = calc_lsn_offset(lsn);
this->lsn = lsn;
}
/** Read a log segment to log_sys.buf.
@param[in,out] start_lsn in: read area start,
out: the last read valid lsn
@param[in] end_lsn read area end
@return whether no invalid blocks (e.g checksum mismatch) were found */
bool read_log_seg(lsn_t* start_lsn, lsn_t end_lsn);
/** Initialize the redo log buffer.
@param[in] n_files number of files */
void create(ulint n_files);
/** Close the redo log buffer. */
void close()
{
ut_free(file_header_bufs_ptr);
n_files = 0;
file_header_bufs_ptr = NULL;
memset(file_header_bufs, 0, sizeof file_header_bufs);
}
} log;
/** The fields involved in the log buffer flush @{ */ /** The fields involved in the log buffer flush @{ */
...@@ -730,6 +715,9 @@ struct log_t{ ...@@ -730,6 +715,9 @@ struct log_t{
bool is_initialised() { return m_initialised; } bool is_initialised() { return m_initialised; }
/** Complete an asynchronous checkpoint write. */
void complete_checkpoint();
/** Initialise the redo log subsystem. */ /** Initialise the redo log subsystem. */
void create(); void create();
...@@ -740,6 +728,27 @@ struct log_t{ ...@@ -740,6 +728,27 @@ struct log_t{
/** Redo log system */ /** Redo log system */
extern log_t log_sys; extern log_t log_sys;
/** Calculate the offset of a log sequence number.
@param[in] lsn log sequence number
@return offset within the log */
inline lsn_t log_t::files::calc_lsn_offset(lsn_t lsn) const
{
ut_ad(this == &log_sys.log);
/* The lsn parameters are updated while holding both the mutexes
and it is ok to have either of them while reading */
ut_ad(log_sys.mutex.is_owned() || log_sys.write_mutex.is_owned());
const lsn_t group_size= capacity();
lsn_t l= lsn - this->lsn;
if (longlong(l) < 0) {
l= lsn_t(-longlong(l)) % group_size;
l= group_size - l;
}
l+= lsn_offset - LOG_FILE_HDR_SIZE * (1 + lsn_offset / file_size);
l%= group_size;
return l + LOG_FILE_HDR_SIZE * (1 + l / (file_size - LOG_FILE_HDR_SIZE));
}
/** Test if flush order mutex is owned. */ /** Test if flush order mutex is owned. */
#define log_flush_order_mutex_own() \ #define log_flush_order_mutex_own() \
mutex_own(&log_sys.log_flush_order_mutex) mutex_own(&log_sys.log_flush_order_mutex)
...@@ -783,15 +792,6 @@ extern log_t log_sys; ...@@ -783,15 +792,6 @@ extern log_t log_sys;
mutex_exit(&log_sys.write_mutex); \ mutex_exit(&log_sys.write_mutex); \
} while (0) } while (0)
/** Calculate the offset of an lsn within a log group.
@param[in] lsn log sequence number
@param[in] group log group
@return offset within the log group */
lsn_t
log_group_calc_lsn_offset(
lsn_t lsn,
const log_group_t* group);
/* log scrubbing speed, in bytes/sec */ /* log scrubbing speed, in bytes/sec */
extern ulonglong innodb_scrub_log_speed; extern ulonglong innodb_scrub_log_speed;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, 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
...@@ -96,20 +96,6 @@ void ...@@ -96,20 +96,6 @@ void
recv_sys_debug_free(void); recv_sys_debug_free(void);
/*=====================*/ /*=====================*/
/** Read a log segment to a buffer.
@param[out] buf buffer
@param[in] group redo log files
@param[in, out] start_lsn in : read area start, out: the last read valid lsn
@param[in] end_lsn read area end
@param[out] invalid_block - invalid, (maybe incompletely written) block encountered
@return false, if invalid block encountered (e.g checksum mismatch), true otherwise */
bool
log_group_read_log_seg(
byte* buf,
const log_group_t* group,
lsn_t* start_lsn,
lsn_t end_lsn);
/********************************************************//** /********************************************************//**
Reset the state of the recovery system variables. */ Reset the state of the recovery system variables. */
void void
......
...@@ -339,8 +339,6 @@ extern const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; ...@@ -339,8 +339,6 @@ extern const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
extern char* srv_log_group_home_dir; extern char* srv_log_group_home_dir;
/** Maximum number of srv_n_log_files, or innodb_log_files_in_group */
#define SRV_N_LOG_FILES_MAX 100
extern ulong srv_n_log_files; extern ulong srv_n_log_files;
/** The InnoDB redo log file size, or 0 when changing the redo log format /** The InnoDB redo log file size, or 0 when changing the redo log format
at startup (while disallowing writes to the redo log). */ at startup (while disallowing writes to the redo log). */
......
...@@ -134,13 +134,6 @@ extern "C" UNIV_INTERN ...@@ -134,13 +134,6 @@ extern "C" UNIV_INTERN
os_thread_ret_t os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(void*); DECLARE_THREAD(log_scrub_thread)(void*);
/******************************************************//**
Completes a checkpoint write i/o to a log file. */
static
void
log_io_complete_checkpoint(void);
/*============================*/
/****************************************************************//** /****************************************************************//**
Returns the oldest modified block lsn in the pool, or log_sys.lsn if none Returns the oldest modified block lsn in the pool, or log_sys.lsn if none
exists. exists.
...@@ -541,108 +534,6 @@ log_close(void) ...@@ -541,108 +534,6 @@ log_close(void)
return(lsn); return(lsn);
} }
/******************************************************//**
Calculates the offset within a log group, when the log file headers are not
included.
@return size offset (<= offset) */
UNIV_INLINE
lsn_t
log_group_calc_size_offset(
/*=======================*/
lsn_t offset, /*!< in: real offset within the
log group */
const log_group_t* group) /*!< in: log group */
{
/* The lsn parameters are updated while holding both the mutexes
and it is ok to have either of them while reading */
ut_ad(log_mutex_own() || log_write_mutex_own());
return(offset - LOG_FILE_HDR_SIZE * (1 + offset / group->file_size));
}
/******************************************************//**
Calculates the offset within a log group, when the log file headers are
included.
@return real offset (>= offset) */
UNIV_INLINE
lsn_t
log_group_calc_real_offset(
/*=======================*/
lsn_t offset, /*!< in: size offset within the
log group */
const log_group_t* group) /*!< in: log group */
{
/* The lsn parameters are updated while holding both the mutexes
and it is ok to have either of them while reading */
ut_ad(log_mutex_own() || log_write_mutex_own());
return(offset + LOG_FILE_HDR_SIZE
* (1 + offset / (group->file_size - LOG_FILE_HDR_SIZE)));
}
/** Calculate the offset of an lsn within a log group.
@param[in] lsn log sequence number
@param[in] group log group
@return offset within the log group */
lsn_t
log_group_calc_lsn_offset(
lsn_t lsn,
const log_group_t* group)
{
lsn_t gr_lsn;
lsn_t gr_lsn_size_offset;
lsn_t difference;
lsn_t group_size;
lsn_t offset;
/* The lsn parameters are updated while holding both the mutexes
and it is ok to have either of them while reading */
ut_ad(log_mutex_own() || log_write_mutex_own());
gr_lsn = group->lsn;
gr_lsn_size_offset = log_group_calc_size_offset(
group->lsn_offset, group);
group_size = group->capacity();
if (lsn >= gr_lsn) {
difference = lsn - gr_lsn;
} else {
difference = gr_lsn - lsn;
difference = difference % group_size;
difference = group_size - difference;
}
offset = (gr_lsn_size_offset + difference) % group_size;
/* fprintf(stderr,
"Offset is " LSN_PF " gr_lsn_offset is " LSN_PF
" difference is " LSN_PF "\n",
offset, gr_lsn_size_offset, difference);
*/
return(log_group_calc_real_offset(offset, group));
}
/********************************************************//**
Sets the field values in group to correspond to a given lsn. For this function
to work, the values must already be correctly initialized to correspond to
some lsn, for instance, a checkpoint lsn. */
void
log_group_set_fields(
/*=================*/
log_group_t* group, /*!< in/out: group */
lsn_t lsn) /*!< in: lsn for which the values should be
set */
{
group->lsn_offset = log_group_calc_lsn_offset(lsn, group);
group->lsn = lsn;
}
/** Calculate the recommended highest values for lsn - last_checkpoint_lsn /** Calculate the recommended highest values for lsn - last_checkpoint_lsn
and lsn - buf_get_oldest_modification(). and lsn - buf_get_oldest_modification().
@param[in] file_size requested innodb_log_file_size @param[in] file_size requested innodb_log_file_size
...@@ -767,87 +658,38 @@ void log_t::create() ...@@ -767,87 +658,38 @@ void log_t::create()
/** Initialize the redo log. /** Initialize the redo log.
@param[in] n_files number of files */ @param[in] n_files number of files */
void void log_t::files::create(ulint n_files)
log_init(ulint n_files)
{
ulint i;
log_group_t* group = &log_sys.log;
group->n_files = n_files;
group->format = srv_encrypt_log
? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED
: LOG_HEADER_FORMAT_CURRENT;
group->file_size = srv_log_file_size;
group->state = LOG_GROUP_OK;
group->lsn = LOG_START_LSN;
group->lsn_offset = LOG_FILE_HDR_SIZE;
group->file_header_bufs_ptr = static_cast<byte**>(
ut_zalloc_nokey(sizeof(byte*) * n_files));
group->file_header_bufs = static_cast<byte**>(
ut_zalloc_nokey(sizeof(byte**) * n_files));
for (i = 0; i < n_files; i++) {
group->file_header_bufs_ptr[i] = static_cast<byte*>(
ut_zalloc_nokey(LOG_FILE_HDR_SIZE
+ OS_FILE_LOG_BLOCK_SIZE));
group->file_header_bufs[i] = static_cast<byte*>(
ut_align(group->file_header_bufs_ptr[i],
OS_FILE_LOG_BLOCK_SIZE));
}
group->checkpoint_buf_ptr = static_cast<byte*>(
ut_zalloc_nokey(2 * OS_FILE_LOG_BLOCK_SIZE));
group->checkpoint_buf = static_cast<byte*>(
ut_align(group->checkpoint_buf_ptr,OS_FILE_LOG_BLOCK_SIZE));
}
/******************************************************//**
Completes an i/o to a log file. */
void
log_io_complete(
/*============*/
log_group_t* group) /*!< in: log group or a dummy pointer */
{ {
if ((ulint) group & 0x1UL) { ut_ad(n_files <= SRV_N_LOG_FILES_MAX);
/* It was a checkpoint write */ ut_ad(this == &log_sys.log);
group = (log_group_t*)((ulint) group - 1); ut_ad(log_sys.is_initialised());
switch (srv_file_flush_method) { this->n_files= n_files;
case SRV_O_DSYNC: format= srv_encrypt_log
case SRV_NOSYNC: ? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED
break; : LOG_HEADER_FORMAT_CURRENT;
case SRV_FSYNC: file_size= srv_log_file_size;
case SRV_LITTLESYNC: state= LOG_GROUP_OK;
case SRV_O_DIRECT: lsn= LOG_START_LSN;
case SRV_O_DIRECT_NO_FSYNC: lsn_offset= LOG_FILE_HDR_SIZE;
#ifdef _WIN32
case SRV_ALL_O_DIRECT_FSYNC:
#endif
fil_flush(SRV_LOG_SPACE_FIRST_ID);
}
DBUG_PRINT("ib_log", ("checkpoint info written")); byte* ptr= static_cast<byte*>(ut_zalloc_nokey(LOG_FILE_HDR_SIZE
log_io_complete_checkpoint(); + OS_FILE_LOG_BLOCK_SIZE
* n_files));
file_header_bufs_ptr= ptr;
ptr= static_cast<byte*>(ut_align(ptr, OS_FILE_LOG_BLOCK_SIZE));
return; memset(file_header_bufs, 0, sizeof file_header_bufs);
}
ut_error; /*!< We currently use synchronous writing of the for (ulint i = 0; i < n_files; i++, ptr += LOG_FILE_HDR_SIZE)
logs and cannot end up here! */ file_header_bufs[i] = ptr;
} }
/******************************************************//** /******************************************************//**
Writes a log file header to a log file space. */ Writes a log file header to a log file space. */
static static
void void
log_group_file_header_flush( log_file_header_flush(
/*========================*/
log_group_t* group, /*!< in: log group */
ulint nth_file, /*!< in: header to the nth file in the ulint nth_file, /*!< in: header to the nth file in the
log file space */ log file space */
lsn_t start_lsn) /*!< in: log file data starts at this lsn_t start_lsn) /*!< in: log file data starts at this
...@@ -858,14 +700,14 @@ log_group_file_header_flush( ...@@ -858,14 +700,14 @@ log_group_file_header_flush(
ut_ad(log_write_mutex_own()); ut_ad(log_write_mutex_own());
ut_ad(!recv_no_log_write); ut_ad(!recv_no_log_write);
ut_a(nth_file < group->n_files); ut_a(nth_file < log_sys.log.n_files);
ut_ad((group->format & ~LOG_HEADER_FORMAT_ENCRYPTED) ut_ad((log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
== LOG_HEADER_FORMAT_CURRENT); == LOG_HEADER_FORMAT_CURRENT);
buf = *(group->file_header_bufs + nth_file); buf = log_sys.log.file_header_bufs[nth_file];
memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE); memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE);
mach_write_to_4(buf + LOG_HEADER_FORMAT, group->format); mach_write_to_4(buf + LOG_HEADER_FORMAT, log_sys.log.format);
mach_write_to_8(buf + LOG_HEADER_START_LSN, start_lsn); mach_write_to_8(buf + LOG_HEADER_START_LSN, start_lsn);
strcpy(reinterpret_cast<char*>(buf) + LOG_HEADER_CREATOR, strcpy(reinterpret_cast<char*>(buf) + LOG_HEADER_CREATOR,
LOG_HEADER_CREATOR_CURRENT); LOG_HEADER_CREATOR_CURRENT);
...@@ -873,7 +715,7 @@ log_group_file_header_flush( ...@@ -873,7 +715,7 @@ log_group_file_header_flush(
>= sizeof LOG_HEADER_CREATOR_CURRENT); >= sizeof LOG_HEADER_CREATOR_CURRENT);
log_block_set_checksum(buf, log_block_calc_checksum_crc32(buf)); log_block_set_checksum(buf, log_block_calc_checksum_crc32(buf));
dest_offset = nth_file * group->file_size; dest_offset = nth_file * log_sys.log.file_size;
DBUG_PRINT("ib_log", ("write " LSN_PF DBUG_PRINT("ib_log", ("write " LSN_PF
" file " ULINTPF " header", " file " ULINTPF " header",
...@@ -891,7 +733,7 @@ log_group_file_header_flush( ...@@ -891,7 +733,7 @@ log_group_file_header_flush(
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
univ_page_size, univ_page_size,
ulint(dest_offset & (srv_page_size - 1)), ulint(dest_offset & (srv_page_size - 1)),
OS_FILE_LOG_BLOCK_SIZE, buf, group); OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
srv_stats.os_log_pending_writes.dec(); srv_stats.os_log_pending_writes.dec();
} }
...@@ -910,12 +752,10 @@ log_block_store_checksum( ...@@ -910,12 +752,10 @@ log_block_store_checksum(
} }
/******************************************************//** /******************************************************//**
Writes a buffer to a log file group. */ Writes a buffer to a log file. */
static static
void void
log_group_write_buf( log_write_buf(
/*================*/
log_group_t* group, /*!< in: log group */
byte* buf, /*!< in: buffer */ byte* buf, /*!< in: buffer */
ulint len, /*!< in: buffer len; must be divisible ulint len, /*!< in: buffer len; must be divisible
by OS_FILE_LOG_BLOCK_SIZE */ by OS_FILE_LOG_BLOCK_SIZE */
...@@ -946,28 +786,27 @@ log_group_write_buf( ...@@ -946,28 +786,27 @@ log_group_write_buf(
return; return;
} }
next_offset = log_group_calc_lsn_offset(start_lsn, group); next_offset = log_sys.log.calc_lsn_offset(start_lsn);
if (write_header if (write_header
&& next_offset % group->file_size == LOG_FILE_HDR_SIZE) { && next_offset % log_sys.log.file_size == LOG_FILE_HDR_SIZE) {
/* We start to write a new log file instance in the group */ /* We start to write a new log file instance in the group */
ut_a(next_offset / group->file_size <= ULINT_MAX); ut_a(next_offset / log_sys.log.file_size <= ULINT_MAX);
log_group_file_header_flush(group, (ulint) log_file_header_flush(
(next_offset / group->file_size), ulint(next_offset / log_sys.log.file_size), start_lsn);
start_lsn);
srv_stats.os_log_written.add(OS_FILE_LOG_BLOCK_SIZE); srv_stats.os_log_written.add(OS_FILE_LOG_BLOCK_SIZE);
srv_stats.log_writes.inc(); srv_stats.log_writes.inc();
} }
if ((next_offset % group->file_size) + len > group->file_size) { if ((next_offset % log_sys.log.file_size) + len
> log_sys.log.file_size) {
/* if the above condition holds, then the below expression /* if the above condition holds, then the below expression
is < len which is ulint, so the typecast is ok */ is < len which is ulint, so the typecast is ok */
write_len = (ulint) write_len = ulint(log_sys.log.file_size
(group->file_size - (next_offset % group->file_size)); - (next_offset % log_sys.log.file_size));
} else { } else {
write_len = len; write_len = len;
} }
...@@ -1012,8 +851,7 @@ log_group_write_buf( ...@@ -1012,8 +851,7 @@ log_group_write_buf(
fil_io(IORequestLogWrite, true, fil_io(IORequestLogWrite, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
univ_page_size, univ_page_size,
ulint(next_offset & (srv_page_size - 1)), write_len, buf, ulint(next_offset & (srv_page_size - 1)), write_len, buf, NULL);
group);
srv_stats.os_log_pending_writes.dec(); srv_stats.os_log_pending_writes.dec();
...@@ -1227,7 +1065,7 @@ log_write_up_to( ...@@ -1227,7 +1065,7 @@ log_write_up_to(
log_buffer_switch(); log_buffer_switch();
log_group_set_fields(&log_sys.log, log_sys.write_lsn); log_sys.log.set_fields(log_sys.write_lsn);
log_mutex_exit(); log_mutex_exit();
/* Erase the end of the last log block. */ /* Erase the end of the last log block. */
...@@ -1236,12 +1074,9 @@ log_write_up_to( ...@@ -1236,12 +1074,9 @@ log_write_up_to(
/* Calculate pad_size if needed. */ /* Calculate pad_size if needed. */
pad_size = 0; pad_size = 0;
if (write_ahead_size > OS_FILE_LOG_BLOCK_SIZE) { if (write_ahead_size > OS_FILE_LOG_BLOCK_SIZE) {
lsn_t end_offset;
ulint end_offset_in_unit; ulint end_offset_in_unit;
end_offset = log_group_calc_lsn_offset( lsn_t end_offset = log_sys.log.calc_lsn_offset(
ut_uint64_align_up(write_lsn, ut_uint64_align_up(write_lsn, OS_FILE_LOG_BLOCK_SIZE));
OS_FILE_LOG_BLOCK_SIZE),
&log_sys.log);
end_offset_in_unit = (ulint) (end_offset % write_ahead_size); end_offset_in_unit = (ulint) (end_offset % write_ahead_size);
if (end_offset_in_unit > 0 if (end_offset_in_unit > 0
...@@ -1262,9 +1097,8 @@ log_write_up_to( ...@@ -1262,9 +1097,8 @@ log_write_up_to(
} }
/* Do the write to the log files */ /* Do the write to the log files */
log_group_write_buf( log_write_buf(
&log_sys.log, write_buf + area_start, write_buf + area_start, area_end - area_start + pad_size,
area_end - area_start + pad_size,
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
pad_size, pad_size,
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
...@@ -1444,20 +1278,17 @@ log_complete_checkpoint(void) ...@@ -1444,20 +1278,17 @@ log_complete_checkpoint(void)
rw_lock_x_unlock_gen(&(log_sys.checkpoint_lock), LOG_CHECKPOINT); rw_lock_x_unlock_gen(&(log_sys.checkpoint_lock), LOG_CHECKPOINT);
} }
/******************************************************//** /** Complete an asynchronous checkpoint write. */
Completes an asynchronous checkpoint info write i/o to a log file. */ void log_t::complete_checkpoint()
static
void
log_io_complete_checkpoint(void)
/*============================*/
{ {
ut_ad(this == &log_sys);
MONITOR_DEC(MONITOR_PENDING_CHECKPOINT_WRITE); MONITOR_DEC(MONITOR_PENDING_CHECKPOINT_WRITE);
log_mutex_enter(); log_mutex_enter();
ut_ad(log_sys.n_pending_checkpoint_writes > 0); ut_ad(n_pending_checkpoint_writes > 0);
if (--log_sys.n_pending_checkpoint_writes == 0) { if (!--n_pending_checkpoint_writes) {
log_complete_checkpoint(); log_complete_checkpoint();
} }
...@@ -1471,7 +1302,6 @@ void ...@@ -1471,7 +1302,6 @@ void
log_group_checkpoint(lsn_t end_lsn) log_group_checkpoint(lsn_t end_lsn)
{ {
lsn_t lsn_offset; lsn_t lsn_offset;
byte* buf;
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(log_mutex_own()); ut_ad(log_mutex_own());
...@@ -1485,9 +1315,7 @@ log_group_checkpoint(lsn_t end_lsn) ...@@ -1485,9 +1315,7 @@ log_group_checkpoint(lsn_t end_lsn)
log_sys.next_checkpoint_no, log_sys.next_checkpoint_no,
log_sys.next_checkpoint_lsn)); log_sys.next_checkpoint_lsn));
log_group_t* group = &log_sys.log; byte* buf = log_sys.checkpoint_buf;
buf = group->checkpoint_buf;
memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE); memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE);
mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys.next_checkpoint_no); mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys.next_checkpoint_no);
...@@ -1497,8 +1325,7 @@ log_group_checkpoint(lsn_t end_lsn) ...@@ -1497,8 +1325,7 @@ log_group_checkpoint(lsn_t end_lsn)
log_crypt_write_checkpoint_buf(buf); log_crypt_write_checkpoint_buf(buf);
} }
lsn_offset = log_group_calc_lsn_offset(log_sys.next_checkpoint_lsn, lsn_offset = log_sys.log.calc_lsn_offset(log_sys.next_checkpoint_lsn);
group);
mach_write_to_8(buf + LOG_CHECKPOINT_OFFSET, lsn_offset); mach_write_to_8(buf + LOG_CHECKPOINT_OFFSET, lsn_offset);
mach_write_to_8(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, mach_write_to_8(buf + LOG_CHECKPOINT_LOG_BUF_SIZE,
srv_log_buffer_size); srv_log_buffer_size);
...@@ -1523,28 +1350,18 @@ log_group_checkpoint(lsn_t end_lsn) ...@@ -1523,28 +1350,18 @@ log_group_checkpoint(lsn_t end_lsn)
/* Note: We alternate the physical place of the checkpoint info. /* Note: We alternate the physical place of the checkpoint info.
See the (next_checkpoint_no & 1) below. */ See the (next_checkpoint_no & 1) below. */
/* We send as the last parameter the group machine address
added with 1, as we want to distinguish between a normal log
file write and a checkpoint field write */
fil_io(IORequestLogWrite, false, fil_io(IORequestLogWrite, false,
page_id_t(SRV_LOG_SPACE_FIRST_ID, 0), page_id_t(SRV_LOG_SPACE_FIRST_ID, 0),
univ_page_size, univ_page_size,
(log_sys.next_checkpoint_no & 1) (log_sys.next_checkpoint_no & 1)
? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1, ? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1,
OS_FILE_LOG_BLOCK_SIZE, OS_FILE_LOG_BLOCK_SIZE,
buf, (byte*) group + 1); buf, reinterpret_cast<void*>(1) /* checkpoint write */);
ut_ad(((ulint) group & 0x1UL) == 0);
} }
/** Read a log group header page to log_sys.checkpoint_buf. /** Read a log group header page to log_sys.checkpoint_buf.
@param[in] group log group @param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 */
@param[in] header 0 or LOG_CHEKCPOINT_1 or LOG_CHECKPOINT2 */ void log_header_read(ulint header)
void
log_group_header_read(
const log_group_t* group,
ulint header)
{ {
ut_ad(log_mutex_own()); ut_ad(log_mutex_own());
...@@ -2212,43 +2029,13 @@ log_refresh_stats(void) ...@@ -2212,43 +2029,13 @@ log_refresh_stats(void)
log_sys.last_printout_time = time(NULL); log_sys.last_printout_time = time(NULL);
} }
/** Close a log group.
@param[in,out] group log group to close */
static
void
log_group_close(log_group_t* group)
{
ulint i;
for (i = 0; i < group->n_files; i++) {
ut_free(group->file_header_bufs_ptr[i]);
}
ut_free(group->file_header_bufs_ptr);
ut_free(group->file_header_bufs);
ut_free(group->checkpoint_buf_ptr);
group->n_files = 0;
group->file_header_bufs_ptr = NULL;
group->file_header_bufs = NULL;
group->checkpoint_buf_ptr = NULL;
}
/********************************************************//**
Closes all log groups. */
void
log_group_close_all(void)
/*=====================*/
{
log_group_close(&log_sys.log);
}
/** Shut down the redo log subsystem. */ /** Shut down the redo log subsystem. */
void log_t::close() void log_t::close()
{ {
ut_ad(this == &log_sys); ut_ad(this == &log_sys);
if (!is_initialised()) return; if (!is_initialised()) return;
m_initialised = false; m_initialised = false;
log_group_close_all(); log.close();
if (!first_in_use) if (!first_in_use)
buf -= srv_log_buffer_size; buf -= srv_log_buffer_size;
......
...@@ -631,42 +631,32 @@ recv_sys_debug_free(void) ...@@ -631,42 +631,32 @@ recv_sys_debug_free(void)
mutex_exit(&(recv_sys->mutex)); mutex_exit(&(recv_sys->mutex));
} }
/** Read a log segment to a buffer. /** Read a log segment to log_sys.buf.
@param[out] buf buffer @param[in,out] start_lsn in: read area start,
@param[in] group redo log files out: the last read valid lsn
@param[in, out] start_lsn in : read area start, out: the last read valid lsn
@param[in] end_lsn read area end @param[in] end_lsn read area end
@param[out] invalid_block - invalid, (maybe incompletely written) block encountered @return whether no invalid blocks (e.g checksum mismatch) were found */
@return false, if invalid block encountered (e.g checksum mismatch), true otherwise */ bool log_t::files::read_log_seg(lsn_t* start_lsn, lsn_t end_lsn)
bool
log_group_read_log_seg(
byte* buf,
const log_group_t* group,
lsn_t *start_lsn,
lsn_t end_lsn)
{ {
ulint len; ulint len;
lsn_t source_offset;
bool success = true; bool success = true;
ut_ad(log_mutex_own()); ut_ad(log_sys.mutex.is_owned());
ut_ad(!(*start_lsn % OS_FILE_LOG_BLOCK_SIZE)); ut_ad(!(*start_lsn % OS_FILE_LOG_BLOCK_SIZE));
ut_ad(!(end_lsn % OS_FILE_LOG_BLOCK_SIZE)); ut_ad(!(end_lsn % OS_FILE_LOG_BLOCK_SIZE));
byte* buf = log_sys.buf;
loop: loop:
source_offset = log_group_calc_lsn_offset(*start_lsn, group); lsn_t source_offset = calc_lsn_offset(*start_lsn);
ut_a(end_lsn - *start_lsn <= ULINT_MAX); ut_a(end_lsn - *start_lsn <= ULINT_MAX);
len = (ulint) (end_lsn - *start_lsn); len = (ulint) (end_lsn - *start_lsn);
ut_ad(len != 0); ut_ad(len != 0);
const bool at_eof = (source_offset % group->file_size) + len const bool at_eof = (source_offset % file_size) + len > file_size;
> group->file_size;
if (at_eof) { if (at_eof) {
/* If the above condition is true then len (which is ulint) /* If the above condition is true then len (which is ulint)
is > the expression below, so the typecast is ok */ is > the expression below, so the typecast is ok */
len = (ulint) (group->file_size - len = ulint(file_size - (source_offset % file_size));
(source_offset % group->file_size));
} }
log_sys.n_log_ios++; log_sys.n_log_ios++;
...@@ -698,7 +688,7 @@ log_group_read_log_seg( ...@@ -698,7 +688,7 @@ log_group_read_log_seg(
break; break;
} }
if (innodb_log_checksums || group->is_encrypted()) { if (innodb_log_checksums || is_encrypted()) {
ulint crc = log_block_calc_checksum_crc32(buf); ulint crc = log_block_calc_checksum_crc32(buf);
ulint cksum = log_block_get_checksum(buf); ulint cksum = log_block_get_checksum(buf);
...@@ -721,7 +711,7 @@ log_group_read_log_seg( ...@@ -721,7 +711,7 @@ log_group_read_log_seg(
break; break;
} }
if (group->is_encrypted()) { if (is_encrypted()) {
log_crypt(buf, *start_lsn, log_crypt(buf, *start_lsn,
OS_FILE_LOG_BLOCK_SIZE, true); OS_FILE_LOG_BLOCK_SIZE, true);
} }
...@@ -759,14 +749,10 @@ recv_synchronize_groups() ...@@ -759,14 +749,10 @@ recv_synchronize_groups()
the block is always incomplete */ the block is always incomplete */
lsn_t start_lsn = ut_uint64_align_down(recovered_lsn, lsn_t start_lsn = ut_uint64_align_down(recovered_lsn,
OS_FILE_LOG_BLOCK_SIZE); OS_FILE_LOG_BLOCK_SIZE);
log_group_read_log_seg(log_sys.buf, &log_sys.log, log_sys.log.read_log_seg(&start_lsn,
&start_lsn, start_lsn + OS_FILE_LOG_BLOCK_SIZE); start_lsn + OS_FILE_LOG_BLOCK_SIZE);
log_sys.log.set_fields(recovered_lsn);
/* Update the fields in the group struct to correspond to
recovered_lsn */
log_group_set_fields(&log_sys.log, recovered_lsn);
/* Copy the checkpoint info to the log; remember that we have /* Copy the checkpoint info to the log; remember that we have
incremented checkpoint_no by one, and the info will not be written incremented checkpoint_no by one, and the info will not be written
...@@ -792,19 +778,17 @@ recv_check_log_header_checksum( ...@@ -792,19 +778,17 @@ recv_check_log_header_checksum(
} }
/** Find the latest checkpoint in the format-0 log header. /** Find the latest checkpoint in the format-0 log header.
@param[out] max_group log group, or NULL
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 @param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@return error code or DB_SUCCESS */ @return error code or DB_SUCCESS */
static MY_ATTRIBUTE((warn_unused_result)) static MY_ATTRIBUTE((warn_unused_result))
dberr_t dberr_t
recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) recv_find_max_checkpoint_0(ulint* max_field)
{ {
log_group_t* group = &log_sys.log;
ib_uint64_t max_no = 0; ib_uint64_t max_no = 0;
ib_uint64_t checkpoint_no; ib_uint64_t checkpoint_no;
byte* buf = log_sys.checkpoint_buf; byte* buf = log_sys.checkpoint_buf;
ut_ad(group->format == 0); ut_ad(log_sys.log.format == 0);
/** Offset of the first checkpoint checksum */ /** Offset of the first checkpoint checksum */
static const uint CHECKSUM_1 = 288; static const uint CHECKSUM_1 = 288;
...@@ -815,11 +799,11 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) ...@@ -815,11 +799,11 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field)
/** Least significant bits of the checkpoint offset */ /** Least significant bits of the checkpoint offset */
static const uint OFFSET_LOW32 = 16; static const uint OFFSET_LOW32 = 16;
*max_group = NULL; bool found = false;
for (ulint field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; for (ulint field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
log_group_header_read(group, field); log_header_read(field);
if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1)) if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1))
!= mach_read_from_4(buf + CHECKSUM_1) != mach_read_from_4(buf + CHECKSUM_1)
...@@ -846,21 +830,21 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) ...@@ -846,21 +830,21 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field)
mach_read_from_8(buf + LOG_CHECKPOINT_LSN))); mach_read_from_8(buf + LOG_CHECKPOINT_LSN)));
if (checkpoint_no >= max_no) { if (checkpoint_no >= max_no) {
*max_group = group; found = true;
*max_field = field; *max_field = field;
max_no = checkpoint_no; max_no = checkpoint_no;
group->state = LOG_GROUP_OK; log_sys.log.state = LOG_GROUP_OK;
group->lsn = mach_read_from_8( log_sys.log.lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN); buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = static_cast<ib_uint64_t>( log_sys.log.lsn_offset = static_cast<ib_uint64_t>(
mach_read_from_4(buf + OFFSET_HIGH32)) << 32 mach_read_from_4(buf + OFFSET_HIGH32)) << 32
| mach_read_from_4(buf + OFFSET_LOW32); | mach_read_from_4(buf + OFFSET_LOW32);
} }
} }
if (*max_group != NULL) { if (found) {
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -882,9 +866,7 @@ dberr_t ...@@ -882,9 +866,7 @@ dberr_t
recv_log_format_0_recover(lsn_t lsn) recv_log_format_0_recover(lsn_t lsn)
{ {
log_mutex_enter(); log_mutex_enter();
log_group_t* group = &log_sys.log; const lsn_t source_offset = log_sys.log.calc_lsn_offset(lsn);
const lsn_t source_offset
= log_group_calc_lsn_offset(lsn, group);
log_mutex_exit(); log_mutex_exit();
const ulint page_no = ulint(source_offset >> srv_page_size_shift); const ulint page_no = ulint(source_offset >> srv_page_size_shift);
byte* buf = log_sys.buf; byte* buf = log_sys.buf;
...@@ -933,26 +915,23 @@ recv_log_format_0_recover(lsn_t lsn) ...@@ -933,26 +915,23 @@ recv_log_format_0_recover(lsn_t lsn)
dberr_t dberr_t
recv_find_max_checkpoint(ulint* max_field) recv_find_max_checkpoint(ulint* max_field)
{ {
log_group_t* group;
ib_uint64_t max_no; ib_uint64_t max_no;
ib_uint64_t checkpoint_no; ib_uint64_t checkpoint_no;
ulint field; ulint field;
byte* buf; byte* buf;
group = &log_sys.log;
max_no = 0; max_no = 0;
*max_field = 0; *max_field = 0;
buf = log_sys.checkpoint_buf; buf = log_sys.checkpoint_buf;
group->state = LOG_GROUP_CORRUPTED; log_sys.log.state = LOG_GROUP_CORRUPTED;
log_group_header_read(group, 0); log_header_read(0);
/* Check the header page checksum. There was no /* Check the header page checksum. There was no
checksum in the first redo log format (version 0). */ checksum in the first redo log format (version 0). */
group->format = mach_read_from_4(buf + LOG_HEADER_FORMAT); log_sys.log.format = mach_read_from_4(buf + LOG_HEADER_FORMAT);
if (group->format != LOG_HEADER_FORMAT_3_23 if (log_sys.log.format != LOG_HEADER_FORMAT_3_23
&& !recv_check_log_header_checksum(buf)) { && !recv_check_log_header_checksum(buf)) {
ib::error() << "Invalid redo log header checksum."; ib::error() << "Invalid redo log header checksum.";
return(DB_CORRUPTION); return(DB_CORRUPTION);
...@@ -964,9 +943,9 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -964,9 +943,9 @@ recv_find_max_checkpoint(ulint* max_field)
/* Ensure that the string is NUL-terminated. */ /* Ensure that the string is NUL-terminated. */
creator[LOG_HEADER_CREATOR_END - LOG_HEADER_CREATOR] = 0; creator[LOG_HEADER_CREATOR_END - LOG_HEADER_CREATOR] = 0;
switch (group->format) { switch (log_sys.log.format) {
case LOG_HEADER_FORMAT_3_23: case LOG_HEADER_FORMAT_3_23:
return(recv_find_max_checkpoint_0(&group, max_field)); return(recv_find_max_checkpoint_0(max_field));
case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2:
case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED:
case LOG_HEADER_FORMAT_CURRENT: case LOG_HEADER_FORMAT_CURRENT:
...@@ -981,7 +960,7 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -981,7 +960,7 @@ recv_find_max_checkpoint(ulint* max_field)
for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
log_group_header_read(group, field); log_header_read(field);
const ulint crc32 = log_block_calc_checksum_crc32(buf); const ulint crc32 = log_block_calc_checksum_crc32(buf);
const ulint cksum = log_block_get_checksum(buf); const ulint cksum = log_block_get_checksum(buf);
...@@ -996,7 +975,7 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -996,7 +975,7 @@ recv_find_max_checkpoint(ulint* max_field)
continue; continue;
} }
if (group->is_encrypted() if (log_sys.is_encrypted()
&& !log_crypt_read_checkpoint_buf(buf)) { && !log_crypt_read_checkpoint_buf(buf)) {
ib::error() << "Reading checkpoint" ib::error() << "Reading checkpoint"
" encryption info failed."; " encryption info failed.";
...@@ -1014,10 +993,10 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -1014,10 +993,10 @@ recv_find_max_checkpoint(ulint* max_field)
if (checkpoint_no >= max_no) { if (checkpoint_no >= max_no) {
*max_field = field; *max_field = field;
max_no = checkpoint_no; max_no = checkpoint_no;
group->state = LOG_GROUP_OK; log_sys.log.state = LOG_GROUP_OK;
group->lsn = mach_read_from_8( log_sys.log.lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_LSN); buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = mach_read_from_8( log_sys.log.lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET); buf + LOG_CHECKPOINT_OFFSET);
log_sys.next_checkpoint_no = checkpoint_no; log_sys.next_checkpoint_no = checkpoint_no;
} }
...@@ -2867,7 +2846,6 @@ recv_scan_log_recs( ...@@ -2867,7 +2846,6 @@ recv_scan_log_recs(
/** Scans log from a buffer and stores new log data to the parsing buffer. /** Scans log from a buffer and stores new log data to the parsing buffer.
Parses and hashes the log records if new data found. Parses and hashes the log records if new data found.
@param[in,out] group log group
@param[in] checkpoint_lsn latest checkpoint log sequence number @param[in] checkpoint_lsn latest checkpoint log sequence number
@param[in,out] contiguous_lsn log sequence number @param[in,out] contiguous_lsn log sequence number
until which all redo log has been scanned until which all redo log has been scanned
...@@ -2877,7 +2855,6 @@ can be applied to the tablespaces ...@@ -2877,7 +2855,6 @@ can be applied to the tablespaces
static static
bool bool
recv_group_scan_log_recs( recv_group_scan_log_recs(
log_group_t* group,
lsn_t checkpoint_lsn, lsn_t checkpoint_lsn,
lsn_t* contiguous_lsn, lsn_t* contiguous_lsn,
bool last_phase) bool last_phase)
...@@ -2910,8 +2887,8 @@ recv_group_scan_log_recs( ...@@ -2910,8 +2887,8 @@ recv_group_scan_log_recs(
* (buf_pool_get_n_pages() * (buf_pool_get_n_pages()
- (recv_n_pool_free_frames * srv_buf_pool_instances)); - (recv_n_pool_free_frames * srv_buf_pool_instances));
group->scanned_lsn = end_lsn = *contiguous_lsn = ut_uint64_align_down( log_sys.log.scanned_lsn = end_lsn = *contiguous_lsn =
*contiguous_lsn, OS_FILE_LOG_BLOCK_SIZE); ut_uint64_align_down(*contiguous_lsn, OS_FILE_LOG_BLOCK_SIZE);
do { do {
if (last_phase && store_to_hash == STORE_NO) { if (last_phase && store_to_hash == STORE_NO) {
...@@ -2926,15 +2903,13 @@ recv_group_scan_log_recs( ...@@ -2926,15 +2903,13 @@ recv_group_scan_log_recs(
start_lsn = ut_uint64_align_down(end_lsn, start_lsn = ut_uint64_align_down(end_lsn,
OS_FILE_LOG_BLOCK_SIZE); OS_FILE_LOG_BLOCK_SIZE);
end_lsn = start_lsn; end_lsn = start_lsn;
log_group_read_log_seg( log_sys.log.read_log_seg(&end_lsn, start_lsn + RECV_SCAN_SIZE);
log_sys.buf, group, &end_lsn,
start_lsn + RECV_SCAN_SIZE);
} while (end_lsn != start_lsn } while (end_lsn != start_lsn
&& !recv_scan_log_recs( && !recv_scan_log_recs(
available_mem, &store_to_hash, log_sys.buf, available_mem, &store_to_hash, log_sys.buf,
checkpoint_lsn, checkpoint_lsn,
start_lsn, end_lsn, start_lsn, end_lsn,
contiguous_lsn, &group->scanned_lsn)); contiguous_lsn, &log_sys.log.scanned_lsn));
if (recv_sys->found_corrupt_log || recv_sys->found_corrupt_fs) { if (recv_sys->found_corrupt_log || recv_sys->found_corrupt_fs) {
DBUG_RETURN(false); DBUG_RETURN(false);
...@@ -2942,7 +2917,7 @@ recv_group_scan_log_recs( ...@@ -2942,7 +2917,7 @@ recv_group_scan_log_recs(
DBUG_PRINT("ib_log", ("%s " LSN_PF " completed", DBUG_PRINT("ib_log", ("%s " LSN_PF " completed",
last_phase ? "rescan" : "scan", last_phase ? "rescan" : "scan",
group->scanned_lsn)); log_sys.log.scanned_lsn));
DBUG_RETURN(store_to_hash == STORE_NO); DBUG_RETURN(store_to_hash == STORE_NO);
} }
...@@ -3123,7 +3098,6 @@ of first system tablespace page ...@@ -3123,7 +3098,6 @@ of first system tablespace page
dberr_t dberr_t
recv_recovery_from_checkpoint_start(lsn_t flush_lsn) recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
{ {
log_group_t* group;
ulint max_cp_field; ulint max_cp_field;
lsn_t checkpoint_lsn; lsn_t checkpoint_lsn;
bool rescan; bool rescan;
...@@ -3151,8 +3125,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3151,8 +3125,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
log_mutex_enter(); log_mutex_enter();
/* Look for the latest checkpoint from any of the log groups */
err = recv_find_max_checkpoint(&max_cp_field); err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -3162,28 +3134,26 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3162,28 +3134,26 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
return(err); return(err);
} }
log_group_header_read(&log_sys.log, max_cp_field); log_header_read(max_cp_field);
buf = log_sys.checkpoint_buf; buf = log_sys.checkpoint_buf;
checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
/* Start reading the log groups from the checkpoint lsn up. The /* Start reading the log from the checkpoint lsn. The variable
variable contiguous_lsn contains an lsn up to which the log is contiguous_lsn contains an lsn up to which the log is known to
known to be contiguously written to all log groups. */ be contiguously written. */
recv_sys->mlog_checkpoint_lsn = 0; recv_sys->mlog_checkpoint_lsn = 0;
ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size); ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size);
group = &log_sys.log;
const lsn_t end_lsn = mach_read_from_8( const lsn_t end_lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_END_LSN); buf + LOG_CHECKPOINT_END_LSN);
ut_ad(recv_sys->n_addrs == 0); ut_ad(recv_sys->n_addrs == 0);
contiguous_lsn = checkpoint_lsn; contiguous_lsn = checkpoint_lsn;
switch (group->format) { switch (log_sys.log.format) {
case 0: case 0:
log_mutex_exit(); log_mutex_exit();
return(recv_log_format_0_recover(checkpoint_lsn)); return(recv_log_format_0_recover(checkpoint_lsn));
...@@ -3201,8 +3171,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3201,8 +3171,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
} }
/* Look for MLOG_CHECKPOINT. */ /* Look for MLOG_CHECKPOINT. */
recv_group_scan_log_recs(group, checkpoint_lsn, &contiguous_lsn, recv_group_scan_log_recs(checkpoint_lsn, &contiguous_lsn, false);
false);
/* The first scan should not have stored or applied any records. */ /* The first scan should not have stored or applied any records. */
ut_ad(recv_sys->n_addrs == 0); ut_ad(recv_sys->n_addrs == 0);
ut_ad(!recv_sys->found_corrupt_fs); ut_ad(!recv_sys->found_corrupt_fs);
...@@ -3219,7 +3188,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3219,7 +3188,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
} }
if (recv_sys->mlog_checkpoint_lsn == 0) { if (recv_sys->mlog_checkpoint_lsn == 0) {
lsn_t scan_lsn = group->scanned_lsn; lsn_t scan_lsn = log_sys.log.scanned_lsn;
if (!srv_read_only_mode && scan_lsn != checkpoint_lsn) { if (!srv_read_only_mode && scan_lsn != checkpoint_lsn) {
log_mutex_exit(); log_mutex_exit();
ib::error err; ib::error err;
...@@ -3232,12 +3201,12 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3232,12 +3201,12 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
return(DB_ERROR); return(DB_ERROR);
} }
group->scanned_lsn = checkpoint_lsn; log_sys.log.scanned_lsn = checkpoint_lsn;
rescan = false; rescan = false;
} else { } else {
contiguous_lsn = checkpoint_lsn; contiguous_lsn = checkpoint_lsn;
rescan = recv_group_scan_log_recs( rescan = recv_group_scan_log_recs(
group, checkpoint_lsn, &contiguous_lsn, false); checkpoint_lsn, &contiguous_lsn, false);
if ((recv_sys->found_corrupt_log && !srv_force_recovery) if ((recv_sys->found_corrupt_log && !srv_force_recovery)
|| recv_sys->found_corrupt_fs) { || recv_sys->found_corrupt_fs) {
...@@ -3308,8 +3277,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3308,8 +3277,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
lsn_t recent_stored_lsn = recv_sys->last_stored_lsn; lsn_t recent_stored_lsn = recv_sys->last_stored_lsn;
rescan = recv_group_scan_log_recs( rescan = recv_group_scan_log_recs(
group, checkpoint_lsn, checkpoint_lsn, &recent_stored_lsn, false);
&recent_stored_lsn, false);
ut_ad(!recv_sys->found_corrupt_fs); ut_ad(!recv_sys->found_corrupt_fs);
...@@ -3340,8 +3308,8 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3340,8 +3308,8 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
if (rescan) { if (rescan) {
contiguous_lsn = checkpoint_lsn; contiguous_lsn = checkpoint_lsn;
recv_group_scan_log_recs(group, checkpoint_lsn, recv_group_scan_log_recs(
&contiguous_lsn, true); checkpoint_lsn, &contiguous_lsn, true);
if ((recv_sys->found_corrupt_log if ((recv_sys->found_corrupt_log
&& !srv_force_recovery) && !srv_force_recovery)
...@@ -3354,12 +3322,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3354,12 +3322,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
ut_ad(!rescan || recv_sys->n_addrs == 0); ut_ad(!rescan || recv_sys->n_addrs == 0);
} }
/* We currently have only one log group */ if (log_sys.log.scanned_lsn < checkpoint_lsn
|| log_sys.log.scanned_lsn < recv_max_page_lsn) {
if (group->scanned_lsn < checkpoint_lsn ib::error() << "We scanned the log up to "
|| group->scanned_lsn < recv_max_page_lsn) { << log_sys.log.scanned_lsn
ib::error() << "We scanned the log up to " << group->scanned_lsn
<< ". A checkpoint was at " << checkpoint_lsn << " and" << ". A checkpoint was at " << checkpoint_lsn << " and"
" the maximum LSN on a database page was " " the maximum LSN on a database page was "
<< recv_max_page_lsn << ". It is possible that the" << recv_max_page_lsn << ". It is possible that the"
...@@ -3375,9 +3342,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ...@@ -3375,9 +3342,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
return(DB_ERROR); return(DB_ERROR);
} }
/* Synchronize the uncorrupted log groups to the most up-to-date log
group; we also copy checkpoint info to groups */
log_sys.next_checkpoint_lsn = checkpoint_lsn; log_sys.next_checkpoint_lsn = checkpoint_lsn;
log_sys.next_checkpoint_no = checkpoint_no + 1; log_sys.next_checkpoint_no = checkpoint_no + 1;
......
...@@ -487,7 +487,7 @@ create_log_files( ...@@ -487,7 +487,7 @@ create_log_files(
} }
} }
log_init(srv_n_log_files); log_sys.log.create(srv_n_log_files);
if (!log_set_capacity(srv_log_file_size_requested)) { if (!log_set_capacity(srv_log_file_size_requested)) {
return(DB_ERROR); return(DB_ERROR);
} }
...@@ -1926,7 +1926,7 @@ dberr_t srv_start(bool create_new_db) ...@@ -1926,7 +1926,7 @@ dberr_t srv_start(bool create_new_db)
} }
} }
log_init(srv_n_log_files_found); log_sys.log.create(srv_n_log_files_found);
if (!log_set_capacity(srv_log_file_size_requested)) { if (!log_set_capacity(srv_log_file_size_requested)) {
return(srv_init_abort(DB_ERROR)); return(srv_init_abort(DB_ERROR));
...@@ -2176,7 +2176,6 @@ dberr_t srv_start(bool create_new_db) ...@@ -2176,7 +2176,6 @@ dberr_t srv_start(bool create_new_db)
err = fil_write_flushed_lsn(log_get_lsn()); err = fil_write_flushed_lsn(log_get_lsn());
ut_ad(!buf_pool_check_no_pending_io()); ut_ad(!buf_pool_check_no_pending_io());
fil_close_log_files(true); fil_close_log_files(true);
log_group_close_all();
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
bool trunc = srv_operation bool trunc = srv_operation
== SRV_OPERATION_RESTORE; == SRV_OPERATION_RESTORE;
...@@ -2244,9 +2243,6 @@ dberr_t srv_start(bool create_new_db) ...@@ -2244,9 +2243,6 @@ dberr_t srv_start(bool create_new_db)
return(srv_init_abort(DB_ERROR));); return(srv_init_abort(DB_ERROR)););
DBUG_PRINT("ib_log", ("After innodb_log_abort_5")); DBUG_PRINT("ib_log", ("After innodb_log_abort_5"));
/* Free the old log file space. */
log_group_close_all();
ib::info() << "Starting to delete and rewrite log" ib::info() << "Starting to delete and rewrite log"
" files."; " files.";
......
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