Track netreqs "in flight"

This commit is contained in:
Willem Toorop 2017-03-14 17:17:56 +01:00
parent b8f43c8acd
commit 14c9f3aafc
8 changed files with 64 additions and 18 deletions

View File

@ -1330,6 +1330,8 @@ getdns_context_create_with_extended_memory_functions(
_getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp);
_getdns_rbtree_init(&result->local_hosts, local_host_cmp);
/* TODO: Initialize pending_netreqs */
result->netreqs_in_flight = 0;
result->server = NULL;
@ -2980,6 +2982,27 @@ _getdns_context_request_timed_out(getdns_dns_req *dnsreq)
_getdns_context_cancel_request(dnsreq);
}
void
_getdns_netreq_change_state(getdns_network_req *netreq, network_req_state new_state)
{
if (!netreq)
return;
if (netreq->state != NET_REQ_IN_FLIGHT) {
if (new_state == NET_REQ_IN_FLIGHT)
netreq->owner->context->netreqs_in_flight += 1;
netreq->state = new_state;
return;
}
if (new_state == NET_REQ_IN_FLIGHT) /* No change */
return;
netreq->state = new_state;
netreq->owner->context->netreqs_in_flight -= 1;
/* TODO: Schedule pending netreqs
* when netreqs_in_flight < oustanding_queries */
}
static void
accumulate_outstanding_transactions(_getdns_rbnode_t *node, void* arg)
{

View File

@ -291,6 +291,11 @@ struct getdns_context {
*/
_getdns_rbtree_t outbound_requests;
/* network requests
*/
size_t netreqs_in_flight;
_getdns_rbtree_t pending_netreqs;
struct listen_set *server;
/* Event loop extension. */
@ -372,12 +377,22 @@ void _getdns_context_clear_outbound_request(getdns_dns_req *dnsreq);
*/
void _getdns_context_cancel_request(getdns_dns_req *dnsreq);
/* Calls user callback (with GETDNS_CALLBACK_TIMEOUT + response dict), then
* cancels and frees the getdns_dns_req with _getdns_context_cancel_request()
*/
void _getdns_context_request_timed_out(getdns_dns_req *dnsreq);
/* Change state of the netreq req.
* - Increments context->netreqs_in_flight
* when state changes from NOT_SENT to IN_FLIGHT
* - Decrements context->netreqs_in_flight
* when state changes from IN_FLIGHT to FINISHED, TIMED_OUT or ERRORED
* - Resubmits NOT_SENT netreqs from context->pending_netreqs,
* when # pending_netreqs < limit_outstanding_queries
*/
void _getdns_netreq_change_state(
getdns_network_req *req, network_req_state new_state);
char *_getdns_strdup(const struct mem_funcs *mfs, const char *str);
struct getdns_bindata *_getdns_bindata_copy(

View File

@ -3040,7 +3040,7 @@ static void check_chain_complete(chain_head *chain)
; !r && (netreq = *netreq_p)
; netreq_p++) {
netreq->state = NET_REQ_NOT_SENT;
_getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT);
netreq->owner = dnsreq;
r = _getdns_submit_netreq(netreq, &now_ms);
}

View File

@ -130,7 +130,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
_getdns_check_dns_req_complete(dns_req);
@ -168,7 +168,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
_getdns_check_dns_req_complete(dns_req);
@ -209,7 +209,7 @@ ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dns_req = netreq->owner;
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
/* parse */
if (getdns_apply_network_result(
netreq, rcode, pkt, pkt_len, sec, why_bogus)) {
@ -227,7 +227,7 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dns_req = netreq->owner;
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
if (err != 0) {
_getdns_call_user_callback(dns_req, NULL);
return;
@ -259,6 +259,8 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
int ub_resolve_r;
#endif
_getdns_netreq_change_state(netreq, NET_REQ_IN_FLIGHT);
#ifdef STUB_NATIVE_DNSSEC
# ifdef DNSSEC_ROADBLOCK_AVOIDANCE
@ -457,7 +459,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
*return_netreq_p = NULL;
return GETDNS_RETURN_GOOD;
}
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
@ -486,7 +488,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
*return_netreq_p = NULL;
return GETDNS_RETURN_GOOD;
}
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
/* Stop processing more namespaces, since there was a match */
@ -509,7 +511,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
*return_netreq_p = NULL;
return GETDNS_RETURN_GOOD;
}
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
break;

View File

@ -121,7 +121,7 @@ mdns_timeout_cb(void *userarg)
#else
close(netreq->fd);
#endif
netreq->state = NET_REQ_TIMED_OUT;
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) {
netreq->debug_end_time = _getdns_get_time_as_uintt64();
(void)_getdns_context_request_timed_out(netreq->owner);
@ -182,7 +182,7 @@ mdns_udp_read_cb(void *userarg)
netreq->response_len = read;
netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(dnsreq);
}

View File

@ -118,7 +118,7 @@ netreq_reset(getdns_network_req *net_req)
/* variables that need to be reset on reinit
*/
net_req->unbound_id = -1;
net_req->state = NET_REQ_NOT_SENT;
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->query_id = 0;
@ -183,6 +183,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
net_req->debug_udp = 0;
/* Scheduling, touch only via _getdns_netreq_change_state!
*/
net_req->state = NET_REQ_NOT_SENT;
if (max_query_sz == 0) {
net_req->query = NULL;
net_req->opt = NULL;

View File

@ -550,7 +550,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
netreq = (getdns_network_req *)
_getdns_rbtree_first(&upstream->netreq_by_query_id);
stub_cleanup(netreq);
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(netreq->owner);
}
}
@ -580,7 +580,7 @@ stub_timeout_cb(void *userarg)
DEBUG_STUB("%s %-35s: MSG: %p\n",
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
stub_cleanup(netreq);
netreq->state = NET_REQ_TIMED_OUT;
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
@ -1368,7 +1368,7 @@ stub_udp_read_cb(void *userarg)
netreq->response_len = read;
dnsreq->upstreams->current_udp = 0;
netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
upstream->udp_responses++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (upstream->udp_responses == 1 ||
@ -1495,7 +1495,7 @@ upstream_read_cb(void *userarg)
DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
netreq->response = upstream->tcp.read_buf;
netreq->response_len =
upstream->tcp.read_pos - upstream->tcp.read_buf;
@ -1614,7 +1614,7 @@ upstream_write_cb(void *userarg)
#endif
if (fallback_on_write(netreq) == STUB_TCP_ERROR) {
/* TODO: Need new state to report transport unavailable*/
netreq->state = NET_REQ_FINISHED;
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(netreq->owner);
}
return;

View File

@ -4,7 +4,9 @@
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
QLIMIT=10
# TODO: Change QLIMIT to 10 once implement pending netreq resubmission
#
QLIMIT=1000
make && "./${TPKG_NAME}" | (
read PORT
${GETDNS_STUB_QUERY} @127.0.0.1:$PORT TXT \