Ejemplo n.º 1
0
bool
Group::pushGetWaiter(const Options &newOptions, const GetCallback &callback,
	boost::container::vector<Callback> &postLockActions)
{
	if (OXT_LIKELY(!testOverflowRequestQueue()
		&& (newOptions.maxRequestQueueSize == 0
		    || getWaitlist.size() < newOptions.maxRequestQueueSize)))
	{
		getWaitlist.push_back(GetWaiter(
			newOptions.copyAndPersist().detachFromUnionStationTransaction(),
			callback));
		return true;
	} else {
		postLockActions.push_back(boost::bind(GetCallback::call,
			callback, SessionPtr(), boost::make_shared<RequestQueueFullException>(newOptions.maxRequestQueueSize)));

		HookScriptOptions hsOptions;
		if (prepareHookScriptOptions(hsOptions, "queue_full_error")) {
			// TODO <Feb 17, 2015] DK> should probably rate limit this, since we are already at heavy load
			postLockActions.push_back(boost::bind(runHookScripts, hsOptions));
		}

		return false;
	}
}
Ejemplo n.º 2
0
/**
 * Process all waiters on the getWaitlist. Call when capacity has become free.
 * This function assigns sessions to them by calling get() on the corresponding
 * Groups, or by creating more Groups, in so far the new capacity allows.
 */
void
Pool::assignSessionsToGetWaiters(boost::container::vector<Callback> &postLockActions) {
	bool done = false;
	vector<GetWaiter>::iterator it, end = getWaitlist.end();
	vector<GetWaiter> newWaitlist;

	for (it = getWaitlist.begin(); it != end && !done; it++) {
		GetWaiter &waiter = *it;

		Group *group = findMatchingGroup(waiter.options);
		if (group != NULL) {
			SessionPtr session = group->get(waiter.options, waiter.callback,
				postLockActions);
			if (session != NULL) {
				postLockActions.push_back(boost::bind(GetCallback::call,
					waiter.callback, session, ExceptionPtr()));
			}
			/* else: the callback has now been put in
			 *       the group's get wait list.
			 */
		} else if (!atFullCapacityUnlocked()) {
			createGroupAndAsyncGetFromIt(waiter.options, waiter.callback,
				postLockActions);
		} else {
			/* Still cannot satisfy this get request. Keep it on the get
			 * wait list and try again later.
			 */
			newWaitlist.push_back(waiter);
		}
	}

	std::swap(getWaitlist, newWaitlist);
}
/** One of the post lock actions can potentially perform a long-running
 * operation, so running them in a thread is advised.
 */
void
Group::finishShutdown(boost::container::vector<Callback> &postLockActions) {
	TRACE_POINT();
	#ifndef NDEBUG
		LifeStatus lifeStatus = (LifeStatus) this->lifeStatus.load(boost::memory_order_relaxed);
		P_ASSERT_EQ(lifeStatus, SHUTTING_DOWN);
	#endif
	P_DEBUG("Finishing shutdown of group " << info.name);
	if (shutdownCallback) {
		postLockActions.push_back(shutdownCallback);
		shutdownCallback = Callback();
	}
	postLockActions.push_back(boost::bind(interruptAndJoinAllThreads,
		shared_from_this()));
	this->lifeStatus.store(SHUT_DOWN, boost::memory_order_seq_cst);
	selfPointer.reset();
}
Ejemplo n.º 4
0
void
Pool::assignExceptionToGetWaiters(Queue &getWaitlist,
	const ExceptionPtr &exception,
	boost::container::vector<Callback> &postLockActions)
{
	while (!getWaitlist.empty()) {
		postLockActions.push_back(boost::bind(GetCallback::call,
			getWaitlist.front().callback, SessionPtr(),
			exception));
		getWaitlist.pop_front();
	}
}
/**
 * Must be called before destroying a Group. You can optionally provide a
 * callback so that you are notified when shutdown has finished.
 *
 * The caller is responsible for migrating waiters on the getWaitlist.
 *
 * One of the post lock actions can potentially perform a long-running
 * operation, so running them in a thread is advised.
 */
void
Group::shutdown(const Callback &callback,
	boost::container::vector<Callback> &postLockActions)
{
	assert(isAlive());
	assert(getWaitlist.empty());

	P_DEBUG("Begin shutting down group " << info.name);
	shutdownCallback = callback;
	detachAll(postLockActions);
	startCheckingDetachedProcesses(true);
	interruptableThreads.interrupt_all();
	postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
	spawner.reset();
	selfPointer = shared_from_this();
	assert(disableWaitlist.empty());
	lifeStatus.store(SHUTTING_DOWN, boost::memory_order_seq_cst);
}
Ejemplo n.º 6
0
void
Group::assignSessionsToGetWaiters(boost::container::vector<Callback> &postLockActions) {
	unsigned int i = 0;
	bool done = false;

	while (!done && i < getWaitlist.size()) {
		const GetWaiter &waiter = getWaitlist[i];
		RouteResult result = route(waiter.options);
		if (result.process != NULL) {
			postLockActions.push_back(boost::bind(
				GetCallback::call,
				waiter.callback,
				newSession(result.process),
				ExceptionPtr()));
			getWaitlist.erase(getWaitlist.begin() + i);
		} else {
			done = result.finished;
			if (!result.finished) {
				i++;
			}
		}
	}
}
Ejemplo n.º 7
0
void
Group::cleanupSpawner(boost::container::vector<Callback> &postLockActions) {
	assert(isAlive());
	postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
}