diff options
Diffstat (limited to 'usr.sbin/bind/lib/isc/ratelimiter.c')
-rw-r--r-- | usr.sbin/bind/lib/isc/ratelimiter.c | 84 |
1 files changed, 67 insertions, 17 deletions
diff --git a/usr.sbin/bind/lib/isc/ratelimiter.c b/usr.sbin/bind/lib/isc/ratelimiter.c index 5794e5a095c..3b7de219563 100644 --- a/usr.sbin/bind/lib/isc/ratelimiter.c +++ b/usr.sbin/bind/lib/isc/ratelimiter.c @@ -1,21 +1,21 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: ratelimiter.c,v 1.18 2001/01/09 21:56:23 bwelling Exp $ */ +/* $ISC: ratelimiter.c,v 1.18.14.4 2004/03/08 09:04:50 marka Exp $ */ #include <config.h> @@ -27,9 +27,10 @@ #include <isc/util.h> typedef enum { - isc_ratelimiter_ratelimited, - isc_ratelimiter_worklimited, - isc_ratelimiter_shuttingdown + isc_ratelimiter_stalled = 0, + isc_ratelimiter_ratelimited = 1, + isc_ratelimiter_idle = 2, + isc_ratelimiter_shuttingdown = 3 } isc_ratelimiter_state_t; struct isc_ratelimiter { @@ -70,7 +71,7 @@ isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, isc_interval_set(&rl->interval, 0, 0); rl->timer = NULL; rl->pertic = 1; - rl->state = isc_ratelimiter_worklimited; + rl->state = isc_ratelimiter_idle; ISC_LIST_INIT(rl->pending); result = isc_mutex_init(&rl->lock); @@ -139,12 +140,13 @@ isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task, REQUIRE(ev->ev_sender == NULL); LOCK(&rl->lock); - if (rl->state == isc_ratelimiter_ratelimited) { + 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_worklimited) { + } 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) { @@ -191,7 +193,7 @@ ratelimiter_tick(isc_task_t *task, isc_event_t *event) { isc_timertype_inactive, NULL, NULL, ISC_FALSE); RUNTIME_CHECK(result == ISC_R_SUCCESS); - rl->state = isc_ratelimiter_worklimited; + rl->state = isc_ratelimiter_idle; pertic = 0; /* Force the loop to exit. */ } UNLOCK(&rl->lock); @@ -274,3 +276,51 @@ isc_ratelimiter_detach(isc_ratelimiter_t **rlp) { *rlp = NULL; } +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); +} + +isc_result_t +isc_ratelimiter_release(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_stalled: + if (!ISC_LIST_EMPTY(rl->pending)) { + result = isc_timer_reset(rl->timer, + isc_timertype_ticker, NULL, + &rl->interval, ISC_FALSE); + if (result == ISC_R_SUCCESS) + rl->state = isc_ratelimiter_ratelimited; + } else + rl->state = isc_ratelimiter_idle; + break; + case isc_ratelimiter_ratelimited: + case isc_ratelimiter_idle: + break; + } + UNLOCK(&rl->lock); + return (result); +} |