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). */
......
This diff is collapsed.
This diff is collapsed.
...@@ -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