So, is it OK to use the 30 seconds as the default dns_timeout value?
If not objection I will commit this patch later today ....


On 03/14/2011 06:35 PM, Alex Rousskov wrote:

+static void
+dump_time_msec(StoreEntry * entry, const char *name, uint64_t var)
+{
+    storeAppendPrintf(entry, "%s %d seconds and %d milliseconds\n", name, 
(int) (var/1000), (int) (var % 1000));
+}

I doubt we are consistent with this everywhere, but should we try to
dump options in a format compatible with squid.conf syntax? If yes, we
could do something like this (at least):

if (var % 1000)
     storeAppendPrintf(entry, "%s %d milliseconds\n", name, (int) var);
else
     storeAppendPrintf(entry, "%s %d seconds\n", name, (int) (var/1000));

OK fixed.


We can also use T_SECOND_STR and T_MILLISECOND_STR in the above.
I did not use them because of the missing "s" at the end of these strings ("second" not "seconds" etc....)


-    commSetTimeout(vc->fd, Config.Timeout.idns_query, NULL, NULL);
+    const int timeout = (Config.Timeout.idns_query % 1000 ?
+        Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
+
+    commSetTimeout(vc->fd, timeout, NULL, NULL);

Perhaps add a source comment explaining that while we are forced to
convert to seconds here, the exact timeout will be checked in
idnsCheckQueue()?
// Comm needs seconds but idnsCheckQueue() will check the exact timeout

done


Please consider typedef-ing uint64_t as time_msec and using time_msec
type as needed. This will help with identifying time-related values in
the future.

done

On 03/15/2011 01:25 AM, Amos Jeffries wrote:
>
> Yes. We MUST even. People use the cachemgr output these dump routines
> flow into as copy-n-paste sources for other squid.conf and tutorials.
>
>>
>> if (var % 1000)
>> storeAppendPrintf(entry, "%s %d milliseconds\n", name, (int) var);
>> else
>> storeAppendPrintf(entry, "%s %d seconds\n", name, (int) (var/1000));
>
> Please also avoid the 32-bit cast by using %"PRIu64" for all unsigned
> 64-bit display.

done

>
> Also, conversion to the largest whole time period (second, minute, hour,
> day etc as supported by the parser) would be good for user education
> through the display defaults.

I did not change this one. I do not think it is something important because it is unusual to have big time periods, in the cases where the user should use milliseconds...




=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2011-02-07 10:27:53 +0000
+++ src/cache_cf.cc	2011-03-15 12:03:25 +0000
@@ -101,67 +101,68 @@
 #if ICAP_CLIENT
 static void parse_icap_service_type(Adaptation::Icap::Config *);
 static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &);
 static void free_icap_service_type(Adaptation::Icap::Config *);
 static void parse_icap_class_type();
 static void parse_icap_access_type();
 
 static void parse_icap_service_failure_limit(Adaptation::Icap::Config *);
 static void dump_icap_service_failure_limit(StoreEntry *, const char *, const Adaptation::Icap::Config &);
 static void free_icap_service_failure_limit(Adaptation::Icap::Config *);
 #endif
 
 #if USE_ECAP
 static void parse_ecap_service_type(Adaptation::Ecap::Config *);
 static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &);
 static void free_ecap_service_type(Adaptation::Ecap::Config *);
 #endif
 
 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";
 static const char *const T_DAY_STR = "day";
 static const char *const T_WEEK_STR = "week";
 static const char *const T_FORTNIGHT_STR = "fortnight";
 static const char *const T_MONTH_STR = "month";
 static const char *const T_YEAR_STR = "year";
 static const char *const T_DECADE_STR = "decade";
 
 static const char *const B_BYTES_STR = "bytes";
 static const char *const B_KBYTES_STR = "KB";
 static const char *const B_MBYTES_STR = "MB";
 static const char *const B_GBYTES_STR = "GB";
 
 static const char *const list_sep = ", \t\n\r";
 
 static void parse_access_log(customlog ** customlog_definitions);
 static int check_null_access_log(customlog *customlog_definitions);
 static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions);
 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);
 static void defaults_if_none(void);
 static int parse_line(char *);
 static void parse_obsolete(const char *);
 static void parseBytesLine(size_t * bptr, const char *units);
 #if USE_SSL
 static void parseBytesOptionValue(size_t * bptr, const char *units, char const * value);
 #endif
 #if !USE_DNSSERVERS
 static void parseBytesLineSigned(ssize_t * bptr, const char *units);
 #endif
 static size_t parseBytesUnits(const char *unit);
 static void free_all(void);
 void requirePathnameExists(const char *name, const char *path);
 static OBJH dump_config;
 #if USE_HTTP_VIOLATIONS
 static void dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[]);
 static void parse_http_header_access(header_mangler header[]);
