the rate limter now uses loop callbacks rather than task events.
the API for isc_ratelimiter_enqueue() has been changed; we now pass
in a loop, a callback function and a callback argument, and
receive back a rate limiter event object (isc_rlevent_t). it
is no longer necessary for the caller to allocate the event.
the callback argument needs to include a pointer to the rlevent
object so that it can be freed using isc_rlevent_free(), or by
dequeueing.
dns_tsigkey_t *key;
dns_transport_t *transport;
ISC_LINK(dns_notify_t) link;
- isc_event_t *event;
+ isc_rlevent_t *rlevent;
};
#define DNS_NOTIFY_NOSOA 0x0001U
dns_tsigkey_t *key;
dns_transport_t *transport;
ISC_LINK(dns_checkds_t) link;
- isc_event_t *event;
+ isc_rlevent_t *rlevent;
};
/*%
static void
queue_soa_query(dns_zone_t *zone);
static void
-soa_query(isc_task_t *, isc_event_t *);
+soa_query(void *arg);
static void
ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
static int
static void
checkds_done(isc_task_t *task, isc_event_t *event);
static void
-checkds_send_toaddr(isc_task_t *task, isc_event_t *event);
+checkds_send_toaddr(void *arg);
static void
notify_cancel(dns_zone_t *zone);
static void
static void
notify_done(isc_task_t *task, isc_event_t *event);
static void
-notify_send_toaddr(isc_task_t *task, isc_event_t *event);
+notify_send_toaddr(void *arg);
static isc_result_t
zone_dump(dns_zone_t *, bool);
static void
* not a startup notify, re-enqueue on the normal notify
* ratelimiter.
*/
- if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
+ if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
(notify->flags & DNS_NOTIFY_STARTUP) != 0)
{
zmgr = notify->zone->zmgr;
result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
- notify->event);
+ ¬ify->rlevent);
if (result != ISC_R_SUCCESS) {
return (true);
}
notify->flags &= ~DNS_NOTIFY_STARTUP;
- result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
- notify->zone->task,
- ¬ify->event);
+ result = isc_ratelimiter_enqueue(
+ notify->zone->zmgr->notifyrl, notify->zone->loop,
+ notify_send_toaddr, notify, ¬ify->rlevent);
if (result != ISC_R_SUCCESS) {
- isc_event_free(¬ify->event);
return (false);
}
}
static isc_result_t
notify_send_queue(dns_notify_t *notify, bool startup) {
- isc_event_t *e;
- isc_result_t result;
-
- INSIST(notify->event == NULL);
- e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
- notify_send_toaddr, notify, sizeof(isc_event_t));
- if (startup) {
- notify->event = e;
- }
- e->ev_arg = notify;
- e->ev_sender = NULL;
- result = isc_ratelimiter_enqueue(
+ return (isc_ratelimiter_enqueue(
startup ? notify->zone->zmgr->startupnotifyrl
: notify->zone->zmgr->notifyrl,
- notify->zone->task, &e);
- if (result != ISC_R_SUCCESS) {
- isc_event_free(&e);
- notify->event = NULL;
- }
- return (result);
+ notify->zone->loop, notify_send_toaddr, notify,
+ ¬ify->rlevent));
}
static void
-notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
- dns_notify_t *notify;
+notify_send_toaddr(void *arg) {
+ dns_notify_t *notify = (dns_notify_t *)arg;
isc_result_t result;
dns_message_t *message = NULL;
isc_netaddr_t dstip;
unsigned int options, timeout;
bool have_notifysource = false;
- notify = event->ev_arg;
REQUIRE(DNS_NOTIFY_VALID(notify));
- UNUSED(task);
-
LOCK_ZONE(notify->zone);
- notify->event = NULL;
-
- if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
- result = ISC_R_CANCELED;
- goto cleanup;
- }
-
- if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
+ if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0 ||
+ notify->rlevent->canceled ||
DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
{
dns_message_detach(&message);
cleanup:
UNLOCK_ZONE(notify->zone);
- isc_event_free(&event);
+ isc_rlevent_free(¬ify->rlevent);
if (result != ISC_R_SUCCESS) {
notify_destroy(notify, false);
}
return;
}
+struct soaquery {
+ dns_zone_t *zone;
+ isc_rlevent_t *rlevent;
+};
+
static void
queue_soa_query(dns_zone_t *zone) {
- isc_event_t *e;
- dns_zone_t *dummy = NULL;
isc_result_t result;
+ struct soaquery *sq = NULL;
ENTER;
/*
return;
}
- e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
- zone, sizeof(isc_event_t));
+ sq = isc_mem_get(zone->mctx, sizeof(*sq));
+ *sq = (struct soaquery){ .zone = NULL };
/*
- * Attach so that we won't clean up
- * until the event is delivered.
+ * Attach so that we won't clean up until the event is delivered.
*/
- zone_iattach(zone, &dummy);
-
- e->ev_arg = zone;
- e->ev_sender = NULL;
- result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
+ zone_iattach(zone, &sq->zone);
+ result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->loop,
+ soa_query, sq, &sq->rlevent);
if (result != ISC_R_SUCCESS) {
- zone_idetach(&dummy);
- isc_event_free(&e);
+ zone_idetach(&sq->zone);
+ isc_mem_put(zone->mctx, sq, sizeof(*sq));
cancel_refresh(zone);
}
}
static void
-soa_query(isc_task_t *task, isc_event_t *event) {
+soa_query(void *arg) {
+ struct soaquery *sq = (struct soaquery *)arg;
+ dns_zone_t *zone = sq->zone;
isc_result_t result = ISC_R_FAILURE;
dns_message_t *message = NULL;
- dns_zone_t *zone = event->ev_arg;
- dns_zone_t *dummy = NULL;
isc_netaddr_t primaryip;
dns_tsigkey_t *key = NULL;
dns_transport_t *transport = NULL;
REQUIRE(DNS_ZONE_VALID(zone));
- UNUSED(task);
-
ENTER;
LOCK_ZONE(zone);
- if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
- DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
+ if (sq->rlevent->canceled || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
zone->view->requestmgr == NULL)
{
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
}
}
- zone_iattach(zone, &dummy);
+ zone_iattach(zone, &(dns_zone_t *){ NULL });
timeout = 15;
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
timeout = 30;
NULL, NULL, options, key, timeout * 3, timeout, 2, zone->task,
refresh_callback, zone, &zone->request);
if (result != ISC_R_SUCCESS) {
- zone_idetach(&dummy);
+ zone_idetach(&(dns_zone_t *){ zone });
zone_debuglog(zone, __func__, 1,
"dns_request_create() failed: %s",
isc_result_totext(result));
if (cancel) {
cancel_refresh(zone);
}
- isc_event_free(&event);
UNLOCK_ZONE(zone);
if (do_queue_xfrin) {
queue_xfrin(zone);
}
+ isc_rlevent_free(&sq->rlevent);
+ isc_mem_put(zone->mctx, sq, sizeof(*sq));
dns_zone_idetach(&zone);
return;
static void
checkds_destroy(dns_checkds_t *checkds, bool locked) {
- isc_mem_t *mctx;
-
REQUIRE(DNS_CHECKDS_VALID(checkds));
dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
if (checkds->transport != NULL) {
dns_transport_detach(&checkds->transport);
}
- mctx = checkds->mctx;
- isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
- isc_mem_detach(&mctx);
+ INSIST(checkds->rlevent == NULL);
+ isc_mem_putanddetach(&checkds->mctx, checkds, sizeof(*checkds));
}
static isc_result_t
}
static void
-checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
- dns_checkds_t *checkds;
+checkds_send_toaddr(void *arg) {
+ dns_checkds_t *checkds = (dns_checkds_t *)arg;
isc_result_t result;
dns_message_t *message = NULL;
isc_netaddr_t dstip;
isc_sockaddr_t src;
unsigned int options, timeout;
bool have_checkdssource = false;
+ bool canceled = checkds->rlevent->canceled;
- checkds = event->ev_arg;
REQUIRE(DNS_CHECKDS_VALID(checkds));
- UNUSED(task);
+ isc_rlevent_free(&checkds->rlevent);
LOCK_ZONE(checkds->zone);
- checkds->event = NULL;
-
- if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
- result = ISC_R_CANCELED;
- goto cleanup;
- }
-
- if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
+ if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0 || canceled ||
DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
checkds->zone->view->requestmgr == NULL ||
checkds->zone->db == NULL)
dns_message_detach(&message);
cleanup:
UNLOCK_ZONE(checkds->zone);
- isc_event_free(&event);
if (result != ISC_R_SUCCESS) {
checkds_destroy(checkds, false);
}
}
-static isc_result_t
-checkds_send_queue(dns_checkds_t *checkds) {
- isc_event_t *e;
- isc_result_t result;
-
- INSIST(checkds->event == NULL);
- e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
- checkds_send_toaddr, checkds,
- sizeof(isc_event_t));
- e->ev_arg = checkds;
- e->ev_sender = NULL;
- result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
- checkds->zone->task, &e);
- if (result != ISC_R_SUCCESS) {
- isc_event_free(&e);
- checkds->event = NULL;
- }
- return (result);
-}
-
static void
checkds_send(dns_zone_t *zone) {
dns_view_t *view = dns_zone_getview(zone);
}
ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
- result = checkds_send_queue(checkds);
+ result = isc_ratelimiter_enqueue(
+ checkds->zone->zmgr->checkdsrl, checkds->zone->loop,
+ checkds_send_toaddr, checkds, &checkds->rlevent);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_DEBUG(3),
"checkds: send DS query to "
#include <isc/time.h>
#include <isc/types.h>
+struct isc_rlevent {
+ isc_loop_t *loop;
+ isc_ratelimiter_t *rl;
+ bool canceled;
+ isc_job_cb cb;
+ void *arg;
+ ISC_LINK(isc_rlevent_t) link;
+};
+
ISC_LANG_BEGINDECLS
/*****
*/
void
-isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval);
+isc_ratelimiter_setinterval(isc_ratelimiter_t *restrict rl,
+ const isc_interval_t *const interval);
/*!<
* Set the minimum interval between event executions.
* The interval value is copied, so the caller need not preserve it.
*/
void
-isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, uint32_t perint);
+isc_ratelimiter_setpertic(isc_ratelimiter_t *restrict rl,
+ const uint32_t perint);
/*%<
* Set the number of events processed per interval timer tick.
* If 'perint' is zero it is treated as 1.
*/
void
-isc_ratelimiter_setpushpop(isc_ratelimiter_t *rl, bool pushpop);
+isc_ratelimiter_setpushpop(isc_ratelimiter_t *restrict rl, const bool pushpop);
/*%<
* Set / clear the ratelimiter to from push pop mode rather
* first in - first out mode (default).
*/
isc_result_t
-isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
- isc_event_t **eventp);
+isc_ratelimiter_enqueue(isc_ratelimiter_t *restrict rl,
+ isc_loop_t *restrict loop, isc_job_cb cb, void *arg,
+ isc_rlevent_t **rlep);
/*%<
* Queue an event for rate-limited execution.
*
- * This is similar
- * to doing an isc_task_send() to the 'task', except that the
- * execution may be delayed to achieve the desired rate of
+ * This is similar to doing an isc_async_run() to the 'loop', except
+ * that the execution may be delayed to achieve the desired rate of
* execution.
*
- * '(*eventp)->ev_sender' is used to hold the task. The caller
- * must ensure that the task exists until the event is delivered.
+ * '*rlep' will be set to point to an allocated ratelimiter event,
+ * which can be freed by the caller using isc_rlevent_free() when the
+ * event fires, or by dequeueing.
*
* Requires:
- *\li An interval has been set by calling
- * isc_ratelimiter_setinterval().
- *
- *\li 'task' to be non NULL.
- *\li '(*eventp)->ev_sender' to be NULL.
+ *\li 'rl' is a valid ratelimiter.
+ *\li 'loop ' is non NULL.
+ *\li 'rlep' is non NULL and '*rlep' is NULL.
*/
isc_result_t
-isc_ratelimiter_dequeue(isc_ratelimiter_t *rl, isc_event_t *event);
+isc_ratelimiter_dequeue(isc_ratelimiter_t *restrict rl,
+ isc_rlevent_t **rleventp);
/*
- * Dequeue a event off the ratelimiter queue.
+ * Dequeue a event off the ratelimiter queue. If the event has not already
+ * been posted, it will be freed and '*rleventp' will be set to NULL.
*
* Returns:
* \li ISC_R_NOTFOUND if the event is no longer linked to the rate limiter.
*/
void
-isc_ratelimiter_shutdown(isc_ratelimiter_t *ratelimiter);
+isc_ratelimiter_shutdown(isc_ratelimiter_t *restrict rl);
/*%<
* Shut down a rate limiter.
*
* Ensures:
- *\li All events that have not yet been
- * dispatched to the task are dispatched immediately with
- * the #ISC_EVENTATTR_CANCELED bit set in ev_attributes.
+ *\li All pending events are dispatched immediately with
+ * rle->canceled set to true.
*
*\li Further attempts to enqueue events will fail with
* #ISC_R_SHUTTINGDOWN.
- *
- *\li The rate limiter is no longer attached to its task.
+ */
+
+void
+isc_rlevent_free(isc_rlevent_t **rlep);
+/*%<
+ * Free the rate limiter event '*rlep'.
*/
ISC_REFCOUNT_DECL(isc_ratelimiter);
typedef struct isc_quota isc_quota_t; /*%< Quota */
typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */
typedef struct isc_region isc_region_t; /*%< Region */
+typedef struct isc_rlevent isc_rlevent_t; /*%< Rate Limiter Event */
typedef struct isc_signal isc_signal_t; /*%< Signal handler */
typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */
typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List
#include <stdbool.h>
#include <isc/async.h>
-#include <isc/event.h>
#include <isc/loop.h>
#include <isc/magic.h>
#include <isc/mem.h>
uint32_t pertic;
bool pushpop;
isc_ratelimiter_state_t state;
- ISC_LIST(isc_event_t) pending;
+ ISC_LIST(isc_rlevent_t) pending;
};
static void
}
void
-isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
+isc_ratelimiter_setinterval(isc_ratelimiter_t *restrict rl,
+ const isc_interval_t *const interval) {
REQUIRE(VALID_RATELIMITER(rl));
REQUIRE(interval != NULL);
}
void
-isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, uint32_t pertic) {
+isc_ratelimiter_setpertic(isc_ratelimiter_t *restrict rl,
+ const uint32_t pertic) {
REQUIRE(VALID_RATELIMITER(rl));
REQUIRE(pertic > 0);
}
void
-isc_ratelimiter_setpushpop(isc_ratelimiter_t *rl, bool pushpop) {
+isc_ratelimiter_setpushpop(isc_ratelimiter_t *restrict rl, const bool pushpop) {
REQUIRE(VALID_RATELIMITER(rl));
LOCK(&rl->lock);
}
isc_result_t
-isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
- isc_event_t **eventp) {
+isc_ratelimiter_enqueue(isc_ratelimiter_t *restrict rl,
+ isc_loop_t *restrict loop, isc_job_cb cb, void *arg,
+ isc_rlevent_t **rlep) {
isc_result_t result = ISC_R_SUCCESS;
- isc_event_t *event;
+ isc_rlevent_t *rle = NULL;
REQUIRE(VALID_RATELIMITER(rl));
- REQUIRE(task != NULL);
- REQUIRE(eventp != NULL && *eventp != NULL);
- event = *eventp;
- REQUIRE(event->ev_sender == NULL);
+ REQUIRE(loop != NULL);
+ REQUIRE(rlep != NULL && *rlep == NULL);
LOCK(&rl->lock);
switch (rl->state) {
rl->state = isc_ratelimiter_ratelimited;
FALLTHROUGH;
case isc_ratelimiter_ratelimited:
- event->ev_sender = task;
- *eventp = NULL;
+ rle = isc_mem_get(isc_loop_getmctx(loop), sizeof(*rle));
+ *rle = (isc_rlevent_t){
+ .cb = cb,
+ .arg = arg,
+ .link = ISC_LINK_INITIALIZER,
+ };
+ isc_loop_attach(loop, &rle->loop);
+ isc_ratelimiter_attach(rl, &rle->rl);
+
if (rl->pushpop) {
- ISC_LIST_PREPEND(rl->pending, event, ev_ratelink);
+ ISC_LIST_PREPEND(rl->pending, rle, link);
} else {
- ISC_LIST_APPEND(rl->pending, event, ev_ratelink);
+ ISC_LIST_APPEND(rl->pending, rle, link);
}
+ *rlep = rle;
break;
default:
UNREACHABLE();
}
isc_result_t
-isc_ratelimiter_dequeue(isc_ratelimiter_t *rl, isc_event_t *event) {
+isc_ratelimiter_dequeue(isc_ratelimiter_t *restrict rl, isc_rlevent_t **rlep) {
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(rl != NULL);
- REQUIRE(event != NULL);
+ REQUIRE(rlep != NULL);
LOCK(&rl->lock);
- if (ISC_LINK_LINKED(event, ev_ratelink)) {
- ISC_LIST_UNLINK(rl->pending, event, ev_ratelink);
- event->ev_sender = NULL;
+ if (ISC_LINK_LINKED(*rlep, link)) {
+ ISC_LIST_UNLINK(rl->pending, *rlep, link);
+ isc_rlevent_free(rlep);
} else {
result = ISC_R_NOTFOUND;
}
UNLOCK(&rl->lock);
-
return (result);
}
static void
isc__ratelimiter_tick(void *arg) {
isc_ratelimiter_t *rl = (isc_ratelimiter_t *)arg;
- isc_event_t *event;
+ isc_rlevent_t *rle = NULL;
uint32_t pertic;
- ISC_LIST(isc_event_t) pending;
+ ISC_LIST(isc_rlevent_t) pending;
REQUIRE(VALID_RATELIMITER(rl));
pertic = rl->pertic;
while (pertic != 0) {
- event = ISC_LIST_HEAD(rl->pending);
- if (event != NULL) {
+ rle = ISC_LIST_HEAD(rl->pending);
+ if (rle != NULL) {
/* There is work to do. Let's do it after unlocking. */
- ISC_LIST_UNLINK(rl->pending, event, ev_ratelink);
- ISC_LIST_APPEND(pending, event, ev_ratelink);
+ ISC_LIST_UNLINK(rl->pending, rle, link);
+ ISC_LIST_APPEND(pending, rle, link);
} else {
/*
* We processed all the scheduled work, but there's a
unlock:
UNLOCK(&rl->lock);
- while ((event = ISC_LIST_HEAD(pending)) != NULL) {
- ISC_LIST_UNLINK(pending, event, ev_ratelink);
- isc_task_send(event->ev_sender, &event);
+ while ((rle = ISC_LIST_HEAD(pending)) != NULL) {
+ ISC_LIST_UNLINK(pending, rle, link);
+ isc_async_run(rle->loop, rle->cb, rle->arg);
}
}
}
void
-isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
- isc_event_t *event;
- ISC_LIST(isc_event_t) pending;
+isc_ratelimiter_shutdown(isc_ratelimiter_t *restrict rl) {
+ isc_rlevent_t *rle = NULL;
+ ISC_LIST(isc_rlevent_t) pending;
REQUIRE(VALID_RATELIMITER(rl));
}
UNLOCK(&rl->lock);
- while ((event = ISC_LIST_HEAD(pending)) != NULL) {
- ISC_LIST_UNLINK(pending, event, ev_ratelink);
- event->ev_attributes |= ISC_EVENTATTR_CANCELED;
- isc_task_send(event->ev_sender, &event);
+ while ((rle = ISC_LIST_HEAD(pending)) != NULL) {
+ ISC_LIST_UNLINK(pending, rle, link);
+ rle->canceled = true;
+ isc_async_run(rl->loop, rle->cb, rle->arg);
}
}
static void
-ratelimiter_destroy(isc_ratelimiter_t *rl) {
+ratelimiter_destroy(isc_ratelimiter_t *restrict rl) {
isc_refcount_destroy(&rl->references);
LOCK(&rl->lock);
isc_mem_putanddetach(&rl->mctx, rl, sizeof(*rl));
}
+void
+isc_rlevent_free(isc_rlevent_t **rlep) {
+ REQUIRE(rlep != NULL && *rlep != NULL);
+
+ isc_rlevent_t *rle = *rlep;
+ isc_mem_t *mctx = isc_loop_getmctx(rle->loop);
+
+ *rlep = NULL;
+
+ isc_loop_detach(&rle->loop);
+ isc_ratelimiter_detach(&rle->rl);
+ isc_mem_put(mctx, rle, sizeof(*rle));
+}
+
ISC_REFCOUNT_IMPL(isc_ratelimiter, ratelimiter_destroy);
isc_ratelimiter_t *rl = NULL;
+typedef struct rlstat {
+ isc_rlevent_t *event;
+} rlstat_t;
+
ISC_LOOP_TEST_IMPL(ratelimiter_create) {
- rl = NULL;
+ assert_null(rl);
expect_assert_failure(isc_ratelimiter_create(NULL, &rl));
expect_assert_failure(isc_ratelimiter_create(mainloop, NULL));
- rl = (isc_ratelimiter_t *)&rl;
- expect_assert_failure(isc_ratelimiter_create(mainloop, &rl));
+ assert_null(rl);
- rl = NULL;
isc_ratelimiter_create(mainloop, &rl);
isc_ratelimiter_shutdown(rl);
-
isc_ratelimiter_detach(&rl);
isc_loopmgr_shutdown(loopmgr);
}
ISC_LOOP_TEST_IMPL(ratelimiter_shutdown) {
- rl = NULL;
-
+ assert_null(rl);
expect_assert_failure(isc_ratelimiter_shutdown(NULL));
expect_assert_failure(isc_ratelimiter_shutdown(rl));
}
ISC_LOOP_TEST_IMPL(ratelimiter_detach) {
- rl = NULL;
+ assert_null(rl);
expect_assert_failure(isc_ratelimiter_detach(NULL));
expect_assert_failure(isc_ratelimiter_detach(&rl));
}
static int ticks = 0;
-static isc_task_t *rl_task = NULL;
static isc_time_t start_time;
static isc_time_t tick_time;
static void
-tick(isc_task_t *task, isc_event_t *event) {
- assert_ptr_equal(task, rl_task);
- isc_event_free(&event);
+tick(void *arg) {
+ rlstat_t *rlstat = (rlstat_t *)arg;
+
+ isc_rlevent_free(&rlstat->event);
+ isc_mem_put(mctx, rlstat, sizeof(*rlstat));
ticks++;
assert_int_equal(isc_time_now(&tick_time), ISC_R_SUCCESS);
- isc_loopmgr_shutdown(loopmgr);
-
- isc_task_detach(&rl_task);
isc_ratelimiter_shutdown(rl);
isc_ratelimiter_detach(&rl);
+
+ isc_loopmgr_shutdown(loopmgr);
}
ISC_LOOP_SETUP_IMPL(ratelimiter_common) {
- isc_result_t result = isc_task_create(taskmgr, &rl_task, 0);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- rl = NULL;
+ assert_null(rl);
isc_time_set(&tick_time, 0, 0);
assert_int_equal(isc_time_now(&start_time), ISC_R_SUCCESS);
isc_ratelimiter_create(mainloop, &rl);
ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(ratelimiter_enqueue) {
isc_result_t result;
- isc_event_t *event = NULL;
+ rlstat_t *rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
-
- result = isc_ratelimiter_enqueue(rl, rl_task, &event);
+ result = isc_ratelimiter_enqueue(rl, mainloop, tick, rlstat,
+ &rlstat->event);
assert_int_equal(result, ISC_R_SUCCESS);
+ assert_non_null(rlstat->event);
}
ISC_LOOP_SETUP_IMPL(ratelimiter_enqueue_shutdown) {
}
ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(ratelimiter_enqueue_shutdown) {
- isc_event_t *event = NULL;
-
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
+ rlstat_t *rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ isc_rlevent_t *event = NULL;
- expect_assert_failure(isc_ratelimiter_enqueue(NULL, rl_task, &event));
- expect_assert_failure(isc_ratelimiter_enqueue(rl, NULL, &event));
- expect_assert_failure(isc_ratelimiter_enqueue(rl, rl_task, NULL));
expect_assert_failure(
- isc_ratelimiter_enqueue(rl, rl_task, &(isc_event_t *){ NULL }));
+ isc_ratelimiter_enqueue(NULL, mainloop, tick, NULL, &event));
+ expect_assert_failure(
+ isc_ratelimiter_enqueue(rl, NULL, tick, NULL, &event));
+ expect_assert_failure(
+ isc_ratelimiter_enqueue(rl, mainloop, tick, NULL, NULL));
- assert_int_equal(isc_ratelimiter_enqueue(rl, rl_task, &event),
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tick, rlstat,
+ &rlstat->event),
ISC_R_SUCCESS);
+ assert_non_null(rlstat->event);
isc_ratelimiter_shutdown(rl);
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
-
- assert_int_equal(isc_ratelimiter_enqueue(rl, rl_task, &event),
- ISC_R_SHUTTINGDOWN);
-
- isc_event_free(&event);
+ assert_int_equal(
+ isc_ratelimiter_enqueue(rl, mainloop, tick, NULL, &event),
+ ISC_R_SHUTTINGDOWN);
+ assert_null(event);
}
ISC_LOOP_SETUP_IMPL(ratelimiter_dequeue) {
}
ISC_LOOP_TEARDOWN_IMPL(ratelimiter_dequeue) { /* */
- assert_int_equal(ticks, 1);
+ assert_int_equal(ticks, 0);
}
ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(ratelimiter_dequeue) {
- isc_event_t *event = NULL;
+ rlstat_t *rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ isc_rlevent_t *fake = isc_mem_get(mctx, sizeof(*fake));
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
- assert_int_equal(
- isc_ratelimiter_enqueue(rl, rl_task, &(isc_event_t *){ event }),
- ISC_R_SUCCESS);
- assert_int_equal(isc_ratelimiter_dequeue(rl, event), ISC_R_SUCCESS);
- isc_event_free(&event);
- assert_null(event);
-
- /* This event didn't get scheduled */
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
- assert_int_equal(isc_ratelimiter_dequeue(rl, event), ISC_R_NOTFOUND);
- assert_int_equal(isc_ratelimiter_enqueue(rl, rl_task, &event),
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tick, rlstat,
+ &rlstat->event),
ISC_R_SUCCESS);
- assert_null(event);
+ assert_int_equal(isc_ratelimiter_dequeue(rl, &rlstat->event),
+ ISC_R_SUCCESS);
+ isc_mem_put(mctx, rlstat, sizeof(*rlstat));
+
+ /* Set up a mock ratelimiter event that isn't actually scheduled */
+ *fake = (isc_rlevent_t){ .link = ISC_LINK_INITIALIZER };
+ isc_loop_attach(mainloop, &fake->loop);
+ isc_ratelimiter_attach(rl, &fake->rl);
+ assert_int_equal(isc_ratelimiter_dequeue(rl, &fake), ISC_R_NOTFOUND);
+ isc_loop_detach(&fake->loop);
+ isc_ratelimiter_detach(&fake->rl);
+ isc_mem_put(mctx, fake, sizeof(*fake));
+
+ isc_ratelimiter_shutdown(rl);
+ isc_ratelimiter_detach(&rl);
+
+ isc_loopmgr_shutdown(loopmgr);
}
static isc_time_t tock_time;
static void
-tock(isc_task_t *task, isc_event_t *event) {
- assert_ptr_equal(task, rl_task);
- isc_event_free(&event);
+tock(void *arg) {
+ rlstat_t *rlstat = (rlstat_t *)arg;
+
+ isc_rlevent_free(&rlstat->event);
+ isc_mem_put(mctx, rlstat, sizeof(*rlstat));
ticks++;
assert_int_equal(isc_time_now(&tock_time), ISC_R_SUCCESS);
}
ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(ratelimiter_pertick_interval) {
- isc_event_t *event = NULL;
+ rlstat_t *rlstat = NULL;
isc_interval_t interval;
isc_interval_set(&interval, 1, NS_PER_SEC / 10);
isc_ratelimiter_setpertic(rl, 1);
isc_ratelimiter_setpushpop(rl, false);
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tock, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
-
- assert_int_equal(isc_ratelimiter_enqueue(rl, rl_task, &event),
+ rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tock, rlstat,
+ &rlstat->event),
ISC_R_SUCCESS);
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
-
- assert_int_equal(isc_ratelimiter_enqueue(rl, rl_task, &event),
+ rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tick, rlstat,
+ &rlstat->event),
ISC_R_SUCCESS);
}
}
ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(ratelimiter_pushpop) {
- isc_event_t *event = NULL;
+ rlstat_t *rlstat = NULL;
isc_interval_t interval;
isc_interval_set(&interval, 1, NS_PER_SEC / 10);
isc_ratelimiter_setpertic(rl, 2);
isc_ratelimiter_setpushpop(rl, true);
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tick, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
-
- assert_int_equal(
- isc_ratelimiter_enqueue(rl, rl_task, &(isc_event_t *){ event }),
- ISC_R_SUCCESS);
-
- event = isc_event_allocate(mctx, NULL, ISC_TASKEVENT_TEST, tock, NULL,
- sizeof(isc_event_t));
- assert_non_null(event);
+ rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tock, rlstat,
+ &rlstat->event),
+ ISC_R_SUCCESS);
- assert_int_equal(
- isc_ratelimiter_enqueue(rl, rl_task, &(isc_event_t *){ event }),
- ISC_R_SUCCESS);
+ rlstat = isc_mem_getx(mctx, sizeof(*rlstat), ISC_MEM_ZERO);
+ assert_int_equal(isc_ratelimiter_enqueue(rl, mainloop, tick, rlstat,
+ &rlstat->event),
+ ISC_R_SUCCESS);
}
static int