summaryrefslogtreecommitdiff
path: root/ares_timeout.c
diff options
context:
space:
mode:
authorSteinar H. Gunderson <sesse@google.com>2007-09-29 18:18:47 +0000
committerSteinar H. Gunderson <sesse@google.com>2007-09-29 18:18:47 +0000
commit04e49e09dcfac29e7e90b5546672a9b42d0b935a (patch)
tree82057cf2db538d1d8682daad0623ea330812a042 /ares_timeout.c
parentedf19010776aee7913d5866ed290349f5b333251 (diff)
downloadc-ares-04e49e09dcfac29e7e90b5546672a9b42d0b935a.tar.gz
c-ares-04e49e09dcfac29e7e90b5546672a9b42d0b935a.tar.bz2
c-ares-04e49e09dcfac29e7e90b5546672a9b42d0b935a.zip
Previously, processing a large batch of timeouts was O(n^2) in the number of
outstanding queries, and processing a DNS response packet was O(n) in the number of outstanding queries. To speed things up in Google, we added a few circular, doubly-linked lists of queries that are hash-bucketed based on the attributes we care about, so most important operations are now O(1). It might be that the number of buckets are higher than most people would need, but on a quick calculation it should only be 100kB or so even on a 64-bit system, so I've let it stay as-is.
Diffstat (limited to 'ares_timeout.c')
-rw-r--r--ares_timeout.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/ares_timeout.c b/ares_timeout.c
index 496db84..12b93b0 100644
--- a/ares_timeout.c
+++ b/ares_timeout.c
@@ -26,23 +26,34 @@
#include "ares.h"
#include "ares_private.h"
+/* WARNING: Beware that this is linear in the number of outstanding
+ * requests! You are probably far better off just calling ares_process()
+ * once per second, rather than calling ares_timeout() to figure out
+ * when to next call ares_process().
+ */
struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
struct timeval *tvbuf)
{
struct query *query;
+ struct list_node* list_head;
+ struct list_node* list_node;
time_t now;
time_t offset, min_offset; /* these use time_t since some 32 bit systems
still use 64 bit time_t! (like VS2005) */
/* No queries, no timeout (and no fetch of the current time). */
- if (!channel->queries)
+ if (ares__is_list_empty(&(channel->all_queries)))
return maxtv;
/* Find the minimum timeout for the current set of queries. */
time(&now);
min_offset = -1;
- for (query = channel->queries; query; query = query->next)
+
+ list_head = &(channel->all_queries);
+ for (list_node = list_head->next; list_node != list_head;
+ list_node = list_node->next)
{
+ query = list_node->data;
if (query->timeout == 0)
continue;
offset = query->timeout - now;