/* * __wt_log_slot_switch -- * Switch out the current slot and set up a new one. */ int __wt_log_slot_switch(WT_SESSION_IMPL *session, WT_MYSLOT *myslot, bool retry, bool forced, bool *did_work) { WT_DECL_RET; WT_LOG *log; log = S2C(session)->log; /* * !!! Since the WT_WITH_SLOT_LOCK macro is a do-while loop, the * compiler does not like it combined directly with the while loop * here. * * The loop conditional is a bit complex. We have to retry if we * closed the slot but were unable to set up a new slot. In that * case the flag indicating we have closed the slot will still be set. * We have to retry in that case regardless of the retry setting * because we are responsible for setting up the new slot. */ do { WT_WITH_SLOT_LOCK(session, log, ret = __log_slot_switch_internal( session, myslot, forced, did_work)); if (ret == EBUSY) { WT_STAT_CONN_INCR(session, log_slot_switch_busy); __wt_yield(); } WT_RET(WT_SESSION_CHECK_PANIC(session)); if (F_ISSET(S2C(session), WT_CONN_CLOSING)) break; } while (F_ISSET(myslot, WT_MYSLOT_CLOSE) || (retry && ret == EBUSY)); return (ret); }
/* * __logmgr_force_ckpt -- * Force a checkpoint out, waiting for the checkpoint LSN in the log * is up to the given log number. */ static int __logmgr_force_ckpt(WT_SESSION_IMPL *session, uint32_t lognum) { WT_CONNECTION_IMPL *conn; WT_LOG *log; WT_SESSION_IMPL *tmp_session; int yield; conn = S2C(session); log = conn->log; yield = 0; WT_RET(__wt_open_internal_session(conn, "compatibility-reconfig", true, 0, &tmp_session)); while (log->ckpt_lsn.l.file < lognum) { /* * Force a checkpoint to be written in the new log file and * force the archiving of all previous log files. We do the * checkpoint in the loop because the checkpoint LSN in the * log record could still reflect the previous log file in * cases such as the write LSN has not yet advanced into the * new log file due to another group of threads still in * progress with their slot copies or writes. */ WT_RET(tmp_session->iface.checkpoint( &tmp_session->iface, "force=1")); WT_RET(WT_SESSION_CHECK_PANIC(tmp_session)); /* * Only sleep in the rare case that we had to come through * this loop more than once. */ if (yield++) { WT_STAT_CONN_INCR(session, log_force_ckpt_sleep); __wt_sleep(0, WT_THOUSAND); } } WT_RET(tmp_session->iface.close(&tmp_session->iface, NULL)); return (0); }
/* * __log_slot_new -- * Find a free slot and switch it as the new active slot. * Must be called holding the slot lock. */ static int __log_slot_new(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; WT_LOG *log; WT_LOGSLOT *slot; int32_t i, pool_i; #ifdef HAVE_DIAGNOSTIC uint64_t time_start, time_stop; int count; #endif WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SLOT)); conn = S2C(session); log = conn->log; /* * Although this function is single threaded, multiple threads could * be trying to set a new active slot sequentially. If we find an * active slot that is valid, return. */ if ((slot = log->active_slot) != NULL && WT_LOG_SLOT_OPEN(slot->slot_state)) return (0); #ifdef HAVE_DIAGNOSTIC count = 0; time_start = __wt_clock(session); #endif /* * Keep trying until we can find a free slot. */ for (;;) { /* * Rotate among the slots to lessen collisions. */ WT_RET(WT_SESSION_CHECK_PANIC(session)); for (i = 0, pool_i = log->pool_index; i < WT_SLOT_POOL; i++, pool_i++) { if (pool_i >= WT_SLOT_POOL) pool_i = 0; slot = &log->slot_pool[pool_i]; if (slot->slot_state == WT_LOG_SLOT_FREE) { /* * Acquire our starting position in the * log file. Assume the full buffer size. */ WT_RET(__wt_log_acquire(session, log->slot_buf_size, slot)); /* * We have a new, initialized slot to use. * Set it as the active slot. */ log->active_slot = slot; log->pool_index = pool_i; return (0); } } /* * If we didn't find any free slots signal the worker thread. */ WT_STAT_CONN_INCR(session, log_slot_no_free_slots); __wt_cond_signal(session, conn->log_wrlsn_cond); __wt_yield(); #ifdef HAVE_DIAGNOSTIC ++count; if (count > WT_MILLION) { time_stop = __wt_clock(session); if (WT_CLOCKDIFF_SEC(time_stop, time_start) > 10) { __wt_errx(session, "SLOT_NEW: Timeout free slot"); __log_slot_dump(session); __wt_abort(session); } count = 0; } #endif } /* NOTREACHED */ }