Update extensions to add/remove persistent event based on request count

This commit is contained in:
Neel Goyal 2014-02-21 18:42:04 -05:00
parent 91daf87f4b
commit deade2b8bb
12 changed files with 146 additions and 48 deletions

View File

@ -98,7 +98,7 @@ install: libgetdns.la
uninstall:
rm -rf $(DESTDIR)$(includedir)/getdns
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libgetdns.la $(EXTENSION_LIBEVENT_LIB) $(EXTENSION_LIBUV_LIB) $(EXTENSION_LIBEV_LIB)
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libgetdns.la $(DESTDIR)$(libdir)/$(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir)/$(EXTENSION_LIBUV_LIB) $(DESTDIR)$(libdir)/$(EXTENSION_LIBEV_LIB)
libgetdns_ext_event.la: libgetdns.la extension/libevent.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ extension/libevent.lo ./.libs/libgetdns.la $(EXTENSION_LDFLAGS) $(EXTENSION_LIBEVENT_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined

View File

@ -1183,15 +1183,14 @@ getdns_context_cancel_request(struct getdns_context *context,
cb = req->user_callback;
user_pointer = req->user_pointer;
/* clean up */
GETDNS_FREE(context->my_mf, node);
dns_req_free(req);
/* fire callback */
cb(context,
GETDNS_CALLBACK_CANCEL,
NULL, user_pointer, transaction_id);
}
/* clean up */
GETDNS_FREE(context->my_mf, node);
dns_req_free(req);
return GETDNS_RETURN_GOOD;
}
@ -1204,7 +1203,12 @@ getdns_cancel_callback(struct getdns_context *context,
getdns_transaction_t transaction_id)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
return getdns_context_cancel_request(context, transaction_id, 1);
getdns_return_t r = getdns_context_cancel_request(context, transaction_id, 1);
if (context->extension) {
context->extension->request_count_changed(context,
context->outbound_requests->count, context->extension_data);
}
return r;
} /* getdns_cancel_callback */
static getdns_return_t
@ -1384,6 +1388,10 @@ getdns_context_track_outbound_request(getdns_dns_req * req)
GETDNS_FREE(context->my_mf, node);
return GETDNS_RETURN_GENERIC_ERROR;
}
if (context->extension) {
context->extension->request_count_changed(context,
context->outbound_requests->count, context->extension_data);
}
return GETDNS_RETURN_GOOD;
}
@ -1454,11 +1462,11 @@ int getdns_context_fd(struct getdns_context* context) {
return ub_fd(context->unbound_ctx);
}
int
uint32_t
getdns_context_get_num_pending_requests(struct getdns_context* context,
struct timeval* next_timeout) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
int r = context->outbound_requests->count;
uint32_t r = context->outbound_requests->count;
if (r > 0) {
if (!context->extension && next_timeout) {
/* default is 1 second */
@ -1697,6 +1705,12 @@ getdns_context_clear_timeout(struct getdns_context* context,
return GETDNS_RETURN_GOOD;
}
void*
getdns_context_get_extension_data(struct getdns_context* context) {
RETURN_IF_NULL(context, NULL);
return context->extension_data;
}
static inline getdns_return_t
priv_dict_set_list_if_not_null(getdns_dict* dict,
const char* name, getdns_list* list) {

View File

@ -46,20 +46,45 @@ struct getdns_libev_data {
struct ev_io* poll_handle;
};
/* lib event callbacks */
static void
request_count_changed(uint32_t request_count, struct getdns_libev_data *ev_data) {
if (request_count > 0) {
ev_io_start(ev_data->loop, ev_data->poll_handle);
} else {
ev_io_stop(ev_data->loop, ev_data->poll_handle);
}
}
/* lib ev callbacks */
static void
getdns_libev_cb(struct ev_loop *loop, struct ev_io *handle, int revents) {
struct getdns_context* context = (struct getdns_context*) handle->data;
getdns_context_process_async(context);
uint32_t rc = getdns_context_get_num_pending_requests(context, NULL);
struct getdns_libev_data* ev_data =
(struct getdns_libev_data*) getdns_context_get_extension_data(context);
request_count_changed(rc, ev_data);
}
static void
getdns_libev_timeout_cb(struct ev_loop *loop, struct ev_timer* handle, int status) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) handle->data;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct getdns_libev_data* ev_data =
(struct getdns_libev_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, ev_data);
}
/* getdns extension functions */
static getdns_return_t
getdns_libev_request_count_changed(struct getdns_context* context,
uint32_t request_count, void* eventloop_data) {
struct getdns_libev_data *ev_data = (struct getdns_libev_data*) eventloop_data;
request_count_changed(request_count, ev_data);
return GETDNS_RETURN_GOOD;
}
static getdns_return_t
getdns_libev_cleanup(struct getdns_context* context, void* data) {
struct getdns_libev_data *ev_data = (struct getdns_libev_data*) data;
@ -102,7 +127,8 @@ getdns_libev_clear_timeout(struct getdns_context* context,
static getdns_eventloop_extension LIBEV_EXT = {
getdns_libev_cleanup,
getdns_libev_schedule_timeout,
getdns_libev_clear_timeout
getdns_libev_clear_timeout,
getdns_libev_request_count_changed
};
/*
@ -129,7 +155,6 @@ getdns_extension_set_libev_loop(struct getdns_context *context,
ev_io_init(ev_data->poll_handle, getdns_libev_cb, fd, EV_READ);
ev_data->loop = loop;
ev_io_start(ev_data->loop, ev_data->poll_handle);
ev_data->poll_handle->data = context;
return getdns_extension_set_eventloop(context, &LIBEV_EXT, ev_data);
} /* getdns_extension_set_libev_loop */

View File

@ -72,20 +72,45 @@ struct event_data {
struct event_base* event_base;
};
static void
request_count_changed(uint32_t request_count, struct event_data *ev_data) {
if (request_count > 0) {
event_add(ev_data->event, NULL);
} else {
event_del(ev_data->event);
}
}
/* lib event callbacks */
static void
getdns_libevent_cb(evutil_socket_t fd, short what, void *userarg) {
struct getdns_context* context = (struct getdns_context*) userarg;
getdns_context_process_async(context);
uint32_t rc = getdns_context_get_num_pending_requests(context, NULL);
struct event_data* ev_data =
(struct event_data*) getdns_context_get_extension_data(context);
request_count_changed(rc, ev_data);
}
static void
getdns_libevent_timeout_cb(evutil_socket_t fd, short what, void* userarg) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) userarg;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct event_data* ev_data =
(struct event_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, ev_data);
}
/* getdns extension functions */
static getdns_return_t
getdns_libevent_request_count_changed(struct getdns_context* context,
uint32_t request_count, void* eventloop_data) {
struct event_data *edata = (struct event_data*) eventloop_data;
request_count_changed(request_count, edata);
return GETDNS_RETURN_GOOD;
}
static getdns_return_t
getdns_libevent_cleanup(struct getdns_context* context, void* data) {
struct event_data *edata = (struct event_data*) data;
@ -128,7 +153,8 @@ getdns_libevent_clear_timeout(struct getdns_context* context,
static getdns_eventloop_extension LIBEVENT_EXT = {
getdns_libevent_cleanup,
getdns_libevent_schedule_timeout,
getdns_libevent_clear_timeout
getdns_libevent_clear_timeout,
getdns_libevent_request_count_changed
};
/*
@ -151,7 +177,6 @@ getdns_extension_set_libevent_base(struct getdns_context *context,
if (!getdns_event) {
return GETDNS_RETURN_GENERIC_ERROR;
}
event_add(getdns_event, NULL);
/* TODO: use context functs? */
struct event_data* ev_data = (struct event_data*) malloc(sizeof(struct event_data));
@ -163,6 +188,5 @@ getdns_extension_set_libevent_base(struct getdns_context *context,
}
ev_data->event = getdns_event;
ev_data->event_base = this_event_base;
return getdns_extension_set_eventloop(context, &LIBEVENT_EXT, ev_data);
} /* getdns_extension_set_libevent_base */

View File

@ -44,19 +44,41 @@
struct getdns_libuv_data {
uv_loop_t* loop;
uv_poll_t* poll_handle;
uint8_t polling;
};
static void request_count_changed(uint32_t request_count, struct getdns_libuv_data *uv_data);
/* lib event callbacks */
static void
getdns_libuv_cb(uv_poll_t* handle, int status, int events) {
struct getdns_context* context = (struct getdns_context*) handle->data;
getdns_context_process_async(context);
uint32_t rc = getdns_context_get_num_pending_requests(context, NULL);
struct getdns_libuv_data* uv_data =
(struct getdns_libuv_data*) getdns_context_get_extension_data(context);
request_count_changed(rc, uv_data);
}
static void
request_count_changed(uint32_t request_count, struct getdns_libuv_data *uv_data) {
if (request_count > 0 && uv_data->polling == 0) {
uv_poll_start(uv_data->poll_handle, UV_READABLE, getdns_libuv_cb);
uv_data->polling = 1;
} else if (request_count == 0 && uv_data->polling == 1) {
uv_poll_stop(uv_data->poll_handle);
uv_data->polling = 0;
}
}
static void
getdns_libuv_timeout_cb(uv_timer_t* handle, int status) {
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) handle->data;
timeout_data->callback(timeout_data->userarg);
uint32_t rc = getdns_context_get_num_pending_requests(timeout_data->context, NULL);
struct getdns_libuv_data* uv_data =
(struct getdns_libuv_data*) getdns_context_get_extension_data(timeout_data->context);
request_count_changed(rc, uv_data);
}
static void
@ -67,6 +89,14 @@ getdns_libuv_close_cb(uv_handle_t* handle) {
}
/* getdns extension functions */
static getdns_return_t
getdns_libuv_request_count_changed(struct getdns_context* context,
uint32_t request_count, void* eventloop_data) {
struct getdns_libuv_data *edata = (struct getdns_libuv_data*) eventloop_data;
request_count_changed(request_count, edata);
return GETDNS_RETURN_GOOD;
}
static getdns_return_t
getdns_libuv_cleanup(struct getdns_context* context, void* data) {
struct getdns_libuv_data *uv_data = (struct getdns_libuv_data*) data;
@ -108,7 +138,8 @@ getdns_libuv_clear_timeout(struct getdns_context* context,
static getdns_eventloop_extension LIBUV_EXT = {
getdns_libuv_cleanup,
getdns_libuv_schedule_timeout,
getdns_libuv_clear_timeout
getdns_libuv_clear_timeout,
getdns_libuv_request_count_changed
};
/*
@ -135,7 +166,6 @@ getdns_extension_set_libuv_loop(struct getdns_context *context,
uv_poll_init(uv_loop, uv_data->poll_handle, fd);
uv_data->poll_handle->data = context;
uv_data->loop = uv_loop;
uv_poll_start(uv_data->poll_handle, UV_READABLE, getdns_libuv_cb);
uv_data->polling = 0;
return getdns_extension_set_eventloop(context, &LIBUV_EXT, uv_data);
} /* getdns_extension_set_libuv_loop */

View File

@ -74,12 +74,9 @@ ub_resolve_timeout(void *arg)
getdns_callback_t cb = dns_req->user_callback;
void *user_arg = dns_req->user_pointer;
/* cancel the req - also clears it from outbound */
/* cancel the req - also clears it from outbound and cleans up*/
getdns_context_cancel_request(context, trans_id, 0);
/* cleanup */
dns_req_free(dns_req);
cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id);
}

View File

@ -1009,16 +1009,6 @@ getdns_context_set_extended_memory_functions(getdns_context *context,
getdns_dict*
getdns_context_get_api_information(getdns_context* context);
/* Async support */
struct timeval;
int getdns_context_get_num_pending_requests(getdns_context* context, struct timeval* next_timeout);
/* get the fd */
int getdns_context_fd(getdns_context* context);
/* process async reqs */
getdns_return_t getdns_context_process_async(getdns_context* context);
/* Get root trust anchor */
getdns_list *getdns_root_trust_anchor(time_t *utc_date_of_anchor);

View File

@ -42,12 +42,12 @@ getdns_return_t getdns_context_set_return_dnssec_status(getdns_context* context,
getdns_return_t getdns_dict_util_set_string(struct getdns_dict * dict, char *name,
const char *value);
/* get a string from a dict. result is valid as long as dict is valid */
/* get a string from a dict. the result must be freed if valid */
getdns_return_t getdns_dict_util_get_string(struct getdns_dict * dict, char *name,
char **result);
/* Async support */
int getdns_context_get_num_pending_requests(getdns_context* context, struct timeval* next_timeout);
uint32_t getdns_context_get_num_pending_requests(getdns_context* context, struct timeval* next_timeout);
/* get the fd */
int getdns_context_fd(getdns_context* context);
@ -61,33 +61,57 @@ typedef void (*getdns_timeout_callback) (void* userarg);
/* context timeout data */
typedef struct getdns_timeout_data {
/* a timeout id */
getdns_transaction_t transaction_id;
/* the absolute time of the timeout */
struct timeval timeout_time;
/* the timeout callback to fire */
getdns_timeout_callback callback;
/* timeout callback user arg */
void* userarg;
/* pointer to the underlying extension pointer that the extension
will create and free */
void* extension_timer;
/* context */
struct getdns_context* context;
} getdns_timeout_data_t;
/* call the extension when the data needs to be cleaned up */
typedef getdns_return_t (*getdns_eventloop_cleanup_t)(struct getdns_context* context, void* eventloop_data);
/* call the extension to schedule a timer. Any timer data that needs to be tracked should be
stored in eventloop_timer */
typedef getdns_return_t (*getdns_eventloop_schedule_timeout_t)(struct getdns_context* context,
void* eventloop_data, uint16_t timeout,
getdns_timeout_data_t* timeout_data,
void** eventloop_timer);
/* call the extension to free a timer. The timer passed in is the same as that returned in
the schedule timeout */
typedef getdns_return_t (*getdns_eventloop_clear_timeout_t)(struct getdns_context* context,
void* eventloop_data, void* eventloop_timer);
/* call the extension to tell it that the number of outbound requests changed. This is called
when an async request is submitted or canceled by the user */
typedef getdns_return_t (*getdns_eventloop_request_count_changed_t)(struct getdns_context* context,
uint32_t request_count, void* eventloop_data);
typedef struct getdns_eventloop_extension {
getdns_eventloop_cleanup_t cleanup_data;
getdns_eventloop_schedule_timeout_t schedule_timeout;
getdns_eventloop_clear_timeout_t clear_timeout;
getdns_eventloop_request_count_changed_t request_count_changed;
} getdns_eventloop_extension;
/* extension stuff */
getdns_return_t getdns_extension_set_eventloop(struct getdns_context* context,
/* set an event loop extension on the context */
getdns_return_t
getdns_extension_set_eventloop(struct getdns_context* context,
getdns_eventloop_extension* extension, void* extension_data);
void*
getdns_context_get_extension_data(struct getdns_context* context);
/* detach the eventloop from the context */
getdns_return_t
getdns_extension_detach_eventloop(struct getdns_context* context);

View File

@ -82,16 +82,16 @@ check_getdns_common: check_getdns_common.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_common.o
check_getdns: check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_selectloop.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_selectloop.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -lpthread -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_selectloop.o
check_getdns_event: check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libevent.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lgetdns_ext_event $(EXTENSION_LIBEVENT_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libevent.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lpthread -lgetdns_ext_event $(EXTENSION_LIBEVENT_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libevent.o
check_getdns_uv: check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libuv.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lgetdns_ext_uv $(EXTENSION_LIBUV_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libuv.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lpthread -lgetdns_ext_uv $(EXTENSION_LIBUV_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libuv.o
check_getdns_ev: check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libev.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lgetdns_ext_ev $(EXTENSION_LIBEV_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libev.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lpthread -lgetdns_ext_ev $(EXTENSION_LIBEV_EXT_LIBS) $(LDLIBS) -o $@ check_getdns.o check_getdns_common.o check_getdns_context_set_timeout.o check_getdns_libev.o
tests_dnssec: tests_dnssec.o testmessages.o
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -lgetdns_ext_event $(LDLIBS) -o $@ tests_dnssec.o testmessages.o

View File

@ -42,9 +42,7 @@
void run_event_loop_impl(struct getdns_context* context, void* eventloop) {
struct ev_loop* loop = (struct ev_loop*) eventloop;
while (getdns_context_get_num_pending_requests(context, NULL) > 0) {
ev_run(loop, EVRUN_ONCE);
}
ev_run(loop, 0);
}
void* create_eventloop_impl(struct getdns_context* context) {

View File

@ -42,9 +42,7 @@
void run_event_loop_impl(struct getdns_context* context, void* eventloop) {
struct event_base* base = (struct event_base*) eventloop;
while (getdns_context_get_num_pending_requests(context, NULL) > 0) {
event_base_loop(base, EVLOOP_ONCE);
}
event_base_dispatch(base);
}
void* create_eventloop_impl(struct getdns_context* context) {

View File

@ -42,9 +42,7 @@
void run_event_loop_impl(struct getdns_context* context, void* eventloop) {
uv_loop_t* loop = (uv_loop_t*) eventloop;
while (getdns_context_get_num_pending_requests(context, NULL) > 0) {
uv_run(loop, UV_RUN_ONCE);
}
uv_run(loop, UV_RUN_DEFAULT);
}