Пример #1
0
/*
 * __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);
}
Пример #2
0
/*
 * __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);
}
Пример #3
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 */
}