/* * __wt_log_slot_new -- * Find a free slot and switch it as the new active slot. * Must be called holding the slot lock. */ int __wt_log_slot_new(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; WT_LOG *log; WT_LOGSLOT *slot; int32_t i; 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); /* * Keep trying until we can find a free slot. */ for (;;) { /* * For now just restart at 0. We could use log->pool_index * if that is inefficient. */ for (i = 0; i < WT_SLOT_POOL; i++) { slot = &log->slot_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. */ WT_STAT_FAST_CONN_INCR(session, log_slot_transitions); log->active_slot = slot; return (0); } } /* * If we didn't find any free slots signal the worker thread. */ (void)__wt_cond_signal(session, conn->log_wrlsn_cond); __wt_yield(); } /* NOTREACHED */ }
/* * __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 */ }