Exemple #1
0
int main(void)
{
    message_queue *q = mq_create();
    message_node  *n = NULL;
    printf("size should be 0, is %d\n", mq_size(q));
    mq_push_msgz(q, "one");
    mq_push_msgz(q, "two");
    mq_push_msgz(q, "three");
    printf("size should be 3, is %d\n", mq_size(q));
    n = mq_pop(q);
    printf("expecting \"one\", got \"%s\"\n", n->message);
    mn_destroy(n);
    mq_push_msgz(q, "four");
    n = mq_pop(q);
    printf("expecting \"two\", got \"%s\"\n", n->message);
    mn_destroy(n);
    n = mq_pop(q);
    printf("expecting \"three\", got \"%s\"\n", n->message);
    mn_destroy(n);
    printf("size should be 1, is %d\n", mq_size(q));
    n = mq_pop(q);
    printf("expecting \"four\", got \"%s\"\n", n->message);
    mn_destroy(n);
    printf("size should be 0, is %d\n", mq_size(q));
    n = mq_pop(q);
    printf("expecting \"%p\", got \"%p\"\n", NULL, n);
    mq_destroy(q);
    return 0;
}
Exemple #2
0
/**
 * Based on the information we have on the query hits we already
 * seen or enqueued, determine whether we're going to drop this
 * message on the floor or forward it.
 */
static enum dh_drop
dh_can_forward(dqhit_t *dh, mqueue_t *mq, bool test)
{
	const char *teststr = test ? "[test] " : "";

	g_assert(mq != NULL);

	/*
	 * The heart of the "dynamic hit routing" algorithm is here.
	 */

	/*
	 * If the queue already has more bytes queued than its high-watermark,
	 * meaning it is in the dangerous zone, drop this hit if we sent more
	 * than DH_THRESH_HITS already or have enough in the queue to reach the
	 * DH_MIN_HITS level.
	 */

	if (
		mq_size(mq) > mq_hiwat(mq) &&		/* Implies we're flow-controlled */
		(dh->hits_sent >= DH_THRESH_HITS || dh->hits_queued >= DH_MIN_HITS)
	) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %squeue size > hiwat, dropping", teststr);
		return DH_DROP_FC;
	}

	/*
	 * In SWIFT mode, we're aggressively dropping messages from the queue.
	 * We're in flow control, but we're probably lower than hiwat, the
	 * heaviest condition.  Be more tolerant before dropping, meaning
	 * a strongest dropping rule than the above.
	 */

	if (
		mq_is_swift_controlled(mq) &&
		(dh->hits_sent >= DH_MIN_HITS || dh->hits_queued >= DH_MIN_HITS)
	) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %squeue in SWIFT mode, dropping", teststr);
		return DH_DROP_FC;
	}

	/*
	 * Queue is flow-controlled, don't add to its burden if we
	 * already have hits enqueued for this query with results sent.
	 */

	if (
		mq_is_flow_controlled(mq) &&
		(
			(dh->hits_sent >= DH_MIN_HITS &&
		 	 dh->hits_queued >= 2 * DH_THRESH_HITS) ||
			(dh->hits_sent < DH_MIN_HITS &&
			 (dh->hits_sent + dh->hits_queued) >= DH_MIN_HITS + DH_THRESH_HITS)
		)
	) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %squeue in FLOWC mode, dropping", teststr);
		return DH_DROP_FC;
	}

	/*
	 * If the queue has more bytes than its low-watermark, meaning
	 * it is in the warning zone, drop if we sent more then DH_POPULAR_HITS
	 * already, and we have quite a few queued.
	 */

	if (
		mq_size(mq) > mq_lowat(mq) &&
		dh->hits_sent >= DH_POPULAR_HITS &&
		dh->hits_queued >= (DH_MIN_HITS / 2)
	) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %squeue size > lowat, dropping", teststr);
		return DH_DROP_FC;
	}

	/*
	 * If we sent more than DH_POPULAR_HITS and have DH_MIN_HITS queued,
	 * don't add more and throttle.
	 */

	if (
		dh->hits_sent >= DH_POPULAR_HITS &&
		dh->hits_queued >= DH_MIN_HITS
	) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %senough hits queued, throttling", teststr);
		return DH_DROP_THROTTLE;
	}

	/*
	 * If what we sent plus what we hold will top the maximum number of hits,
	 * yet we did not reach the maximum, drop: we need to leave room for
	 * other hits for less popular results.
	 */

	if (
		dh->hits_sent < DH_MAX_HITS &&
		dh->hits_queued > (DH_MIN_HITS / 2) &&
		(dh->hits_queued + dh->hits_sent) >= DH_MAX_HITS) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %senough queued, nearing max, throttling", teststr);
		return DH_DROP_THROTTLE;
	}

	/*
	 * Finally, if what we have sent makes up for more than DH_MAX_HITS and
	 * we have anything queued for that query, drop.
	 */

	if (dh->hits_sent >= DH_MAX_HITS && dh->hits_queued) {
		if (GNET_PROPERTY(dh_debug) > 19)
			g_debug("DH %smax sendable hits reached, throttling", teststr);
		return DH_DROP_THROTTLE;
	}

	/*
	 * Transient nodes are going to go away soon, results should not be
	 * forwarded to them since they may not be relayed in time anyway or
	 * could be just a waste of bandwidth.
	 *
	 * Avoid them if they already have enough in their TX queue.
	 */

	{
		gnutella_node_t *n = mq_node(mq);

		if (NODE_IS_TRANSIENT(n) && mq_size(mq) > mq_lowat(mq)) {
			if (GNET_PROPERTY(dh_debug) > 19) {
				g_debug("DH %stransient target %s with %d bytes in queue",
					teststr, node_infostr(n), mq_size(mq));
			}
			return DH_DROP_TRANSIENT;
		}
	}

	if (GNET_PROPERTY(dh_debug) > 19)
		g_debug("DH %sforwarding", teststr);

	return DH_FORWARD;
}