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)
lsn_t lsn= start_lsn;
for(int retries= 0; retries < 100; retries++) {
if (log_group_read_log_seg(log_sys.buf, &log_sys.log,
&lsn, end_lsn)){
if (log_sys.log.read_log_seg(&lsn, end_lsn)) {
break;
}
msg("Retrying read of a redo log block");
......@@ -3819,7 +3818,7 @@ xtrabackup_backup_func()
SRV_MAX_N_PENDING_SYNC_IOS);
log_sys.create();
log_init(srv_n_log_files);
log_sys.log.create(srv_n_log_files);
fil_space_t* space = fil_space_create(
"innodb_redo_log", SRV_LOG_SPACE_FIRST_ID, 0,
FIL_TYPE_LOG, NULL);
......@@ -3924,7 +3923,7 @@ xtrabackup_backup_func()
ut_ad(!((log_sys.log.format ^ LOG_HEADER_FORMAT_CURRENT)
& ~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)) {
goto reread_log_header;
......
......@@ -2007,6 +2007,10 @@ fil_close_log_files(
}
mutex_exit(&fil_system.mutex);
if (free) {
log_sys.log.close();
}
}
/*******************************************************************//**
......@@ -4685,7 +4689,26 @@ fil_aio_wait(
switch (purpose) {
case FIL_TYPE_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;
case FIL_TYPE_TABLESPACE:
case FIL_TYPE_TEMPORARY:
......
......@@ -41,8 +41,8 @@ Created 12/9/1995 Heikki Tuuri
#include "os0event.h"
#include "os0file.h"
/** Redo log group */
struct log_group_t;
/** Maximum number of srv_n_log_files, or innodb_log_files_in_group */
#define SRV_N_LOG_FILES_MAX 100
/** Magic value to use instead of log checksums when they are disabled */
#define LOG_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
......@@ -151,10 +151,6 @@ lsn_t
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
and lsn - buf_get_oldest_modification().
@param[in] file_size requested innodb_log_file_size
......@@ -166,12 +162,6 @@ log_set_capacity(ulonglong file_size)
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
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
......@@ -231,12 +221,8 @@ void
logs_empty_and_mark_files_at_shutdown(void);
/*=======================================*/
/** Read a log group header page to log_sys.checkpoint_buf.
@param[in] group log group
@param[in] header 0 or LOG_CHEKCPOINT_1 or LOG_CHECKPOINT2 */
void
log_group_header_read(
const log_group_t* group,
ulint header);
@param[in] header 0 or LOG_CHECKPOINT_1 or LOG_CHECKPOINT2 */
void log_header_read(ulint header);
/** 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] end_lsn start LSN of the MLOG_CHECKPOINT mini-transaction */
......@@ -257,16 +243,6 @@ objects! */
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.
@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. */
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 */
extern my_bool innodb_log_checksums;
......@@ -536,50 +507,6 @@ enum log_group_state_t {
typedef ib_mutex_t LogSysMutex;
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 */
struct log_t{
MY_ALIGNED(CACHE_LINE_SIZE)
......@@ -590,8 +517,7 @@ struct log_t{
MY_ALIGNED(CACHE_LINE_SIZE)
LogSysMutex mutex; /*!< mutex protecting the log */
MY_ALIGNED(CACHE_LINE_SIZE)
LogSysMutex write_mutex; /*!< mutex protecting writing to log
file and accessing to log_group_t */
LogSysMutex write_mutex; /*!< mutex protecting writing to log */
MY_ALIGNED(CACHE_LINE_SIZE)
FlushOrderMutex log_flush_order_mutex;/*!< mutex to serialize access to
the flush list when we are putting
......@@ -626,8 +552,67 @@ struct log_t{
max_checkpoint_age; this flag is
peeked at by log_free_check(), which
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 @{ */
......@@ -730,6 +715,9 @@ struct log_t{
bool is_initialised() { return m_initialised; }
/** Complete an asynchronous checkpoint write. */
void complete_checkpoint();
/** Initialise the redo log subsystem. */
void create();
......@@ -740,6 +728,27 @@ struct log_t{
/** Redo log system */
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. */
#define log_flush_order_mutex_own() \
mutex_own(&log_sys.log_flush_order_mutex)
......@@ -783,15 +792,6 @@ extern log_t log_sys;
mutex_exit(&log_sys.write_mutex); \
} 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 */
extern ulonglong innodb_scrub_log_speed;
......
/*****************************************************************************
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
the terms of the GNU General Public License as published by the Free Software
......@@ -96,20 +96,6 @@ 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. */
void
......
......@@ -339,8 +339,6 @@ extern const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
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;
/** The InnoDB redo log file size, or 0 when changing the redo log format
at startup (while disallowing writes to the redo log). */
......
This diff is collapsed.
This diff is collapsed.
......@@ -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)) {
return(DB_ERROR);
}
......@@ -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)) {
return(srv_init_abort(DB_ERROR));
......@@ -2176,7 +2176,6 @@ dberr_t srv_start(bool create_new_db)
err = fil_write_flushed_lsn(log_get_lsn());
ut_ad(!buf_pool_check_no_pending_io());
fil_close_log_files(true);
log_group_close_all();
if (err == DB_SUCCESS) {
bool trunc = srv_operation
== SRV_OPERATION_RESTORE;
......@@ -2244,9 +2243,6 @@ dberr_t srv_start(bool create_new_db)
return(srv_init_abort(DB_ERROR)););
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"
" 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