📄 log0trsh.c
字号:
dulint cp_no; ulint field; ulint fold; byte* buf; ut_ad(mutex_own(&(log_sys->mutex))); /* Look for the latest checkpoint from the log groups */ group = UT_LIST_GET_FIRST(log_sys->log_groups); checkpoint_no = ut_dulint_zero; checkpoint_lsn = ut_dulint_zero; *max_group = NULL; buf = log_sys->checkpoint_buf; while (group) { group->state = LOG_GROUP_CORRUPTED; for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { log_group_read_checkpoint_info(group, field); /* Check the consistency of the checkpoint info */ fold = ut_fold_binary(buf, LOG_CHECKPOINT_CHECKSUM_1); if (fold != mach_read_from_4(buf + LOG_CHECKPOINT_CHECKSUM_1)) { goto not_consistent; } fold = ut_fold_binary(buf + LOG_CHECKPOINT_LSN, LOG_CHECKPOINT_CHECKSUM_2 - LOG_CHECKPOINT_LSN); if (fold != mach_read_from_4(buf + LOG_CHECKPOINT_CHECKSUM_2)) { goto not_consistent; } group->state = LOG_GROUP_OK; group->lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); group->lsn_offset = mach_read_from_4(buf + LOG_CHECKPOINT_OFFSET); group->lsn_file_count = mach_read_from_4( buf + LOG_CHECKPOINT_FILE_COUNT); cp_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); if (ut_dulint_cmp(cp_no, max_no) >= 0) { *max_group = group; *max_field = field; max_no = cp_no; } not_consistent: } group = UT_LIST_GET_NEXT(log_groups, group); } if (*max_group == NULL) { return(DB_ERROR); } return(DB_SUCCESS);}/***********************************************************Parses log records from a buffer and stores them to a hash table to waitmerging to file pages. If the hash table becomes too big, merges automaticallyit to file pages. */staticboolrecv_parse_and_hash_log_recs(/*=========================*/ /* out: TRUE if limit_lsn has been reached */ byte* buf, /* in: buffer containing a log segment or garbage */ ulint len, /* in: buffer length */ dulint start_lsn, /* in: buffer start lsn */ dulint limit_lsn, /* in: recover at least to this lsn */ dulint* recovered_lsn) /* out: was able to parse up to this lsn */{ }/************************************************************Recovers from a checkpoint. When this function returns, the database is ableto start processing new user transactions, but the functionrecv_recovery_from_checkpoint_finish should be called later to completethe recovery and free the resources used in it. */ulintrecv_recovery_from_checkpoint_start(/*================================*/ /* out: error code or DB_SUCCESS */ dulint limit_lsn) /* in: recover up to this lsn if possible */{ log_group_t* max_cp_group; log_group_t* up_to_date_group; ulint max_cp_field; byte* buf; ulint err; dulint checkpoint_lsn; dulint checkpoint_no; dulint recovered_lsn; dulint old_lsn; dulint end_lsn; dulint start_lsn; bool finished; dulint flush_start_lsn; mutex_enter(&(log_sys->mutex)); /* Look for the latest checkpoint from any of the log groups */ err = recv_find_max_checkpoint(&max_cp_group, &max_cp_field); if (err != DB_SUCCESS) { mutex_exit(&(log_sys->mutex)); return(err); } log_group_read_checkpoint_info(max_cp_group, max_cp_field); buf = log_sys->checkpoint_buf; checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); if (ut_dulint_cmp(limit_lsn, checkpoint_lsn) < 0) { mutex_exit(&(log_sys->mutex)); return(DB_ERROR); } /* Start reading the log groups from the checkpoint lsn up. The variable flush_start_lsn tells a lsn up to which the log is known to be contiguously written in all log groups. */ recovered_lsn = checkpoint_lsn; flush_start_lsn = ut_dulint_align_down(checkpoint_lsn, OS_FILE_LOG_BLOCK_SIZE); up_to_date_group = max_cp_group; ut_ad(RECV_SCAN_SIZE <= log_sys->buf_size); group = UT_LIST_GET_FIRST(log_sys->log_groups); while (group) { finished = FALSE; if (group->state == LOG_GROUP_CORRUPTED) { finished = TRUE; } start_lsn = flush_start_lsn; while (!finished) { end_lsn = ut_dulint_add(start_lsn, RECV_SCAN_SIZE); log_group_read_log_seg(LOG_RECOVER, log_sys->buf, group, start_lsn, end_lsn); old_lsn = recovered_lsn; finished = recv_parse_and_hash_log_recs(log_sys->buf, RECV_SCAN_SIZE, start_lsn, limit_lsn, &flush_start_lsn, &recovered_lsn); if (ut_dulint_cmp(recovered_lsn, old_lsn) > 0) { /* We found a more up-to-date group */ up_to_date_group = group; } start_lsn = end_lsn; } group = UT_LIST_GET_NEXT(log_groups, group); } /* Delete possible corrupted or extra log records from all log groups */ recv_truncate_groups(recovered_lsn); /* Synchronize the uncorrupted log groups to the most up-to-date log group; we may also have to copy checkpoint info to groups */ log_sys->next_checkpoint_lsn = checkpoint_lsn; log_sys->next_checkpoint_no = checkpoint_no; recv_synchronize_groups(up_to_date_group, _lsn, max_cp_group); log_sys->next_checkpoint_no = ut_dulint_add(checkpoint_no, 1); /* The database is now ready to start almost normal processing of user transactions */ return(DB_SUCCESS);}/************************************************************Completes recovery from a checkpoint. */voidrecv_recovery_from_checkpoint_finish(void)/*======================================*/{ /* Rollback the uncommitted transactions which have no user session */ trx_rollback_all_without_sess(); /* Merge the hashed log records */ recv_merge_hashed_log_recs(); /* Free the resources of the recovery system */ recv_sys_empty(); }/****************************************************************Writes to the log a record about incrementing the row id counter. */UNIV_INLINEvoidlog_write_row_id_incr_rec(void)/*===========================*/{ log_t* log = log_sys; ulint data_len; mutex_enter(&(log->mutex)); data_len = (log->buf_free % OS_FILE_LOG_BLOCK_SIZE) + 1; if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { /* The string does not fit within the current log block or the the block would become full */ mutex_exit(&(log->mutex)); log_write_row_id_incr_rec_slow(); return; } *(log->buf + log->buf_free) = MLOG_INCR_ROW_ID | MLOG_SINGLE_REC_FLAG; 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; log_check_log_recs(log->buf + log->buf_free, 1, log->lsn);#endif log->buf_free++; ut_ad(log->buf_free <= log->buf_size); UT_DULINT_INC(log->lsn); mutex_exit(&(log->mutex));}/****************************************************************Writes to the log a record about incrementing the row id counter. */staticvoidlog_write_row_id_incr_rec_slow(void)/*================================*/{ byte type; log_reserve_and_open(1); type = MLOG_INCR_ROW_ID | MLOG_SINGLE_REC_FLAG; log_write_low(&type, 1); log_close(); log_release();}/**************************************************************************Parses and applies a log record MLOG_SET_ROW_ID. */byte*dict_hdr_parse_set_row_id(/*======================*/ /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ page_t* page) /* in: page or NULL */{ dulint dval; ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval); if (ptr == NULL) { return(NULL); } if (!page) { return(ptr); } mach_write_to_8(page + DICT_HDR + DICT_HDR_ROW_ID, dval); return(ptr); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -