From fd0f51c4480a19a03d30d0f3fcecd69f5257c293 Mon Sep 17 00:00:00 2001 From: Christos Tsantilas Date: Tue, 15 Mar 2011 19:31:34 +0200 Subject: [PATCH] Convert dns_timeout and dns_retransmit_interval configuration options to use millisecond resolution. One second resolution is too coarse for small timeouts in delay-sensitive environments, especially when a retransmit, bypass, or another corrective action is available and is likely to produce a positive outcome. In DNS world specifically, most timeouts are measured in milliseconds. This is a Measurement Factory project --- src/cache_cf.cc | 61 ++++++++++++++++++++++++++++++++------------- src/cf.data.depend | 1 + src/cf.data.pre | 4 +-- src/dns_internal.cc | 16 ++++++++---- src/structs.h | 4 +-- src/typedefs.h | 3 +++ 6 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/cache_cf.cc b/src/cache_cf.cc index aaf4dbd575..6c5c1d3f00 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -118,6 +118,7 @@ static void free_ecap_service_type(Adaptation::Ecap::Config *); CBDATA_TYPE(peer); +static const char *const T_MILLISECOND_STR = "millisecond"; static const char *const T_SECOND_STR = "second"; static const char *const T_MINUTE_STR = "minute"; static const char *const T_HOUR_STR = "hour"; @@ -143,8 +144,8 @@ static void free_access_log(customlog ** definitions); static void update_maxobjsize(void); static void configDoConfigure(void); static void parse_refreshpattern(refresh_t **); -static int parseTimeUnits(const char *unit); -static void parseTimeLine(time_t * tptr, const char *units); +static uint64_t parseTimeUnits(const char *unit); +static void parseTimeLine(time_msec_t * tptr, const char *units); static void parse_ushort(u_short * var); static void parse_string(char **); static void default_all(void); @@ -957,12 +958,12 @@ parse_obsolete(const char *name) /* Parse a time specification from the config file. Store the * result in 'tptr', after converting it to 'units' */ static void -parseTimeLine(time_t * tptr, const char *units) +parseTimeLine(time_msec_t * tptr, const char *units) { char *token; double d; - time_t m; - time_t u; + time_msec_t m; + time_msec_t u; if ((u = parseTimeUnits(units)) == 0) self_destruct(); @@ -983,38 +984,41 @@ parseTimeLine(time_t * tptr, const char *units) else if ((m = parseTimeUnits(token)) == 0) self_destruct(); - *tptr = static_cast (m * d / u); + *tptr = static_cast(m * d); } -static int +static uint64_t parseTimeUnits(const char *unit) { - if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR))) + if (!strncasecmp(unit, T_MILLISECOND_STR, strlen(T_MILLISECOND_STR))) return 1; + if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR))) + return 1000; + if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR))) - return 60; + return 60 * 1000; if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR))) - return 3600; + return 3600 * 1000; if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR))) - return 86400; + return 86400 * 1000; if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR))) - return 86400 * 7; + return 86400 * 7 * 1000; if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR))) - return 86400 * 14; + return 86400 * 14 * 1000; if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR))) - return 86400 * 30; + return static_cast(86400) * 30 * 1000; if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR))) - return static_cast(86400 * 365.2522); + return static_cast(86400 * 1000 * 365.2522); if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR))) - return static_cast(86400 * 365.2522 * 10); + return static_cast(86400 * 1000 * 365.2522 * 10); debugs(3, 1, "parseTimeUnits: unknown time unit '" << unit << "'"); @@ -3003,7 +3007,9 @@ dump_time_t(StoreEntry * entry, const char *name, time_t var) void parse_time_t(time_t * var) { - parseTimeLine(var, T_SECOND_STR); + time_msec_t tval; + parseTimeLine(&tval, T_SECOND_STR); + *var = static_cast(tval/1000); } static void @@ -3012,6 +3018,27 @@ free_time_t(time_t * var) *var = 0; } +static void +dump_time_msec(StoreEntry * entry, const char *name, time_msec_t var) +{ + if (var % 1000) + storeAppendPrintf(entry, "%s %"PRId64" milliseconds\n", name, var); + else + storeAppendPrintf(entry, "%s %d seconds\n", name, (int)(var/1000) ); +} + +void +parse_time_msec(time_msec_t * var) +{ + parseTimeLine(var, T_SECOND_STR); +} + +static void +free_time_msec(time_msec_t * var) +{ + *var = 0; +} + #if UNUSED_CODE static void dump_size_t(StoreEntry * entry, const char *name, size_t var) diff --git a/src/cf.data.depend b/src/cf.data.depend index b1496baf58..fc5f3ff1b2 100644 --- a/src/cf.data.depend +++ b/src/cf.data.depend @@ -57,6 +57,7 @@ size_t IpAddress_list string string +time_msec time_t tristate uri_whitespace diff --git a/src/cf.data.pre b/src/cf.data.pre index 7831da1d36..d947897b48 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -6879,7 +6879,7 @@ DOC_START DOC_END NAME: dns_retransmit_interval -TYPE: time_t +TYPE: time_msec DEFAULT: 5 seconds LOC: Config.Timeout.idns_retransmit IFDEF: !USE_DNSSERVERS @@ -6889,7 +6889,7 @@ DOC_START DOC_END NAME: dns_timeout -TYPE: time_t +TYPE: time_msec DEFAULT: 2 minutes LOC: Config.Timeout.idns_query IFDEF: !USE_DNSSERVERS diff --git a/src/dns_internal.cc b/src/dns_internal.cc index e8ee3ac7de..77d9bb0fba 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -724,7 +724,9 @@ idnsTickleQueue(void) if (NULL == lru_list.tail) return; - eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, 1.0, 1); + const double when = min(Config.Timeout.idns_query, Config.Timeout.idns_retransmit)/1000.0; + + eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, when, 1); event_queued = 1; } @@ -764,7 +766,11 @@ idnsDoSendQueryVC(nsvc *vc) vc->busy = 1; - commSetTimeout(vc->fd, Config.Timeout.idns_query, NULL, NULL); + // Comm needs seconds but idnsCheckQueue() will check the exact timeout + const int timeout = (Config.Timeout.idns_query % 1000 ? + Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000; + + commSetTimeout(vc->fd, timeout, NULL, NULL); AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC", CommIoCbPtrFun(&idnsSentQueryVC, vc)); @@ -1341,11 +1347,11 @@ idnsCheckQueue(void *unused) q = static_cast(n->data); /* Anything to process in the queue? */ - if (tvSubDsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit ) + if ((time_msec_t)tvSubMsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit ) break; /* Query timer expired? */ - if (tvSubDsec(q->sent_t, current_time) < Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns)) { + if ((time_msec_t)tvSubMsec(q->sent_t, current_time) < (Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns))) { dlinkDelete(&q->lru, &lru_list); q->queue_t = current_time; dlinkAdd(q, &q->lru, &lru_list); @@ -1358,7 +1364,7 @@ idnsCheckQueue(void *unused) dlinkDelete(&q->lru, &lru_list); - if (tvSubDsec(q->start_t, current_time) < Config.Timeout.idns_query) { + if ((time_msec_t)tvSubMsec(q->start_t, current_time) < Config.Timeout.idns_query) { idnsSendQuery(q); } else { debugs(78, 2, "idnsCheckQueue: ID " << q->xact_id << diff --git a/src/structs.h b/src/structs.h index 9b6e3aef96..c99508fa86 100644 --- a/src/structs.h +++ b/src/structs.h @@ -192,8 +192,8 @@ struct SquidConfig { #if !USE_DNSSERVERS - time_t idns_retransmit; - time_t idns_query; + time_msec_t idns_retransmit; + time_msec_t idns_query; #endif } Timeout; diff --git a/src/typedefs.h b/src/typedefs.h index 44d14837e0..2e7239d8e6 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -191,4 +191,7 @@ typedef unsigned char cache_key; typedef ssize_t mb_size_t; typedef int STDIRSELECT(const StoreEntry *); + +/*Use uint64_t to store miliseconds*/ +typedef uint64_t time_msec_t; #endif /* SQUID_TYPEDEFS_H */ -- 2.47.3