Reuse sync eventloop per context

So recursive resolution can depend on and continue with outstanding queries it depends on
This commit is contained in:
Willem Toorop 2016-03-09 11:16:19 +01:00
parent 70cc65f786
commit a83c54387d
3 changed files with 58 additions and 64 deletions

View File

@ -1156,6 +1156,7 @@ getdns_context_create_with_extended_memory_functions(
result->extension = &result->default_eventloop.loop; result->extension = &result->default_eventloop.loop;
_getdns_default_eventloop_init(&result->default_eventloop); _getdns_default_eventloop_init(&result->default_eventloop);
_getdns_default_eventloop_init(&result->sync_eventloop);
result->fchg_resolvconf = NULL; result->fchg_resolvconf = NULL;
result->fchg_hosts = NULL; result->fchg_hosts = NULL;
@ -1260,13 +1261,13 @@ getdns_context_destroy(struct getdns_context *context)
*/ */
_getdns_upstreams_dereference(context->upstreams); _getdns_upstreams_dereference(context->upstreams);
context->sync_eventloop.loop.vmt->cleanup(&context->sync_eventloop.loop);
context->extension->vmt->cleanup(context->extension);
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
if (context->unbound_ctx) if (context->unbound_ctx)
ub_ctx_delete(context->unbound_ctx); ub_ctx_delete(context->unbound_ctx);
#endif #endif
context->extension->vmt->cleanup(context->extension);
if (context->namespaces) if (context->namespaces)
GETDNS_FREE(context->my_mf, context->namespaces); GETDNS_FREE(context->my_mf, context->namespaces);

View File

@ -249,6 +249,7 @@ struct getdns_context {
/* The default extension */ /* The default extension */
_getdns_default_eventloop default_eventloop; _getdns_default_eventloop default_eventloop;
_getdns_default_eventloop sync_eventloop;
/* /*
* state data used to detect changes to the system config files * state data used to detect changes to the system config files

View File

@ -45,36 +45,33 @@
#include "stub.h" #include "stub.h"
#include "gldns/wire2str.h" #include "gldns/wire2str.h"
typedef struct getdns_sync_loop { typedef struct getdns_sync_data {
_getdns_default_eventloop loop;
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
getdns_eventloop_event ub_event; getdns_eventloop_event ub_event;
#endif #endif
getdns_context *context; getdns_context *context;
int to_run; int to_run;
getdns_dict *response; getdns_dict *response;
} getdns_sync_loop; } getdns_sync_data;
static getdns_return_t static getdns_return_t
getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) getdns_sync_data_init(getdns_context *context, getdns_sync_data *data)
{ {
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
getdns_eventloop *ext = &loop->loop.loop; getdns_eventloop *ext = &context->sync_eventloop.loop;
#endif #endif
loop->response = NULL; data->context = context;
loop->to_run = 1; data->to_run = 1;
loop->context = context; data->response = NULL;
_getdns_default_eventloop_init(&loop->loop);
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
# ifndef USE_WINSOCK # ifndef USE_WINSOCK
loop->ub_event.userarg = loop->context; data->ub_event.userarg = data->context;
loop->ub_event.read_cb = _getdns_context_ub_read_cb; data->ub_event.read_cb = _getdns_context_ub_read_cb;
loop->ub_event.write_cb = NULL; data->ub_event.write_cb = NULL;
loop->ub_event.timeout_cb = NULL; data->ub_event.timeout_cb = NULL;
loop->ub_event.ev = NULL; data->ub_event.ev = NULL;
# endif # endif
# ifdef HAVE_UNBOUND_EVENT_API # ifdef HAVE_UNBOUND_EVENT_API
if (_getdns_ub_loop_enabled(&context->ub_loop)) { if (_getdns_ub_loop_enabled(&context->ub_loop)) {
@ -83,7 +80,7 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop)
# endif # endif
# ifndef USE_WINSOCK # ifndef USE_WINSOCK
return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx),
TIMEOUT_FOREVER, &loop->ub_event); TIMEOUT_FOREVER, &data->ub_event);
# else # else
/* No sync full recursion requests on windows without /* No sync full recursion requests on windows without
* UNBOUND_EVENT_API because ub_fd() doesn't work on windows. * UNBOUND_EVENT_API because ub_fd() doesn't work on windows.
@ -95,66 +92,61 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop)
} }
static void static void
getdns_sync_loop_cleanup(getdns_sync_loop *loop) getdns_sync_data_cleanup(getdns_sync_data *data)
{ {
getdns_eventloop *ext = &loop->loop.loop;
#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) #if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK)
# ifdef HAVE_UNBOUND_EVENT_API # ifdef HAVE_UNBOUND_EVENT_API
if (_getdns_ub_loop_enabled(&loop->context->ub_loop)) { if (_getdns_ub_loop_enabled(&data->context->ub_loop)) {
loop->context->ub_loop.extension = loop->context->extension; data->context->ub_loop.extension = data->context->extension;
} else } else
# endif # endif
ext->vmt->clear(ext, &loop->ub_event); data->context->sync_eventloop.loop.vmt->clear(
&data->context->sync_eventloop.loop, &data->ub_event);
#endif #endif
ext->vmt->cleanup(ext);
} }
static void static void
getdns_sync_loop_run(getdns_sync_loop *loop) getdns_sync_loop_run(getdns_sync_data *data)
{ {
getdns_eventloop *ext = &loop->loop.loop; while (data->to_run)
data->context->sync_eventloop.loop.vmt->run_once(
while (loop->to_run) &data->context->sync_eventloop.loop, 1);
ext->vmt->run_once(ext, 1);
getdns_sync_loop_cleanup(loop);
} }
static void static void
getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type,
getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) getdns_dict *response, void *userarg, getdns_transaction_t transaction_id)
{ {
getdns_sync_loop *loop = (getdns_sync_loop *)userarg; getdns_sync_data *data = (getdns_sync_data *)userarg;
assert(loop); assert(data);
loop->response = response; data->response = response;
loop->to_run = 0; data->to_run = 0;
} }
getdns_return_t getdns_return_t
getdns_general_sync(getdns_context *context, const char *name, getdns_general_sync(getdns_context *context, const char *name,
uint16_t request_type, getdns_dict *extensions, getdns_dict **response) uint16_t request_type, getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_loop loop; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
if (!context || !name || !response) if (!context || !name || !response)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = getdns_sync_loop_init(context, &loop))) if ((r = getdns_sync_data_init(context, &data)))
return r; return r;
if ((r = _getdns_general_loop(context, &loop.loop.loop, name, if ((r = _getdns_general_loop(context, &context->sync_eventloop.loop,
request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) { name, request_type, extensions, &data, NULL, getdns_sync_cb, NULL))) {
getdns_sync_loop_cleanup(&loop); getdns_sync_data_cleanup(&data);
return r; return r;
} }
getdns_sync_loop_run(&loop); getdns_sync_loop_run(&data);
return (*response = loop.response) ? return (*response = data.response) ?
GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
} }
@ -162,24 +154,24 @@ getdns_return_t
getdns_address_sync(getdns_context *context, const char *name, getdns_address_sync(getdns_context *context, const char *name,
getdns_dict *extensions, getdns_dict **response) getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_loop loop; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
if (!context || !name || !response) if (!context || !name || !response)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = getdns_sync_loop_init(context, &loop))) if ((r = getdns_sync_data_init(context, &data)))
return r; return r;
if ((r = _getdns_address_loop(context, &loop.loop.loop, name, if ((r = _getdns_address_loop(context, &context->sync_eventloop.loop,
extensions, &loop, NULL, getdns_sync_cb))) { name, extensions, &data, NULL, getdns_sync_cb))) {
getdns_sync_loop_cleanup(&loop); getdns_sync_data_cleanup(&data);
return r; return r;
} }
getdns_sync_loop_run(&loop); getdns_sync_loop_run(&data);
return (*response = loop.response) ? return (*response = data.response) ?
GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
} }
@ -187,24 +179,24 @@ getdns_return_t
getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_hostname_sync(getdns_context *context, getdns_dict *address,
getdns_dict *extensions, getdns_dict **response) getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_loop loop; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
if (!context || !address || !response) if (!context || !address || !response)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = getdns_sync_loop_init(context, &loop))) if ((r = getdns_sync_data_init(context, &data)))
return r; return r;
if ((r = _getdns_hostname_loop(context, &loop.loop.loop, address, if ((r = _getdns_hostname_loop(context, &context->sync_eventloop.loop,
extensions, &loop, NULL, getdns_sync_cb))) { address, extensions, &data, NULL, getdns_sync_cb))) {
getdns_sync_loop_cleanup(&loop); getdns_sync_data_cleanup(&data);
return r; return r;
} }
getdns_sync_loop_run(&loop); getdns_sync_loop_run(&data);
return (*response = loop.response) ? return (*response = data.response) ?
GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
} }
@ -212,24 +204,24 @@ getdns_return_t
getdns_service_sync(getdns_context *context, const char *name, getdns_service_sync(getdns_context *context, const char *name,
getdns_dict *extensions, getdns_dict **response) getdns_dict *extensions, getdns_dict **response)
{ {
getdns_sync_loop loop; getdns_sync_data data;
getdns_return_t r; getdns_return_t r;
if (!context || !name || !response) if (!context || !name || !response)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = getdns_sync_loop_init(context, &loop))) if ((r = getdns_sync_data_init(context, &data)))
return r; return r;
if ((r = _getdns_service_loop(context, &loop.loop.loop, name, if ((r = _getdns_service_loop(context, &context->sync_eventloop.loop,
extensions, &loop, NULL, getdns_sync_cb))) { name, extensions, &data, NULL, getdns_sync_cb))) {
getdns_sync_loop_cleanup(&loop); getdns_sync_data_cleanup(&data);
return r; return r;
} }
getdns_sync_loop_run(&loop); getdns_sync_loop_run(&data);
return (*response = loop.response) ? return (*response = data.response) ?
GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR;
} }