/* * __log_prealloc_once -- * Perform one iteration of log pre-allocation. */ static int __log_prealloc_once(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_LOG *log; u_int i, reccount; char **recfiles; conn = S2C(session); log = conn->log; reccount = 0; recfiles = NULL; /* * Allocate up to the maximum number, accounting for any existing * files that may not have been used yet. */ WT_ERR(__wt_dirlist(session, conn->log_path, WT_LOG_PREPNAME, WT_DIRLIST_INCLUDE, &recfiles, &reccount)); __wt_log_files_free(session, recfiles, reccount); recfiles = NULL; /* * Adjust the number of files to pre-allocate if we find that * the critical path had to allocate them since we last ran. */ if (log->prep_missed > 0) { conn->log_prealloc += log->prep_missed; WT_ERR(__wt_verbose(session, WT_VERB_LOG, "Missed %" PRIu32 ". Now pre-allocating up to %" PRIu32, log->prep_missed, conn->log_prealloc)); } WT_STAT_FAST_CONN_SET(session, log_prealloc_max, conn->log_prealloc); /* * Allocate up to the maximum number that we just computed and detected. */ for (i = reccount; i < (u_int)conn->log_prealloc; i++) { WT_ERR(__wt_log_allocfile( session, ++log->prep_fileid, WT_LOG_PREPNAME, 1)); WT_STAT_FAST_CONN_INCR(session, log_prealloc_files); } /* * Reset the missed count now. If we missed during pre-allocating * the log files, it means the allocation is not keeping up, not that * we didn't allocate enough. So we don't just want to keep adding * in more. */ log->prep_missed = 0; if (0) err: __wt_err(session, ret, "log pre-alloc server error"); if (recfiles != NULL) __wt_log_files_free(session, recfiles, reccount); return (ret); }
/* * __wt_log_get_files -- * Retrieve the list of all existing log files. */ int __wt_log_get_files(WT_SESSION_IMPL *session, char ***filesp, u_int *countp) { WT_CONNECTION_IMPL *conn; const char *log_path; *countp = 0; *filesp = NULL; conn = S2C(session); log_path = conn->log_path; if (log_path == NULL) log_path = ""; return (__wt_dirlist(session, log_path, WT_LOG_FILENAME, WT_DIRLIST_INCLUDE, filesp, countp)); }
/* * __log_archive_once -- * Perform one iteration of log archiving. Must be called with the * log archive lock held. */ static int __log_archive_once(WT_SESSION_IMPL *session, uint32_t backup_file) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_LOG *log; uint32_t lognum, min_lognum; u_int i, locked, logcount; char **logfiles; conn = S2C(session); log = conn->log; logcount = 0; logfiles = NULL; /* * If we're coming from a backup cursor we want the smaller of * the last full log file copied in backup or the checkpoint LSN. * Otherwise we want the minimum of the last log file written to * disk and the checkpoint LSN. */ if (backup_file != 0) min_lognum = WT_MIN(log->ckpt_lsn.file, backup_file); else min_lognum = WT_MIN(log->ckpt_lsn.file, log->sync_lsn.file); WT_RET(__wt_verbose(session, WT_VERB_LOG, "log_archive: archive to log number %" PRIu32, min_lognum)); /* * Main archive code. Get the list of all log files and * remove any earlier than the minimum log number. */ WT_RET(__wt_dirlist(session, conn->log_path, WT_LOG_FILENAME, WT_DIRLIST_INCLUDE, &logfiles, &logcount)); /* * We can only archive files if a hot backup is not in progress or * if we are the backup. */ WT_RET(__wt_readlock(session, conn->hot_backup_lock)); locked = 1; if (conn->hot_backup == 0 || backup_file != 0) { for (i = 0; i < logcount; i++) { WT_ERR(__wt_log_extract_lognum( session, logfiles[i], &lognum)); if (lognum < min_lognum) WT_ERR(__wt_log_remove( session, WT_LOG_FILENAME, lognum)); } } WT_ERR(__wt_readunlock(session, conn->hot_backup_lock)); locked = 0; __wt_log_files_free(session, logfiles, logcount); logfiles = NULL; logcount = 0; /* * Indicate what is our new earliest LSN. It is the start * of the log file containing the last checkpoint. */ log->first_lsn.file = min_lognum; log->first_lsn.offset = 0; if (0) err: __wt_err(session, ret, "log archive server error"); if (locked) WT_TRET(__wt_readunlock(session, conn->hot_backup_lock)); if (logfiles != NULL) __wt_log_files_free(session, logfiles, logcount); return (ret); }