@@ -940,98 +941,101 @@
  * To upgrade it where possible instead of just "Bungled config" for
  * directives which cannot be marked as simply aliases of the some name.
  * For example if the parameter order and content has changed.
  * Or if the directive has been completely removed.
  */
 void
 parse_obsolete(const char *name)
 {
     // Directives which have been radically changed rather than removed
     if (!strcmp(name, "url_rewrite_concurrency")) {
         int cval;
         parse_int(&cval);
         debugs(3, DBG_CRITICAL, "WARNING: url_rewrite_concurrency upgrade overriding url_rewrite_children settings.");
         Config.redirectChildren.concurrency = cval;
     }
 }
 
 /* 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();
 
     if ((token = strtok(NULL, w_space)) == NULL)
         self_destruct();
 
     d = xatof(token);
 
     m = u;			/* default to 'units' if none specified */
 
     if (0 == d)
         (void) 0;
     else if ((token = strtok(NULL, w_space)) == NULL)
         debugs(3, 0, "WARNING: No units on '" <<
                config_input_line << "', assuming " <<
                d << " " << units  );
     else if ((m = parseTimeUnits(token)) == 0)
         self_destruct();
 
-    *tptr = static_cast<time_t> (m * d / u);
+    *tptr = static_cast<time_msec_t>(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<uint64_t>(86400) * 30 * 1000;
 
     if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR)))
-        return static_cast<int>(86400 * 365.2522);
+        return static_cast<uint64_t>(86400 * 1000 * 365.2522);
 
     if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
