diff options
Diffstat (limited to 'innobase/include/log0log.ic')
-rw-r--r-- | innobase/include/log0log.ic | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/innobase/include/log0log.ic b/innobase/include/log0log.ic new file mode 100644 index 00000000000..e5c313d129b --- /dev/null +++ b/innobase/include/log0log.ic @@ -0,0 +1,378 @@ +/****************************************************** +Database log + +(c) 1995 Innobase Oy + +Created 12/9/1995 Heikki Tuuri +*******************************************************/ + +#include "os0file.h" +#include "mach0data.h" +#include "mtr0mtr.h" + +/********************************************************** +Checks by parsing that the catenated log segment for a single mtr is +consistent. */ + +ibool +log_check_log_recs( +/*===============*/ + 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 */ + dulint buf_start_lsn); /* in: buffer start lsn */ + +/**************************************************************** +Gets a log block flush bit. */ +UNIV_INLINE +ibool +log_block_get_flush_bit( +/*====================*/ + /* out: TRUE if this block was the first + to be written in a log flush */ + byte* log_block) /* in: log block */ +{ + if (LOG_BLOCK_FLUSH_BIT_MASK + & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)) { + + return(TRUE); + } + + return(FALSE); +} + +/**************************************************************** +Sets the log block flush bit. */ +UNIV_INLINE +void +log_block_set_flush_bit( +/*====================*/ + byte* log_block, /* in: log block */ + ibool val) /* in: value to set */ +{ + ulint field; + + field = mach_read_from_4(log_block + LOG_BLOCK_HDR_NO); + + if (val) { + field = field | LOG_BLOCK_FLUSH_BIT_MASK; + } else { + field = field & ~LOG_BLOCK_FLUSH_BIT_MASK; + } + + mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, field); +} + +/**************************************************************** +Gets a log block number stored in the header. */ +UNIV_INLINE +ulint +log_block_get_hdr_no( +/*=================*/ + /* out: log block number stored in the block + header */ + byte* log_block) /* in: log block */ +{ + return(~LOG_BLOCK_FLUSH_BIT_MASK + & mach_read_from_4(log_block + LOG_BLOCK_HDR_NO)); +} + +/**************************************************************** +Sets the log block number stored in the header; NOTE that this must be set +before the flush bit! */ +UNIV_INLINE +void +log_block_set_hdr_no( +/*=================*/ + byte* log_block, /* in: log block */ + ulint n) /* in: log block number: must be > 0 and + < LOG_BLOCK_FLUSH_BIT_MASK */ +{ + ut_ad(n > 0); + ut_ad(n < LOG_BLOCK_FLUSH_BIT_MASK); + + mach_write_to_4(log_block + LOG_BLOCK_HDR_NO, n); +} + +/**************************************************************** +Gets a log block data length. */ +UNIV_INLINE +ulint +log_block_get_data_len( +/*===================*/ + /* out: log block data length measured as a + byte offset from the block start */ + byte* log_block) /* in: log block */ +{ + return(mach_read_from_2(log_block + LOG_BLOCK_HDR_DATA_LEN)); +} + +/**************************************************************** +Sets the log block data length. */ +UNIV_INLINE +void +log_block_set_data_len( +/*===================*/ + byte* log_block, /* in: log block */ + ulint len) /* in: data length */ +{ + mach_write_to_2(log_block + LOG_BLOCK_HDR_DATA_LEN, len); +} + +/**************************************************************** +Gets a log block first mtr log record group offset. */ +UNIV_INLINE +ulint +log_block_get_first_rec_group( +/*==========================*/ + /* out: first mtr log record group byte offset + from the block start, 0 if none */ + byte* log_block) /* in: log block */ +{ + return(mach_read_from_2(log_block + LOG_BLOCK_FIRST_REC_GROUP)); +} + +/**************************************************************** +Sets the log block first mtr log record group offset. */ +UNIV_INLINE +void +log_block_set_first_rec_group( +/*==========================*/ + byte* log_block, /* in: log block */ + ulint offset) /* in: offset, 0 if none */ +{ + mach_write_to_2(log_block + LOG_BLOCK_FIRST_REC_GROUP, offset); +} + +/**************************************************************** +Gets a log block checkpoint number field (4 lowest bytes). */ +UNIV_INLINE +ulint +log_block_get_checkpoint_no( +/*========================*/ + /* out: checkpoint no (4 lowest bytes) */ + byte* log_block) /* in: log block */ +{ + return(mach_read_from_4(log_block + LOG_BLOCK_CHECKPOINT_NO)); +} + +/**************************************************************** +Sets a log block checkpoint number field (4 lowest bytes). */ +UNIV_INLINE +void +log_block_set_checkpoint_no( +/*========================*/ + byte* log_block, /* in: log block */ + dulint no) /* in: checkpoint no */ +{ + mach_write_to_4(log_block + LOG_BLOCK_CHECKPOINT_NO, + ut_dulint_get_low(no)); +} + +/**************************************************************** +Gets a log block number stored in the trailer. */ +UNIV_INLINE +ulint +log_block_get_trl_no( +/*=================*/ + /* out: log block number stored in the block + trailer */ + byte* log_block) /* in: log block */ +{ + return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE + - LOG_BLOCK_TRL_NO)); +} + +/**************************************************************** +Sets the log block number stored in the trailer. */ +UNIV_INLINE +void +log_block_set_trl_no( +/*=================*/ + byte* log_block, /* in: log block */ + ulint n) /* in: log block number */ +{ + mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_NO, + n); +} + +/**************************************************************** +Converts a lsn to a log block number. */ +UNIV_INLINE +ulint +log_block_convert_lsn_to_no( +/*========================*/ + /* out: log block number, it is > 0 and <= 1G */ + dulint lsn) /* in: lsn of a byte within the block */ +{ + ulint no; + + no = ut_dulint_get_low(lsn) / OS_FILE_LOG_BLOCK_SIZE; + no += (ut_dulint_get_high(lsn) % OS_FILE_LOG_BLOCK_SIZE) + * 2 * (0x80000000 / OS_FILE_LOG_BLOCK_SIZE); + + no = no & 0x3FFFFFFF; + + return(no + 1); +} + +/**************************************************************** +Initializes a log block in the log buffer. */ +UNIV_INLINE +void +log_block_init( +/*===========*/ + byte* log_block, /* in: pointer to the log buffer */ + dulint lsn) /* in: lsn within the log block */ +{ + 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); + log_block_set_trl_no(log_block, no); + + log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE); + log_block_set_first_rec_group(log_block, 0); +} + +/**************************************************************** +Writes to the log the string given. The log must be released with +log_release. */ +UNIV_INLINE +dulint +log_reserve_and_write_fast( +/*=======================*/ + /* out: end lsn of the log record, ut_dulint_zero if + did not succeed */ + byte* str, /* in: string */ + ulint len, /* in: string length */ + dulint* start_lsn,/* out: start lsn of the log record */ + ibool* success)/* out: TRUE if success */ +{ + log_t* log = log_sys; + ulint data_len; + dulint lsn; + + *success = TRUE; + + mutex_enter(&(log->mutex)); + + data_len = len + log->buf_free % OS_FILE_LOG_BLOCK_SIZE; + + if (log->online_backup_state + || (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE)) { + + /* The string does not fit within the current log block + or the log block would become full */ + + *success = FALSE; + + mutex_exit(&(log->mutex)); + + return(ut_dulint_zero); + } + + *start_lsn = log->lsn; + + ut_memcpy(log->buf + log->buf_free, str, len); + + log_block_set_data_len(ut_align_down(log->buf + log->buf_free, + OS_FILE_LOG_BLOCK_SIZE), + data_len); +#ifdef UNIV_LOG_DEBUG + log->old_buf_free = log->buf_free; + log->old_lsn = log->lsn; +#endif + log->buf_free += len; + + ut_ad(log->buf_free <= log->buf_size); + + lsn = ut_dulint_add(log->lsn, len); + + log->lsn = lsn; + +#ifdef UNIV_LOG_DEBUG + log_check_log_recs(log->buf + log->old_buf_free, + log->buf_free - log->old_buf_free, log->old_lsn); +#endif + return(lsn); +} + +/*************************************************************************** +Releases the log mutex. */ +UNIV_INLINE +void +log_release(void) +/*=============*/ +{ + mutex_exit(&(log_sys->mutex)); +} + +/**************************************************************** +Gets the current lsn. */ +UNIV_INLINE +dulint +log_get_lsn(void) +/*=============*/ + /* out: current lsn */ +{ + dulint lsn; + + mutex_enter(&(log_sys->mutex)); + + lsn = log_sys->lsn; + + mutex_exit(&(log_sys->mutex)); + + return(lsn); +} + +/*************************************************************************** +Checks if there is need for a log buffer flush or a new checkpoint, and does +this if yes. Any database operation should call this when it has modified +more than about 4 pages. NOTE that this function may only be called when the +OS thread owns no synchronization objects except the dictionary mutex. */ +UNIV_INLINE +void +log_free_check(void) +/*================*/ +{ + /* ut_ad(sync_thread_levels_empty()); */ + + if (log_sys->check_flush_or_checkpoint) { + + log_check_margins(); + } +} + +/**************************************************************************** +Gets the online backup lsn. */ +UNIV_INLINE +dulint +log_get_online_backup_lsn_low(void) +/*===============================*/ + /* out: online_backup_lsn, the caller must + own the log_sys mutex */ +{ + ut_ad(mutex_own(&(log_sys->mutex))); + ut_ad(log_sys->online_backup_state); + + return(log_sys->online_backup_lsn); +} + +/**************************************************************************** +Gets the online backup state. */ +UNIV_INLINE +ibool +log_get_online_backup_state_low(void) +/*=================================*/ + /* out: online backup state, the caller must + own the log_sys mutex */ +{ + ut_ad(mutex_own(&(log_sys->mutex))); + + return(log_sys->online_backup_state); +} |