From c052487cdf42c83bb0fa8e4c0ed135e801ac1e90 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 11 May 2000 09:23:29 +0000 Subject: [PATCH] 169. [func] ratelimiter can now process N events per interval. --- CHANGES | 2 + lib/isc/include/isc/ratelimiter.h | 7 ++++ lib/isc/ratelimiter.c | 65 ++++++++++++++++++------------- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/CHANGES b/CHANGES index 875f7d5188..c23407d476 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + 169. [func] ratelimiter can now process N events per interval. + 168. [bug] include statements in named.conf caused syntax errors due to not consuming the semicolon ending the include statement before switching input streams. diff --git a/lib/isc/include/isc/ratelimiter.h b/lib/isc/include/isc/ratelimiter.h index 5dd4b57919..122e49bd00 100644 --- a/lib/isc/include/isc/ratelimiter.h +++ b/lib/isc/include/isc/ratelimiter.h @@ -59,6 +59,13 @@ isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval); * '*interval' is a nonzero interval. */ +void +isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t perint); +/* + * Set the number of events procesed per interval timer tic. + * If 'perint' is zero it is trated as 1. + */ + isc_result_t isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_event_t **eventp); /* diff --git a/lib/isc/ratelimiter.c b/lib/isc/ratelimiter.c index e95692e004..0ca41753fd 100644 --- a/lib/isc/ratelimiter.c +++ b/lib/isc/ratelimiter.c @@ -36,6 +36,7 @@ struct isc_ratelimiter { isc_task_t * task; isc_timer_t * timer; isc_interval_t interval; + isc_uint32_t pertic; isc_ratelimiter_state_t state; isc_event_t shutdownevent; ISC_LIST(isc_event_t) pending; @@ -69,6 +70,7 @@ isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, rl->task = task; isc_interval_set(&rl->interval, 0, 0); rl->timer = NULL; + rl->pertic = 1; rl->state = isc_ratelimiter_worklimited; ISC_LIST_INIT(rl->pending); @@ -111,6 +113,13 @@ isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) { UNLOCK(&rl->lock); return (result); } + +void +isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t pertic) { + if (pertic == 0) + pertic = 1; + rl->pertic = pertic; +} isc_result_t isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_event_t **eventp) { @@ -142,34 +151,38 @@ 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); - 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_worklimited; - } - UNLOCK(&rl->lock); + isc_event_free(&event); - /* - * If we have an event, dispatch it. - * There is potential for optimization here since - * we are already executing in the context of "task". - */ - if (p != NULL) - isc_task_send(rl->task, &p); - INSIST(p == NULL); + + 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_worklimited; + pertic = 0; /* Force the loop to exit. */ + } + UNLOCK(&rl->lock); + if (p != NULL) + isc_task_send(rl->task, &p); + INSIST(p == NULL); + } } void