-        return static_cast<int>(86400 * 365.2522 * 10);
+        return static_cast<uint64_t>(86400 * 1000 * 365.2522 * 10);
 
     debugs(3, 1, "parseTimeUnits: unknown time unit '" << unit << "'");
 
     return 0;
 }
 
 static void
 parseBytesLine64(int64_t * bptr, const char *units)
 {
     char *token;
     double d;
     int64_t m;
     int64_t u;
 
     if ((u = parseBytesUnits(units)) == 0) {
         self_destruct();
         return;
     }
 
     if ((token = strtok(NULL, w_space)) == NULL) {
@@ -2986,49 +2990,72 @@
     if (!*token) {
         self_destruct();
         return;
     }
 
     *var = xstrdup((char *) token);
 }
 
 #define dump_eol dump_string
 #define free_eol free_string
 
 static void
 dump_time_t(StoreEntry * entry, const char *name, time_t var)
 {
     storeAppendPrintf(entry, "%s %d seconds\n", name, (int) 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<time_t>(tval/1000);
 }
 
 static void
 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)
 {
     storeAppendPrintf(entry, "%s %d\n", name, (int) var);
 }
 #endif
 
 static void
 dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
 {
     storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
 }
 
 #if !USE_DNSSERVERS
 static void
 dump_b_ssize_t(StoreEntry * entry, const char *name, ssize_t var)
 {
     storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
 }

=== modified file 'src/cf.data.depend'
--- src/cf.data.depend	2010-10-25 18:25:19 +0000
+++ src/cf.data.depend	2011-03-09 10:48:40 +0000
@@ -40,29 +40,30 @@
 icap_class_type		icap_service
 icap_service_type
 icap_service_failure_limit
 ecap_service_type
 int
 kb_int64_t
 kb_size_t
 logformat
 memcachemode
 obsolete
 onoff
 peer
 peer_access		cache_peer acl
 QosConfig
 refreshpattern
 removalpolicy
 size_t
 IpAddress_list
 string
 string
+time_msec
 time_t
 tristate
 uri_whitespace
 ushort
 wccp2_method
 wccp2_amethod
 wccp2_service
 wccp2_service_info
 wordlist

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2011-02-07 10:27:53 +0000
+++ src/cf.data.pre	2011-03-15 11:52:25 +0000
@@ -6853,52 +6853,52 @@
 	tuning.
 	
 		startup=
 	
 	Sets a minimum of how many processes are to be spawned when Squid
 	starts or reconfigures. When set to zero the first request will
 	cause spawning of the first child process to handle it.
 	
 	Starting too few will cause an initial slowdown in traffic as Squid
 	attempts to simultaneously spawn enough processes to cope.
 	
 		idle=
 	
 	Sets a minimum of how many processes Squid is to try and keep available
 	at all times. When traffic begins to rise above what the existing
 	processes can handle this many more will be spawned up to the maximum
 	configured. A minimum setting of 1 is required.
 DOC_END
 
 NAME: dns_retransmit_interval
-TYPE: time_t
+TYPE: time_msec
 DEFAULT: 5 seconds
 LOC: Config.Timeout.idns_retransmit
 IFDEF: !USE_DNSSERVERS
 DOC_START
 	Initial retransmit interval for DNS queries. The interval is
 	doubled each time all configured DNS servers have been tried.
 DOC_END
 
 NAME: dns_timeout
-TYPE: time_t
-DEFAULT: 2 minutes
+TYPE: time_msec
+DEFAULT: 30 seconds
 LOC: Config.Timeout.idns_query
 IFDEF: !USE_DNSSERVERS
 DOC_START
 	DNS Query timeout. If no response is received to a DNS query
 	within this time all DNS servers for the queried domain
 	are assumed to be unavailable.
 DOC_END
 
 NAME: dns_packet_max
 TYPE: b_ssize_t
 DEFAULT: none
 LOC: Config.dns.packet_max
 IFDEF: !USE_DNSSERVERS
 DOC_START
 	Maximum number of bytes packet size to advertise via EDNS.
 	Set to "none" to disable EDNS large packet support.
 	
 	For legacy reasons DNS UDP replies will default to 512 bytes which
 	is too small for many responses. EDNS provides a means for Squid to
 	negotiate receiving larger responses back immediately without having

=== modified file 'src/dns_internal.cc'
--- src/dns_internal.cc	2011-03-06 11:48:16 +0000
+++ src/dns_internal.cc	2011-03-15 10:55:51 +0000
@@ -707,81 +707,87 @@
 
     if (npc) {
         storeAppendPrintf(sentry, "\nSearch list:\n");
 
         for (i=0; i < npc; i++)
             storeAppendPrintf(sentry, "%s\n", searchpath[i].domain);
 
         storeAppendPrintf(sentry, "\n");
     }
 }
 
 static void
 idnsTickleQueue(void)
 {
     if (event_queued)
         return;
 
     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;
 }
 
 static void
 idnsSentQueryVC(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
 {
     nsvc * vc = (nsvc *)data;
 
     if (flag == COMM_ERR_CLOSING)
         return;
 
     if (fd_table[fd].closing())
         return;
 
     if (flag != COMM_OK || size <= 0) {
         comm_close(fd);
         return;
     }
 
     vc->busy = 0;
     idnsDoSendQueryVC(vc);
 }
 
 static void
 idnsDoSendQueryVC(nsvc *vc)
 {
     if (vc->busy)
         return;
 
     if (vc->queue->contentSize() == 0)
         return;
 
     MemBuf *mb = vc->queue;
 
     vc->queue = new MemBuf;
 
     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));
 
     Comm::Write(vc->fd, mb, call);
 
     delete mb;
 }
 
 static void
 idnsInitVCConnected(int fd, const DnsLookupDetails &details, comm_err_t status, int xerrno, void *data)
 {
     nsvc * vc = (nsvc *)data;
 
     if (status != COMM_OK) {
         char buf[MAX_IPSTRLEN] = "";
         if (vc->ns < nns)
             nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN);
         debugs(78, 1, HERE << "Failed to connect to nameserver " << buf << " using TCP: " << details);
         comm_close(fd);
@@ -1324,58 +1330,58 @@
 }
 
 static void
 idnsCheckQueue(void *unused)
 {
     dlink_node *n;
     dlink_node *p = NULL;
     idns_query *q;
     event_queued = 0;
 
     if (0 == nns)
         /* name servers went away; reconfiguring or shutting down */
         return;
 
     for (n = lru_list.tail; n; n = p) {
 
         p = n->prev;
         q = static_cast<idns_query*>(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);
             continue;
         }
 
         debugs(78, 3, "idnsCheckQueue: ID " << q->xact_id <<
                " QID 0x"  << std::hex << std::setfill('0')  <<
                std::setw(4) << q->msg_id << ": timeout" );
 
         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 <<
                    " QID 0x" << std::hex << q->msg_id <<
                    " : giving up after " << std::dec << q->nsends << " tries and " <<
                    std::setw(5)<< std::setprecision(2) << tvSubDsec(q->start_t, current_time) << " seconds");
 
             if (q->rcode != 0)
                 idnsCallback(q, NULL, -q->rcode, rfc1035ErrorMessage(q->rcode));
             else
                 idnsCallback(q, NULL, -16, "Timeout");
 
             cbdataFree(q);
         }
     }
 
     idnsTickleQueue();
 }
 
 static void

