📄 log0trsh.c
字号:
/******************************************************Recovery(c) 1997 Innobase OyCreated 9/20/1997 Heikki Tuuri*******************************************************/#include "log0recv.h"#ifdef UNIV_NONINL#include "log0recv.ic"#endif#include "mem0mem.h"#include "buf0buf.h"#include "buf0flu.h"#include "srv0srv.h"/* Size of block reads when the log groups are scanned forward to doroll-forward */#define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE)/* Size of block reads when the log groups are scanned backwards to synchronizethem */#define RECV_BACK_SCAN_SIZE (4 * UNIV_PAGE_SIZE)recv_sys_t* recv_sys = NULL;recv_recover_page(block->frame, block->space, block->offset);/************************************************************Creates the recovery system. */voidrecv_sys_create(void)/*=================*/{ ut_a(recv_sys == NULL); recv_sys = mem_alloc(sizeof(recv_t)); mutex_create(&(recv_sys->mutex)); recv_sys->hash = NULL; recv_sys->heap = NULL;}/************************************************************Inits the recovery system for a recovery operation. */voidrecv_sys_init(void)/*===============*/{ recv_sys->hash = hash_create(buf_pool_get_curr_size() / 64); recv_sys->heap = mem_heap_create_in_buffer(256);}/************************************************************Empties the recovery system. */voidrecv_sys_empty(void)/*================*/{ mutex_enter(&(recv_sys->mutex)); hash_free(recv_sys->hash); mem_heap_free(recv_sys->heap); recv_sys->hash = NULL; recv_sys->heap = NULL; mutex_exit(&(recv_sys->mutex));}/***********************************************************For recovery purposes copies the log buffer to a group to synchronize logdata. */staticvoidrecv_log_buf_flush(/*===============*/ log_group_t* group, /* in: log group */ dulint start_lsn, /* in: start lsn of the log data in the log buffer; must be divisible by OS_FILE_LOG_BLOCK_SIZE */ dulint end_lsn) /* in: end lsn of the log data in the log buffer; must be divisible by OS_FILE_LOG_BLOCK_SIZE */{ ulint len; ut_ad(mutex_own(&(log_sys->mutex))); len = ut_dulint_minus(end_lsn, start_lsn); log_group_write_buf(LOG_RECOVER, group, log_sys->buf, len, start_lsn, 0);}/***********************************************************Compares two buffers containing log segments and determines the highest lsnwhere they match, if any. */staticdulintrecv_log_bufs_cmp(/*==============*/ /* out: if no match found, ut_dulint_zero or if start_lsn == LOG_START_LSN, returns LOG_START_LSN; otherwise the highest matching lsn */ byte* recv_buf, /* in: buffer containing valid log data */ byte* buf, /* in: buffer of data from a possibly incompletely written log group */ dulint start_lsn, /* in: buffer start lsn, must be divisible by OS_FILE_LOG_BLOCK_SIZE and must be >= LOG_START_LSN */ dulint end_lsn, /* in: buffer end lsn, must be divisible by OS_FILE_LOG_BLOCK_SIZE */ dulint recovered_lsn) /* in: recovery succeeded up to this lsn */{ ulint len; ulint offset; byte* log_block1; byte* log_block2; ulint no; ulint data_len; ut_ad(ut_dulint_cmp(start_lsn, LOG_START_LSN) >= 0); if (ut_dulint_cmp(end_lsn, recovered_lsn) > 0) { end_lsn = ut_dulint_align_up(recovered_lsn, OS_FILE_LOG_BLOCK_SIZE); } len = ut_dulint_minus(end_lsn, start_lsn); if (len == 0) { goto no_match; } ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); log_block1 = recv_buf + len; log_block2 = buf + len; for (;;) { log_block1 -= OS_FILE_LOG_BLOCK_SIZE; log_block2 -= OS_FILE_LOG_BLOCK_SIZE; no = log_block_get_hdr_no(log_block1); ut_a(no == log_block_get_trl_no(log_block1)); if ((no == log_block_get_hdr_no(log_block2)) && (no == log_block_get_trl_no(log_block2))) { /* Match found if the block is not corrupted */ data_len = log_block_get_data_len(log_block2); if (0 == ut_memcmp(log_block1 + LOG_BLOCK_DATA, log_block2 + LOG_BLOCK_DATA, data_len - LOG_BLOCK_DATA)) { /* Match found */ return(ut_dulint_add(start_lsn, log_block2 - buf + data_len)); } } if (log_block1 == recv_buf) { /* No match found */ break; } }no_match: if (ut_dulint_cmp(start_lsn, LOG_START_LSN) == 0) { return(LOG_START_LSN); } return(ut_dulint_zero);}/************************************************************Copies a log segment from the most up-to-date log group to the other loggroup, so that it contains the latest log data. */staticvoidrecv_copy_group(/*============*/ log_group_t* up_to_date_group, /* in: the most up-to-date log group */ log_group_t* group, /* in: copy to this log group */ dulint_lsn recovered_lsn) /* in: recovery succeeded up to this lsn */{ dulint start_lsn; dulint end_lsn; dulint match; byte* buf; byte* buf1; ut_ad(mutex_own(&(log_sys->mutex))); if (0 == ut_dulint_cmp(LOG_START_LSN, recovered_lsn)) { return; } ut_ad(RECV_BACK_SCAN_SIZE <= log_sys->buf_size); buf1 = mem_alloc(2 * RECV_BACK_SCAN_SIZE); buf = ut_align(buf, RECV_BACK_SCAN_SIZE);); end_lsn = ut_dulint_align_up(recovered_lsn, RECV_BACK_SCAN_SIZE); match = ut_dulint_zero; for (;;) { if (ut_dulint_cmp(ut_dulint_add(LOG_START_LSN, RECV_BACK_SCAN_SIZE), end_lsn) >= 0) { start_lsn = LOG_START_LSN; } else { start_lsn = ut_dulint_subtract(end_lsn, RECV_BACK_SCAN_SIZE); } log_group_read_log_seg(LOG_RECOVER, buf, group, start_lsn, end_lsn); log_group_read_log_seg(LOG_RECOVER, log_sys->buf, up_to_date_group, start_lsn, end_lsn); match = recv_log_bufs_cmp(log_sys->buf, buf, start_lsn, end_lsn, recovered_lsn); if (ut_dulint_cmp(match, recovered_lsn) != 0) { recv_log_buf_flush(group, start_lsn, end_lsn); } if (!ut_dulint_zero(match)) { mem_free(buf1); return; } end_lsn = start_lsn; }}/************************************************************Copies a log segment from the most up-to-date log group to the other loggroups, so that they all contain the latest log data. Also writes the infoabout the latest checkpoint to the groups, and inits the fields in the groupmemory structs to up-to-date values. */voidrecv_synchronize_groups(/*====================*/ log_group_t* up_to_date_group, /* in: the most up-to-date log group */ dulint_lsn recovered_lsn, /* in: recovery succeeded up to this lsn */ log_group_t* max_checkpoint_group) /* in: the group with the most recent checkpoint info */{ log_group_t* group; ut_ad(mutex_own(&(log_sys->mutex))); group = UT_LIST_GET_FIRST(log_sys->log_groups); while (group) { if (group != up_to_date_group) { /* Copy log data */ recv_copy_group(group, up_to_date_group, recovered_lsn); } if (group != max_checkpoint_group) { /* Copy the checkpoint info to the group */ log_group_checkpoint(group); mutex_exit(&(log_sys->mutex)); /* Wait for the checkpoint write to complete */ rw_lock_s_lock(&(log_sys->checkpoint_lock)); rw_lock_s_unlock(&(log_sys->checkpoint_lock)); mutex_enter(&(log_sys->mutex)); } /* Update the fields in the group struct to correspond to recovered_lsn */ log_group_set_fields(group, recovered_lsn); group = UT_LIST_GET_NEXT(log_groups, group); } }/************************************************************Looks for the maximum consistent checkpoint from the log groups. */staticulintrecv_find_max_checkpoint(/*=====================*/ /* out: error code or DB_SUCCESS */ log_group_t** max_group, /* out: max group */ ulint* max_field) /* out: LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 */{ log_group_t* group; dulint max_no;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -