00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/mem.h>
00025 #include <isc/ratelimiter.h>
00026 #include <isc/task.h>
00027 #include <isc/time.h>
00028 #include <isc/timer.h>
00029 #include <isc/util.h>
00030
00031 typedef enum {
00032 isc_ratelimiter_stalled = 0,
00033 isc_ratelimiter_ratelimited = 1,
00034 isc_ratelimiter_idle = 2,
00035 isc_ratelimiter_shuttingdown = 3
00036 } isc_ratelimiter_state_t;
00037
00038 struct isc_ratelimiter {
00039 isc_mem_t * mctx;
00040 isc_mutex_t lock;
00041 int refs;
00042 isc_task_t * task;
00043 isc_timer_t * timer;
00044 isc_interval_t interval;
00045 isc_uint32_t pertic;
00046 isc_ratelimiter_state_t state;
00047 isc_event_t shutdownevent;
00048 ISC_LIST(isc_event_t) pending;
00049 };
00050
00051 #define ISC_RATELIMITEREVENT_SHUTDOWN (ISC_EVENTCLASS_RATELIMITER + 1)
00052
00053 static void
00054 ratelimiter_tick(isc_task_t *task, isc_event_t *event);
00055
00056 static void
00057 ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event);
00058
00059 isc_result_t
00060 isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
00061 isc_task_t *task, isc_ratelimiter_t **ratelimiterp)
00062 {
00063 isc_result_t result;
00064 isc_ratelimiter_t *rl;
00065 INSIST(ratelimiterp != NULL && *ratelimiterp == NULL);
00066
00067 rl = isc_mem_get(mctx, sizeof(*rl));
00068 if (rl == NULL)
00069 return ISC_R_NOMEMORY;
00070 rl->mctx = mctx;
00071 rl->refs = 1;
00072 rl->task = task;
00073 isc_interval_set(&rl->interval, 0, 0);
00074 rl->timer = NULL;
00075 rl->pertic = 1;
00076 rl->state = isc_ratelimiter_idle;
00077 ISC_LIST_INIT(rl->pending);
00078
00079 result = isc_mutex_init(&rl->lock);
00080 if (result != ISC_R_SUCCESS)
00081 goto free_mem;
00082
00083 result = isc_timer_create(timermgr, isc_timertype_inactive,
00084 NULL, NULL, rl->task, ratelimiter_tick,
00085 rl, &rl->timer);
00086 if (result != ISC_R_SUCCESS)
00087 goto free_mutex;
00088
00089
00090
00091
00092
00093 rl->refs++;
00094
00095 ISC_EVENT_INIT(&rl->shutdownevent,
00096 sizeof(isc_event_t),
00097 0, NULL, ISC_RATELIMITEREVENT_SHUTDOWN,
00098 ratelimiter_shutdowncomplete, rl, rl, NULL, NULL);
00099
00100 *ratelimiterp = rl;
00101 return (ISC_R_SUCCESS);
00102
00103 free_mutex:
00104 DESTROYLOCK(&rl->lock);
00105 free_mem:
00106 isc_mem_put(mctx, rl, sizeof(*rl));
00107 return (result);
00108 }
00109
00110 isc_result_t
00111 isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
00112 isc_result_t result = ISC_R_SUCCESS;
00113
00114 REQUIRE(rl != NULL);
00115 REQUIRE(interval != NULL);
00116
00117 LOCK(&rl->lock);
00118 rl->interval = *interval;
00119
00120
00121
00122 if (rl->state == isc_ratelimiter_ratelimited) {
00123 result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
00124 &rl->interval, ISC_FALSE);
00125 }
00126 UNLOCK(&rl->lock);
00127 return (result);
00128 }
00129
00130 void
00131 isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t pertic) {
00132
00133 REQUIRE(rl != NULL);
00134
00135 if (pertic == 0)
00136 pertic = 1;
00137 rl->pertic = pertic;
00138 }
00139
00140 isc_result_t
00141 isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
00142 isc_event_t **eventp)
00143 {
00144 isc_result_t result = ISC_R_SUCCESS;
00145 isc_event_t *ev;
00146
00147 REQUIRE(rl != NULL);
00148 REQUIRE(task != NULL);
00149 REQUIRE(eventp != NULL && *eventp != NULL);
00150 ev = *eventp;
00151 REQUIRE(ev->ev_sender == NULL);
00152
00153 LOCK(&rl->lock);
00154 if (rl->state == isc_ratelimiter_ratelimited ||
00155 rl->state == isc_ratelimiter_stalled) {
00156 ev->ev_sender = task;
00157 *eventp = NULL;
00158 ISC_LIST_APPEND(rl->pending, ev, ev_link);
00159 } else if (rl->state == isc_ratelimiter_idle) {
00160 result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
00161 &rl->interval, ISC_FALSE);
00162 if (result == ISC_R_SUCCESS) {
00163 ev->ev_sender = task;
00164 rl->state = isc_ratelimiter_ratelimited;
00165 }
00166 } else {
00167 INSIST(rl->state == isc_ratelimiter_shuttingdown);
00168 result = ISC_R_SHUTTINGDOWN;
00169 }
00170 UNLOCK(&rl->lock);
00171 if (*eventp != NULL && result == ISC_R_SUCCESS)
00172 isc_task_send(task, eventp);
00173 return (result);
00174 }
00175
00176 isc_result_t
00177 isc_ratelimiter_dequeue(isc_ratelimiter_t *rl, isc_event_t *event) {
00178 isc_result_t result = ISC_R_SUCCESS;
00179
00180 REQUIRE(rl != NULL);
00181 REQUIRE(event != NULL);
00182
00183 LOCK(&rl->lock);
00184 if (ISC_LINK_LINKED(event, ev_link)) {
00185 ISC_LIST_UNLINK(rl->pending, event, ev_link);
00186 event->ev_sender = NULL;
00187 } else
00188 result = ISC_R_NOTFOUND;
00189 UNLOCK(&rl->lock);
00190 return (result);
00191 }
00192
00193 static void
00194 ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
00195 isc_result_t result = ISC_R_SUCCESS;
00196 isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
00197 isc_event_t *p;
00198 isc_uint32_t pertic;
00199
00200 UNUSED(task);
00201
00202 isc_event_free(&event);
00203
00204 pertic = rl->pertic;
00205 while (pertic != 0) {
00206 pertic--;
00207 LOCK(&rl->lock);
00208 p = ISC_LIST_HEAD(rl->pending);
00209 if (p != NULL) {
00210
00211
00212
00213 ISC_LIST_UNLINK(rl->pending, p, ev_link);
00214 } else {
00215
00216
00217
00218
00219 result = isc_timer_reset(rl->timer,
00220 isc_timertype_inactive,
00221 NULL, NULL, ISC_FALSE);
00222 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00223 rl->state = isc_ratelimiter_idle;
00224 pertic = 0;
00225 }
00226 UNLOCK(&rl->lock);
00227 if (p != NULL) {
00228 isc_task_t *evtask = p->ev_sender;
00229 isc_task_send(evtask, &p);
00230 }
00231 INSIST(p == NULL);
00232 }
00233 }
00234
00235 void
00236 isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
00237 isc_event_t *ev;
00238 isc_task_t *task;
00239
00240 REQUIRE(rl != NULL);
00241
00242 LOCK(&rl->lock);
00243 rl->state = isc_ratelimiter_shuttingdown;
00244 (void)isc_timer_reset(rl->timer, isc_timertype_inactive,
00245 NULL, NULL, ISC_FALSE);
00246 while ((ev = ISC_LIST_HEAD(rl->pending)) != NULL) {
00247 ISC_LIST_UNLINK(rl->pending, ev, ev_link);
00248 ev->ev_attributes |= ISC_EVENTATTR_CANCELED;
00249 task = ev->ev_sender;
00250 isc_task_send(task, &ev);
00251 }
00252 isc_timer_detach(&rl->timer);
00253
00254
00255
00256
00257
00258 ev = &rl->shutdownevent;
00259 isc_task_send(rl->task, &ev);
00260
00261 UNLOCK(&rl->lock);
00262 }
00263
00264 static void
00265 ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event) {
00266 isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
00267
00268 UNUSED(task);
00269
00270 isc_ratelimiter_detach(&rl);
00271 }
00272
00273 static void
00274 ratelimiter_free(isc_ratelimiter_t *rl) {
00275 DESTROYLOCK(&rl->lock);
00276 isc_mem_put(rl->mctx, rl, sizeof(*rl));
00277 }
00278
00279 void
00280 isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target) {
00281
00282 REQUIRE(source != NULL);
00283 REQUIRE(target != NULL && *target == NULL);
00284
00285 LOCK(&source->lock);
00286 REQUIRE(source->refs > 0);
00287 source->refs++;
00288 INSIST(source->refs > 0);
00289 UNLOCK(&source->lock);
00290 *target = source;
00291 }
00292
00293 void
00294 isc_ratelimiter_detach(isc_ratelimiter_t **rlp) {
00295 isc_ratelimiter_t *rl;
00296 isc_boolean_t free_now = ISC_FALSE;
00297
00298 REQUIRE(rlp != NULL && *rlp != NULL);
00299
00300 rl = *rlp;
00301
00302 LOCK(&rl->lock);
00303 REQUIRE(rl->refs > 0);
00304 rl->refs--;
00305 if (rl->refs == 0)
00306 free_now = ISC_TRUE;
00307 UNLOCK(&rl->lock);
00308
00309 if (free_now)
00310 ratelimiter_free(rl);
00311
00312 *rlp = NULL;
00313 }
00314
00315 isc_result_t
00316 isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
00317 isc_result_t result = ISC_R_SUCCESS;
00318
00319 REQUIRE(rl != NULL);
00320
00321 LOCK(&rl->lock);
00322 switch (rl->state) {
00323 case isc_ratelimiter_shuttingdown:
00324 result = ISC_R_SHUTTINGDOWN;
00325 break;
00326 case isc_ratelimiter_ratelimited:
00327 result = isc_timer_reset(rl->timer, isc_timertype_inactive,
00328 NULL, NULL, ISC_FALSE);
00329 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00330
00331 case isc_ratelimiter_idle:
00332 case isc_ratelimiter_stalled:
00333 rl->state = isc_ratelimiter_stalled;
00334 break;
00335 }
00336 UNLOCK(&rl->lock);
00337 return (result);
00338 }
00339
00340 isc_result_t
00341 isc_ratelimiter_release(isc_ratelimiter_t *rl) {
00342 isc_result_t result = ISC_R_SUCCESS;
00343
00344 REQUIRE(rl != NULL);
00345
00346 LOCK(&rl->lock);
00347 switch (rl->state) {
00348 case isc_ratelimiter_shuttingdown:
00349 result = ISC_R_SHUTTINGDOWN;
00350 break;
00351 case isc_ratelimiter_stalled:
00352 if (!ISC_LIST_EMPTY(rl->pending)) {
00353 result = isc_timer_reset(rl->timer,
00354 isc_timertype_ticker, NULL,
00355 &rl->interval, ISC_FALSE);
00356 if (result == ISC_R_SUCCESS)
00357 rl->state = isc_ratelimiter_ratelimited;
00358 } else
00359 rl->state = isc_ratelimiter_idle;
00360 break;
00361 case isc_ratelimiter_ratelimited:
00362 case isc_ratelimiter_idle:
00363 break;
00364 }
00365 UNLOCK(&rl->lock);
00366 return (result);
00367 }