=== modified file 'src/structs.h'
--- src/structs.h	2011-02-07 10:27:53 +0000
+++ src/structs.h	2011-03-15 10:38:29 +0000
@@ -175,42 +175,42 @@
 
     struct {
         time_t read;
         time_t write;
         time_t lifetime;
         time_t connect;
         time_t forward;
         time_t peer_connect;
         time_t request;
         time_t persistent_request;
         time_t pconn;
         time_t siteSelect;
         time_t deadPeer;
         int icp_query;		/* msec */
         int icp_query_max;	/* msec */
         int icp_query_min;	/* msec */
         int mcast_icp_query;	/* msec */
 
 #if !USE_DNSSERVERS
 
-        time_t idns_retransmit;
-        time_t idns_query;
+        time_msec_t idns_retransmit;
+        time_msec_t idns_query;
 #endif
 
     } Timeout;
     size_t maxRequestHeaderSize;
     int64_t maxRequestBodySize;
     int64_t maxChunkedRequestBodySize;
     size_t maxRequestBufferSize;
     size_t maxReplyHeaderSize;
     acl_size_t *ReplyBodySize;
 
     struct {
         u_short icp;
 #if USE_HTCP
 
         u_short htcp;
 #endif
 #if SQUID_SNMP
 
         u_short snmp;
 #endif

=== modified file 'src/typedefs.h'
--- src/typedefs.h	2011-03-02 07:27:24 +0000
+++ src/typedefs.h	2011-03-15 10:40:57 +0000
@@ -174,21 +174,24 @@
 class StoreEntry;
 typedef void OBJH(StoreEntry *);
 typedef void SIGHDLR(int sig);
 typedef void STVLDCB(void *, int, int);
 typedef void HLPCB(void *, char *buf);
 typedef int HLPSAVAIL(void *);
 typedef void HLPSONEQ(void *);
 typedef void HLPCMDOPTS(int *argc, char **argv);
 typedef void IDNSCB(void *, rfc1035_rr *, int, const char *);
 
 typedef double hbase_f(double);
 typedef void StatHistBinDumper(StoreEntry *, int idx, double val, double size, int count);
 
 /* MD5 cache keys */
 typedef unsigned char cache_key;
 
 /* in case we want to change it later */
 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 */

Reply via email to