/* * __log_slot_switch_internal -- * Switch out the current slot and set up a new one. */ static int __log_slot_switch_internal( WT_SESSION_IMPL *session, WT_MYSLOT *myslot, bool forced) { WT_DECL_RET; WT_LOG *log; WT_LOGSLOT *slot; bool free_slot, release; log = S2C(session)->log; release = false; slot = myslot->slot; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SLOT)); /* * If someone else raced us to closing this specific slot, we're * done here. */ if (slot != log->active_slot) return (0); /* * We may come through here multiple times if we were able to close * a slot but could not set up a new one. If we closed it already, * don't try to do it again but still set up the new slot. */ if (!F_ISSET(myslot, WT_MYSLOT_CLOSE)) { ret = __log_slot_close(session, slot, &release, forced); /* * If close returns WT_NOTFOUND it means that someone else * is processing the slot change. */ if (ret == WT_NOTFOUND) return (0); WT_RET(ret); if (release) { WT_RET(__wt_log_release(session, slot, &free_slot)); if (free_slot) __wt_log_slot_free(session, slot); } } /* * Set that we have closed this slot because we may call in here * multiple times if we retry creating a new slot. */ F_SET(myslot, WT_MYSLOT_CLOSE); WT_RET(__wt_log_slot_new(session)); F_CLR(myslot, WT_MYSLOT_CLOSE); return (0); }
/* * __log_slot_switch_internal -- * Switch out the current slot and set up a new one. */ static int __log_slot_switch_internal( WT_SESSION_IMPL *session, WT_MYSLOT *myslot, bool forced, bool *did_work) { WT_DECL_RET; WT_LOG *log; WT_LOGSLOT *slot; uint32_t joined; bool free_slot, release; log = S2C(session)->log; release = false; slot = myslot->slot; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SLOT)); /* * If someone else raced us to closing this specific slot, we're * done here. */ if (slot != log->active_slot) return (0); /* * If the current active slot is unused and this is a forced switch, * we're done. If this is a non-forced switch we always switch * because the slot could be part of an unbuffered operation. */ joined = WT_LOG_SLOT_JOINED(slot->slot_state); if (joined == 0 && forced && !F_ISSET(log, WT_LOG_FORCE_NEWFILE)) { WT_STAT_CONN_INCR(session, log_force_write_skip); if (did_work != NULL) *did_work = false; return (0); } /* * We may come through here multiple times if we were not able to * set up a new one. If we closed it already, * don't try to do it again but still set up the new slot. */ if (!F_ISSET(myslot, WT_MYSLOT_CLOSE)) { ret = __log_slot_close(session, slot, &release, forced); /* * If close returns WT_NOTFOUND it means that someone else * is processing the slot change. */ if (ret == WT_NOTFOUND) return (0); WT_RET(ret); /* * Set that we have closed this slot because we may call in here * multiple times if we retry creating a new slot. Similarly * set retain whether this slot needs releasing so that we don't * lose that information if we retry. */ F_SET(myslot, WT_MYSLOT_CLOSE); if (release) F_SET(myslot, WT_MYSLOT_NEEDS_RELEASE); } /* * Now that the slot is closed, set up a new one so that joining * threads don't have to wait on writing the previous slot if we * release it. Release after setting a new one. */ WT_RET(__log_slot_new(session)); F_CLR(myslot, WT_MYSLOT_CLOSE); if (F_ISSET(myslot, WT_MYSLOT_NEEDS_RELEASE)) { /* * The release here must be done while holding the slot lock. * The reason is that a forced slot switch needs to be sure * that any earlier slot switches have completed, including * writing out the buffer contents of earlier slots. */ WT_RET(__wt_log_release(session, slot, &free_slot)); F_CLR(myslot, WT_MYSLOT_NEEDS_RELEASE); if (free_slot) __wt_log_slot_free(session, slot); } return (ret); }