summaryrefslogtreecommitdiff
path: root/innobase/log/log0log.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/log/log0log.c')
-rw-r--r--innobase/log/log0log.c161
1 files changed, 154 insertions, 7 deletions
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index e787176bb21..5ec1274d117 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -1,7 +1,7 @@
/******************************************************
Database log
-(c) 1995-1997 InnoDB Oy
+(c) 1995-1997 Innobase Oy
Created 12/9/1995 Heikki Tuuri
*******************************************************/
@@ -24,6 +24,9 @@ Created 12/9/1995 Heikki Tuuri
#include "trx0sys.h"
#include "trx0trx.h"
+/* Current free limit; protected by the log sys mutex; 0 means uninitialized */
+ulint log_fsp_current_free_limit = 0;
+
/* Global log system variable */
log_t* log_sys = NULL;
@@ -95,6 +98,32 @@ void
log_archive_margin(void);
/*====================*/
+/********************************************************************
+Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
+so that we know that the limit has been written to a log checkpoint field
+on disk. */
+
+void
+log_fsp_current_free_limit_set_and_checkpoint(
+/*==========================================*/
+ ulint limit) /* in: limit to set */
+{
+ ibool success;
+
+ mutex_enter(&(log_sys->mutex));
+
+ log_fsp_current_free_limit = limit;
+
+ mutex_exit(&(log_sys->mutex));
+
+ /* Try to make a synchronous checkpoint */
+
+ success = FALSE;
+
+ while (!success) {
+ success = log_checkpoint(TRUE, TRUE);
+ }
+}
/********************************************************************
Returns the oldest modified block lsn in the pool, or log_sys->lsn if none
@@ -436,6 +465,51 @@ log_group_calc_lsn_offset(
return(log_group_calc_real_offset(offset, group));
}
+/***********************************************************************
+Calculates where in log files we find a specified lsn. */
+
+ulint
+log_calc_where_lsn_is(
+/*==================*/
+ /* out: log file number */
+ ib_longlong* log_file_offset, /* out: offset in that file
+ (including the header) */
+ dulint first_header_lsn, /* in: first log file start
+ lsn */
+ dulint lsn, /* in: lsn whose position to
+ determine */
+ ulint n_log_files, /* in: total number of log
+ files */
+ ib_longlong log_file_size) /* in: log file size
+ (including the header) */
+{
+ ib_longlong ib_lsn;
+ ib_longlong ib_first_header_lsn;
+ ib_longlong capacity = log_file_size - LOG_FILE_HDR_SIZE;
+ ulint file_no;
+ ib_longlong add_this_many;
+
+ ib_lsn = ut_conv_dulint_to_longlong(lsn);
+ ib_first_header_lsn = ut_conv_dulint_to_longlong(first_header_lsn);
+
+ if (ib_lsn < ib_first_header_lsn) {
+ add_this_many = 1 + (ib_first_header_lsn - ib_lsn)
+ / (capacity * (ib_longlong)n_log_files);
+ ib_lsn += add_this_many
+ * capacity * (ib_longlong)n_log_files;
+ }
+
+ ut_a(ib_lsn >= ib_first_header_lsn);
+
+ file_no = ((ulint)((ib_lsn - ib_first_header_lsn) / capacity))
+ % n_log_files;
+ *log_file_offset = (ib_lsn - ib_first_header_lsn) % capacity;
+
+ *log_file_offset = *log_file_offset + LOG_FILE_HDR_SIZE;
+
+ return(file_no);
+}
+
/************************************************************
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
@@ -653,7 +727,7 @@ log_init(void)
#ifdef UNIV_LOG_DEBUG
recv_sys_create();
- recv_sys_init();
+ recv_sys_init(FALSE, buf_pool_get_curr_size());
recv_sys->parse_start_lsn = log_sys->lsn;
recv_sys->scanned_lsn = log_sys->lsn;
@@ -961,7 +1035,7 @@ log_group_write_buf(
ibool sync;
ibool write_header;
ulint next_offset;
-
+
ut_ad(mutex_own(&(log_sys->mutex)));
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
@@ -1002,9 +1076,28 @@ loop:
}
if (log_debug_writes) {
+ ulint i;
+
+ printf(
+ "Writing log file segment to group %lu offset %lu len %lu\n"
+ "start lsn %lu %lu\n",
+ group->id, next_offset, write_len,
+ ut_dulint_get_high(start_lsn),
+ ut_dulint_get_low(start_lsn));
printf(
- "Writing log file segment to group %lu offset %lu len %lu\n",
- group->id, next_offset, write_len);
+ "First block n:o %lu last block n:o %lu\n",
+ log_block_get_hdr_no(buf),
+ log_block_get_hdr_no(
+ buf + write_len - OS_FILE_LOG_BLOCK_SIZE));
+ ut_a(log_block_get_hdr_no(buf)
+ == log_block_convert_lsn_to_no(start_lsn));
+
+ for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
+
+ ut_a(log_block_get_hdr_no(buf) + i
+ == log_block_get_hdr_no(buf
+ + i * OS_FILE_LOG_BLOCK_SIZE));
+ }
}
if (log_do_write) {
@@ -1346,7 +1439,7 @@ log_group_checkpoint(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
- ut_ad(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
+ ut_a(LOG_CHECKPOINT_SIZE <= OS_FILE_LOG_BLOCK_SIZE);
buf = group->checkpoint_buf;
@@ -1394,6 +1487,15 @@ log_group_checkpoint(
LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
+ /* Starting from InnoDB-3.23.50, we also write info on allocated
+ size in the tablespace */
+
+ mach_write_to_4(buf + LOG_CHECKPOINT_FSP_FREE_LIMIT,
+ log_fsp_current_free_limit);
+
+ mach_write_to_4(buf + LOG_CHECKPOINT_FSP_MAGIC_N,
+ LOG_CHECKPOINT_FSP_MAGIC_N_VAL);
+
/* We alternate the physical place of the checkpoint info in the first
log file */
@@ -1429,6 +1531,48 @@ log_group_checkpoint(
}
/**********************************************************
+Writes info to a buffer of a log group when log files are created in
+backup restoration. */
+
+void
+log_reset_first_header_and_checkpoint(
+/*==================================*/
+ byte* hdr_buf,/* in: buffer which will be written to the start
+ of the first log file */
+ dulint lsn) /* in: lsn of the start of the first log file
+ + LOG_BLOCK_HDR_SIZE */
+{
+ ulint fold;
+ byte* buf;
+
+ mach_write_to_4(hdr_buf + LOG_GROUP_ID, 0);
+ mach_write_to_8(hdr_buf + LOG_FILE_START_LSN, lsn);
+
+ buf = hdr_buf + LOG_CHECKPOINT_1;
+
+ mach_write_to_8(buf + LOG_CHECKPOINT_NO, ut_dulint_zero);
+ mach_write_to_8(buf + LOG_CHECKPOINT_LSN, lsn);
+
+ mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
+ LOG_FILE_HDR_SIZE + LOG_BLOCK_HDR_SIZE);
+
+ mach_write_to_4(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, 2 * 1024 * 1024);
+
+ mach_write_to_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN, ut_dulint_max);
+
+ fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1);
+ mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_1, fold);
+
+ fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
+ LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN);
+ mach_write_to_4(buf + LOG_CHECKPOINT_CHECKSUM_2, fold);
+
+ /* Starting from InnoDB-3.23.50, we should also write info on
+ allocated size in the tablespace, but unfortunately we do not
+ know it here */
+}
+
+/**********************************************************
Reads a checkpoint info from a log group header to log_sys->checkpoint_buf. */
void
@@ -2800,7 +2944,10 @@ log_check_log_recs(
ut_memcpy(scan_buf, start, end - start);
- recv_scan_log_recs(FALSE, scan_buf, end - start,
+ recv_scan_log_recs(TRUE,
+ buf_pool_get_curr_size() -
+ RECV_POOL_N_FREE_BLOCKS * UNIV_PAGE_SIZE,
+ FALSE, scan_buf, end - start,
ut_dulint_align_down(buf_start_lsn,
OS_FILE_LOG_BLOCK_SIZE),
&contiguous_lsn, &scanned_lsn);