예제 #1
0
isc_result_t
isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
	isc_result_t result = ISC_R_SUCCESS;

	REQUIRE(rl != NULL);
	REQUIRE(interval != NULL);

	LOCK(&rl->lock);
	rl->interval = *interval;
	/*
	 * If the timer is currently running, change its rate.
	 */
	if (rl->state == isc_ratelimiter_ratelimited) {
		result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
					 &rl->interval, ISC_FALSE);
	}
	UNLOCK(&rl->lock);
	return (result);
}
예제 #2
0
static void
ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
	isc_result_t result = ISC_R_SUCCESS;
	isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
	isc_event_t *p;
	isc_uint32_t pertic;

	UNUSED(task);

	isc_event_free(&event);

	pertic = rl->pertic;
        while (pertic != 0) {
		pertic--;
		LOCK(&rl->lock);
		p = ISC_LIST_HEAD(rl->pending);
		if (p != NULL) {
			/*
			 * There is work to do.  Let's do it after unlocking.
			 */
			ISC_LIST_UNLINK(rl->pending, p, ev_link);
		} else {
			/*
			 * No work left to do.  Stop the timer so that we don't
			 * waste resources by having it fire periodically.
			 */
			result = isc_timer_reset(rl->timer,
						 isc_timertype_inactive,
						 NULL, NULL, ISC_FALSE);
			RUNTIME_CHECK(result == ISC_R_SUCCESS);
			rl->state = isc_ratelimiter_idle;
			pertic = 0;	/* Force the loop to exit. */
		}
		UNLOCK(&rl->lock);
		if (p != NULL) {
			isc_task_t *evtask = p->ev_sender;
			isc_task_send(evtask, &p);
		}
		INSIST(p == NULL);
	}
}
예제 #3
0
isc_result_t
isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
	isc_result_t result = ISC_R_SUCCESS;

	LOCK(&rl->lock);
	switch (rl->state) {
	case isc_ratelimiter_shuttingdown:
		result = ISC_R_SHUTTINGDOWN;
		break;
	case isc_ratelimiter_ratelimited:
		result = isc_timer_reset(rl->timer, isc_timertype_inactive,
				 	 NULL, NULL, ISC_FALSE);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
	case isc_ratelimiter_idle:
	case isc_ratelimiter_stalled:
		rl->state = isc_ratelimiter_stalled;
		break;
	}
	UNLOCK(&rl->lock);
	return (result);
}
예제 #4
0
파일: ratelimiter.c 프로젝트: 274914765/C
isc_result_t isc_ratelimiter_enqueue (isc_ratelimiter_t * rl, isc_task_t * task, isc_event_t ** eventp)
{
    isc_result_t result = ISC_R_SUCCESS;

    isc_event_t *ev;

    REQUIRE (eventp != NULL && *eventp != NULL);
    REQUIRE (task != NULL);
    ev = *eventp;
    REQUIRE (ev->ev_sender == NULL);

    LOCK (&rl->lock);
    if (rl->state == isc_ratelimiter_ratelimited || rl->state == isc_ratelimiter_stalled)
    {
        isc_event_t *ev = *eventp;

        ev->ev_sender = task;
        ISC_LIST_APPEND (rl->pending, ev, ev_link);
        *eventp = NULL;
    }
    else if (rl->state == isc_ratelimiter_idle)
    {
        result = isc_timer_reset (rl->timer, isc_timertype_ticker, NULL, &rl->interval, ISC_FALSE);
        if (result == ISC_R_SUCCESS)
        {
            ev->ev_sender = task;
            rl->state = isc_ratelimiter_ratelimited;
        }
    }
    else
    {
        INSIST (rl->state == isc_ratelimiter_shuttingdown);
        result = ISC_R_SHUTTINGDOWN;
    }
    UNLOCK (&rl->lock);
    if (*eventp != NULL && result == ISC_R_SUCCESS)
        isc_task_send (task, eventp);
    return (result);
}
예제 #5
0
파일: timer.c 프로젝트: 274914765/C
isc_result_t dns_timer_setidle (isc_timer_t * timer, unsigned int maxtime, unsigned int idletime, isc_boolean_t purge)
{
    isc_result_t result;

    isc_interval_t maxinterval, idleinterval;

    isc_time_t expires;

    /* Compute the time of expiry. */
    isc_interval_set (&maxinterval, maxtime, 0);
    CHECK (isc_time_nowplusinterval (&expires, &maxinterval));

    /*
     * Compute the idle interval, and add a spare nanosecond to
     * work around the silly limitation of the ISC timer interface
     * that you cannot specify an idle interval of zero.
     */
    isc_interval_set (&idleinterval, idletime, 1);

    CHECK (isc_timer_reset (timer, isc_timertype_once, &expires, &idleinterval, purge));
  failure:
    return (result);
}
예제 #6
0
void
isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
	isc_event_t *ev;
	isc_task_t *task;
	LOCK(&rl->lock);
	rl->state = isc_ratelimiter_shuttingdown;
	(void)isc_timer_reset(rl->timer, isc_timertype_inactive,
			      NULL, NULL, ISC_FALSE);
	while ((ev = ISC_LIST_HEAD(rl->pending)) != NULL) {
		ISC_LIST_UNLINK(rl->pending, ev, ev_link);
		ev->ev_attributes |= ISC_EVENTATTR_CANCELED;
		task = ev->ev_sender;
		isc_task_send(task, &ev);
	}
	isc_timer_detach(&rl->timer);
	/*
	 * Send an event to our task.  The delivery of this event
	 * indicates that no more timer events will be delivered.
	 */
	ev = &rl->shutdownevent;
	isc_task_send(rl->task, &ev);

	UNLOCK(&rl->lock);
}
예제 #7
0
파일: t_timers.c 프로젝트: jhbsz/netbsd
static void
t4_te(isc_task_t *task, isc_event_t *event) {

	isc_result_t	isc_result;
	isc_time_t	now;
	isc_time_t	base;
	isc_time_t	ulim;
	isc_time_t	llim;
	isc_time_t	expires;
	isc_interval_t	interval;

	++Tx_eventcnt;

	t_info("tick %d\n", Tx_eventcnt);

	/*
	 * Check expired time.
	 */

	isc_result = isc_time_now(&now);
	if (isc_result != ISC_R_SUCCESS) {
		t_info("isc_time_now failed %s\n",
		       isc_result_totext(isc_result));
		++Tx_nprobs;
	}

	if (isc_result == ISC_R_SUCCESS) {
		interval.seconds = Tx_seconds;
		interval.nanoseconds = Tx_nanoseconds;
		isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
		if (isc_result != ISC_R_SUCCESS) {
			t_info("isc_time_add failed %s\n",
			       isc_result_totext(isc_result));
			++Tx_nprobs;
		}
	}

	if (isc_result == ISC_R_SUCCESS) {
		interval.seconds = Tx_FUDGE_SECONDS;
		interval.nanoseconds = Tx_FUDGE_NANOSECONDS;
		isc_result = isc_time_add(&base, &interval, &ulim);
		if (isc_result != ISC_R_SUCCESS) {
			t_info("isc_time_add failed %s\n",
			       isc_result_totext(isc_result));
			++Tx_nprobs;
		}
	}

	if (isc_result == ISC_R_SUCCESS) {
		isc_result = isc_time_subtract(&base, &interval, &llim);
		if (isc_result != ISC_R_SUCCESS) {
			t_info("isc_time_subtract failed %s\n",
			       isc_result_totext(isc_result));
			++Tx_nprobs;
		}
	}

	if (isc_result == ISC_R_SUCCESS) {
		if (isc_time_compare(&llim, &now) > 0) {
			t_info("timer range error: early by "
			       "%lu microseconds\n",
			       (unsigned long)isc_time_microdiff(&base, &now));
			++Tx_nfails;
		} else if (isc_time_compare(&ulim, &now) < 0) {
			t_info("timer range error: late by "
			       "%lu microseconds\n",
			       (unsigned long)isc_time_microdiff(&now, &base));
			++Tx_nfails;
		}
		Tx_lasttime = now;
	}

	if (Tx_eventcnt < 3) {
		if (event->ev_type != ISC_TIMEREVENT_TICK) {
			t_info("received event type %d, expected type %d\n",
			       event->ev_type, ISC_TIMEREVENT_IDLE);
			++Tx_nfails;
		}
		if (Tx_eventcnt == 2) {
			isc_interval_set(&interval, T4_SECONDS,
					 T4_NANOSECONDS);
			isc_result = isc_time_nowplusinterval(&expires,
							      &interval);
			if (isc_result == ISC_R_SUCCESS) {
				isc_interval_set(&interval, 0, 0);
				isc_result =
					isc_timer_reset(Tx_timer,
							isc_timertype_once,
							&expires, &interval,
							ISC_FALSE);
				if (isc_result != ISC_R_SUCCESS) {
					t_info("isc_timer_reset failed %s\n",
					       isc_result_totext(isc_result));
					++Tx_nfails;
				}
			} else {
				t_info("isc_time_nowplusinterval failed %s\n",
				       isc_result_totext(isc_result));
				++Tx_nprobs;
			}
		}
	} else {
		if (event->ev_type != ISC_TIMEREVENT_LIFE) {
			t_info("received event type %d, expected type %d\n",
			       event->ev_type, ISC_TIMEREVENT_IDLE);
			++Tx_nfails;
		}

		isc_timer_detach(&Tx_timer);
		isc_task_shutdown(task);
	}

	isc_event_free(&event);
}