📄 log0log.c
字号:
/* Wait for the checkpoint write to complete */ rw_lock_s_lock(&(log_sys->checkpoint_lock)); rw_lock_s_unlock(&(log_sys->checkpoint_lock)); } return(TRUE);}/********************************************************************Makes a checkpoint at a given lsn or later. */voidlog_make_checkpoint_at(/*===================*/ dulint lsn, /* in: make a checkpoint at this or a later lsn, if ut_dulint_max, makes a checkpoint at the latest lsn */ ibool write_always) /* in: the function normally checks if the the new checkpoint would have a greater lsn than the previous one: if not, then no physical write is done; by setting this parameter TRUE, a physical write will always be made to log files */{ ibool success; /* Preflush pages synchronously */ success = FALSE; while (!success) { success = log_preflush_pool_modified_pages(lsn, TRUE); } success = FALSE; while (!success) { success = log_checkpoint(TRUE, write_always); }}/********************************************************************Tries to establish a big enough margin of free space in the log groups, suchthat a new log entry can be catenated without an immediate need for acheckpoint. NOTE: this function may only be called if the calling threadowns no synchronization objects! */staticvoidlog_checkpoint_margin(void)/*=======================*/{ log_t* log = log_sys; ulint age; ulint checkpoint_age; ulint advance; dulint oldest_lsn; ibool sync; ibool checkpoint_sync; ibool do_checkpoint; ibool success;loop: sync = FALSE; checkpoint_sync = FALSE; do_checkpoint = FALSE; mutex_enter(&(log->mutex)); if (log->check_flush_or_checkpoint == FALSE) { mutex_exit(&(log->mutex)); return; } oldest_lsn = log_buf_pool_get_oldest_modification(); age = ut_dulint_minus(log->lsn, oldest_lsn); if (age > log->max_modified_age_sync) { /* A flush is urgent: we have to do a synchronous preflush */ sync = TRUE; advance = 2 * (age - log->max_modified_age_sync); } else if (age > log->max_modified_age_async) { /* A flush is not urgent: we do an asynchronous preflush */ advance = age - log->max_modified_age_async; } else { advance = 0; } checkpoint_age = ut_dulint_minus(log->lsn, log->last_checkpoint_lsn); if (checkpoint_age > log->max_checkpoint_age) { /* A checkpoint is urgent: we do it synchronously */ checkpoint_sync = TRUE; do_checkpoint = TRUE; } else if (checkpoint_age > log->max_checkpoint_age_async) { /* A checkpoint is not urgent: do it asynchronously */ do_checkpoint = TRUE; log->check_flush_or_checkpoint = FALSE; } else { log->check_flush_or_checkpoint = FALSE; } mutex_exit(&(log->mutex)); if (advance) { dulint new_oldest = ut_dulint_add(oldest_lsn, advance); success = log_preflush_pool_modified_pages(new_oldest, sync); /* If the flush succeeded, this thread has done its part and can proceed. If it did not succeed, there was another thread doing a flush at the same time. If sync was FALSE, the flush was not urgent, and we let this thread proceed. Otherwise, we let it start from the beginning again. */ if (sync && !success) { mutex_enter(&(log->mutex)); log->check_flush_or_checkpoint = TRUE; mutex_exit(&(log->mutex)); goto loop; } } if (do_checkpoint) { log_checkpoint(checkpoint_sync, FALSE); if (checkpoint_sync) { goto loop; } }}/**********************************************************Reads a specified log segment to a buffer. */voidlog_group_read_log_seg(/*===================*/ ulint type, /* in: LOG_ARCHIVE or LOG_RECOVER */ byte* buf, /* in: buffer where to read */ log_group_t* group, /* in: log group */ dulint start_lsn, /* in: read area start */ dulint end_lsn) /* in: read area end */{ ulint len; ulint source_offset; ibool sync;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ sync = FALSE; if (type == LOG_RECOVER) { sync = TRUE; }loop: source_offset = log_group_calc_lsn_offset(start_lsn, group); len = ut_dulint_minus(end_lsn, start_lsn); ut_ad(len != 0); if ((source_offset % group->file_size) + len > group->file_size) { len = group->file_size - (source_offset % group->file_size); }#ifdef UNIV_LOG_ARCHIVE if (type == LOG_ARCHIVE) { log_sys->n_pending_archive_ios++; }#endif /* UNIV_LOG_ARCHIVE */ log_sys->n_log_ios++; fil_io(OS_FILE_READ | OS_FILE_LOG, sync, group->space_id, source_offset / UNIV_PAGE_SIZE, source_offset % UNIV_PAGE_SIZE, len, buf, NULL); start_lsn = ut_dulint_add(start_lsn, len); buf += len; if (ut_dulint_cmp(start_lsn, end_lsn) != 0) { goto loop; }}#ifdef UNIV_LOG_ARCHIVE/**********************************************************Generates an archived log file name. */voidlog_archived_file_name_gen(/*=======================*/ char* buf, /* in: buffer where to write */ ulint id __attribute__((unused)), /* in: group id; currently we only archive the first group */ ulint file_no)/* in: file number */{ sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, (ulong) file_no);}/**********************************************************Writes a log file header to a log file space. */staticvoidlog_group_archive_file_header_write(/*================================*/ log_group_t* group, /* in: log group */ ulint nth_file, /* in: header to the nth file in the archive log file space */ ulint file_no, /* in: archived file number */ dulint start_lsn) /* in: log file data starts at this lsn */{ byte* buf; ulint dest_offset;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(nth_file < group->n_files); buf = *(group->archive_file_header_bufs + nth_file); mach_write_to_4(buf + LOG_GROUP_ID, group->id); mach_write_to_8(buf + LOG_FILE_START_LSN, start_lsn); mach_write_to_4(buf + LOG_FILE_NO, file_no); mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, FALSE); dest_offset = nth_file * group->file_size; log_sys->n_log_ios++; fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, 2 * OS_FILE_LOG_BLOCK_SIZE, buf, &log_archive_io);}/**********************************************************Writes a log file header to a completed archived log file. */staticvoidlog_group_archive_completed_header_write(/*=====================================*/ log_group_t* group, /* in: log group */ ulint nth_file, /* in: header to the nth file in the archive log file space */ dulint end_lsn) /* in: end lsn of the file */{ byte* buf; ulint dest_offset;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ ut_a(nth_file < group->n_files); buf = *(group->archive_file_header_bufs + nth_file); mach_write_to_4(buf + LOG_FILE_ARCH_COMPLETED, TRUE); mach_write_to_8(buf + LOG_FILE_END_LSN, end_lsn); dest_offset = nth_file * group->file_size + LOG_FILE_ARCH_COMPLETED; log_sys->n_log_ios++; fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->archive_space_id, dest_offset / UNIV_PAGE_SIZE, dest_offset % UNIV_PAGE_SIZE, OS_FILE_LOG_BLOCK_SIZE, buf + LOG_FILE_ARCH_COMPLETED, &log_archive_io);}/**********************************************************Does the archive writes for a single log group. */staticvoidlog_group_archive(/*==============*/ log_group_t* group) /* in: log group */{ os_file_t file_handle; dulint start_lsn; dulint end_lsn; char name[1024]; byte* buf; ulint len; ibool ret; ulint next_offset; ulint n_files; ulint open_mode; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ start_lsn = log_sys->archived_lsn; ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); end_lsn = log_sys->next_archived_lsn; ut_a(ut_dulint_get_low(end_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); buf = log_sys->archive_buf; n_files = 0; next_offset = group->archived_offset;loop: if ((next_offset % group->file_size == 0) || (fil_space_get_size(group->archive_space_id) == 0)) { /* Add the file to the archive file space; create or open the file */ if (next_offset % group->file_size == 0) { open_mode = OS_FILE_CREATE; } else { open_mode = OS_FILE_OPEN; } log_archived_file_name_gen(name, group->id, group->archived_file_no + n_files); file_handle = os_file_create(name, open_mode, OS_FILE_AIO, OS_DATA_FILE, &ret); if (!ret && (open_mode == OS_FILE_CREATE)) { file_handle = os_file_create(name, OS_FILE_OPEN, OS_FILE_AIO, OS_DATA_FILE, &ret); } if (!ret) { fprintf(stderr, "InnoDB: Cannot create or open archive log file %s.\n" "InnoDB: Cannot continue operation.\n" "InnoDB: Check that the log archive directory exists,\n" "InnoDB: you have access rights to it, and\n" "InnoDB: there is space available.\n", name); exit(1); }#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Created archive file %s\n", name); }#endif /* UNIV_DEBUG */ ret = os_file_close(file_handle); ut_a(ret); /* Add the archive file as a node to the space */ fil_node_create(name, group->file_size / UNIV_PAGE_SIZE, group->archive_space_id, FALSE); if (next_offset % group->file_size == 0) { log_group_archive_file_header_write(group, n_files, group->archived_file_no + n_files, start_lsn); next_offset += LOG_FILE_HDR_SIZE; } } len = ut_dulint_minus(end_lsn, start_lsn); if (group->file_size < (next_offset % group->file_size) + len) { len = group->file_size - (next_offset % group->file_size); }#ifdef UNIV_DEBUG if (log_debug_writes) { fprintf(stderr, "Archiving starting at lsn %lu %lu, len %lu to group %lu\n", (ulong) ut_dulint_get_high(start_lsn), (ulong) ut_dulint_get_low(start_lsn), (ulong) len, (ulong) group->id); }#endif /* UNIV_DEBUG */ log_sys->n_pending_archive_ios++; log_sys->n_log_ios++; fil_io(OS_FILE_WRITE | OS_FILE_LOG, FALSE, group->archive_space_id, next_offset / UNIV_PAGE_SIZE, next_offset % UNIV_PAGE_SIZE, ut_calc_align(len, OS_FILE_LOG_BLOCK_SIZE), buf, &log_archive_io); start_lsn = ut_dulint_add(start_lsn, len); next_offset += len; buf += len; if (next_offset % group->file_size == 0) { n_files++; } if (ut_dulint_cmp(end_lsn, start_lsn) != 0) { goto loop; } group->next_archived_file_no = group->archived_file_no + n_files; group->next_archived_offset = next_offset % group->file_size; ut_a(group->next_archived_offset % OS_FILE_LOG_BLOCK_SIZE == 0);}/*********************************************************(Writes to the archive of each log group.) Currently, only the firstgroup is archived. */staticvoidlog_archive_groups(void)/*====================*/{ log_group_t* group;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ group = UT_LIST_GET_FIRST(log_sys->log_groups); log_group_archive(group);}/*********************************************************Completes the archiving write phase for (each log group), currently,the first log group. */staticvoidlog_archive_write_complete_groups(void)/*===================================*/{ log_group_t* group; ulint end_offset; ulint trunc_files; ulint n_files; dulint start_lsn; dulint end_lsn; ulint i;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(log_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ group = UT_LIST_GET_FIRST(log_sys->log_groups); group->archived_file_no = group->next_archived_file_no; group->archived_offset = group->next_archived_offset; /* Truncate from the archive file space all but the last file, or if it has been written full, all files */ n_files = (UNIV_PAGE_SIZE * fil_space_get_size(group->archive_space_id)) / group->file_size; ut_ad(n_files > 0); end_offset = group->archived_offset; if (end_offset % group->file_size == 0) { trunc_files = n_files; } else { trunc_files
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -