예제 #1
0
파일: log_slot.c 프로젝트: Jaryli/mongo
/*
 * __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);
}
예제 #2
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);
}