From 7870937036a5eda44e746d8fa965aa8eb1c0b16e Mon Sep 17 00:00:00 2001 From: hniksic Date: Sat, 20 Sep 2003 16:12:18 -0700 Subject: [PATCH] [svn] Allow decimal values for --timeout, --wait, and --waitretry. Message-ID: --- src/ChangeLog | 17 ++++++++++ src/connect.c | 6 ++-- src/connect.h | 2 +- src/host.c | 7 ++-- src/init.c | 90 +++++++++++++++++++++++++++++++++++-------------- src/mswindows.c | 3 +- src/mswindows.h | 1 + src/options.h | 7 ++-- src/retr.c | 17 ++++------ src/sysdep.h | 5 +-- src/utils.c | 28 +++++++++++++-- src/utils.h | 3 +- 12 files changed, 132 insertions(+), 54 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7f64e35f..a2d4d7b5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2003-09-21 Hrvoje Niksic + + * connect.c (select_fd): Change MAXTIME's type to double. Handle + its decimal part. + + * retr.c (sleep_between_retrievals): In the random-wait case, use + random_float() to wait between 0 and 2*opt.wait seconds. + + * utils.c (run_with_timeout): Accept `double' timeouts. Correctly + handle timeout values in (0, 1) range. + (random_float): New function. + + * options.h (struct options): Change the types of wait, waitretry, + and timeout to double. + + * init.c (cmd_time): Accept floating point time. + 2003-09-20 Hrvoje Niksic * retr.c (get_contents): Cosmetic fixes. diff --git a/src/connect.c b/src/connect.c index 7ac7d3fb..5f927647 100644 --- a/src/connect.c +++ b/src/connect.c @@ -355,7 +355,7 @@ bindport (unsigned short *port, int family) Returns 1 if FD is available, 0 for timeout and -1 for error. */ int -select_fd (int fd, int maxtime, int writep) +select_fd (int fd, double maxtime, int writep) { fd_set fds; fd_set *rd = NULL, *wrt = NULL; @@ -366,8 +366,8 @@ select_fd (int fd, int maxtime, int writep) FD_SET (fd, &fds); *(writep ? &wrt : &rd) = &fds; - tmout.tv_sec = maxtime; - tmout.tv_usec = 0; + tmout.tv_sec = (long)maxtime; + tmout.tv_usec = 1000000L * (maxtime - (long)maxtime); do result = select (fd + 1, rd, wrt, NULL, &tmout); diff --git a/src/connect.h b/src/connect.h index e1924159..75eb9caa 100644 --- a/src/connect.h +++ b/src/connect.h @@ -39,7 +39,7 @@ int connect_to_many PARAMS ((struct address_list *, unsigned short, int)); void set_connection_host_name PARAMS ((const char *)); int test_socket_open PARAMS ((int)); -int select_fd PARAMS ((int, int, int)); +int select_fd PARAMS ((int, double, int)); uerr_t bindport PARAMS ((unsigned short *, int)); uerr_t acceptport PARAMS ((int *)); void closeport PARAMS ((int)); diff --git a/src/host.c b/src/host.c index 12b80602..baae0f38 100644 --- a/src/host.c +++ b/src/host.c @@ -494,7 +494,7 @@ gethostbyname_with_timeout_callback (void *arg) other than timeout, errno is reset. */ static struct hostent * -gethostbyname_with_timeout (const char *host_name, int timeout) +gethostbyname_with_timeout (const char *host_name, double timeout) { struct ghbnwt_context ctx; ctx.host_name = host_name; @@ -533,7 +533,7 @@ getaddrinfo_with_timeout_callback (void *arg) static int getaddrinfo_with_timeout (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res, - int timeout) + double timeout) { struct gaiwt_context ctx; ctx.node = node; @@ -670,7 +670,8 @@ lookup_host (const char *host, int silent) } #else { - struct hostent *hptr = gethostbyname_with_timeout (host, opt.timeout); + struct hostent *hptr; + hptr = gethostbyname_with_timeout (host, opt.timeout); if (!hptr) { if (!silent) diff --git a/src/init.c b/src/init.c index 59a2aab9..321e2d42 100644 --- a/src/init.c +++ b/src/init.c @@ -856,51 +856,89 @@ cmd_bytes (const char *com, const char *val, void *closure) return 1; } -/* Store the value of VAL to *OUT, allowing suffixes for minutes and - hours. */ +/* Store the value of VAL to *OUT. The value is a time period, by + default expressed in seconds. */ + static int cmd_time (const char *com, const char *val, void *closure) { - long result = 0; - const char *p = val; + double result, mult, divider; + int seen_dot, seen_digit; - /* Search for digits and construct result. */ - for (; *p && ISDIGIT (*p); p++) - result = (10 * result) + (*p - '0'); - /* If no digits were found, or more than one character is following - them, bail out. */ - if (p == val || (*p != '\0' && *(p + 1) != '\0')) + const char *p; + const char *end = val + strlen (val); + + /* Skip trailing whitespace. */ + while (end > val && ISSPACE (end[-1])) + --end; + + if (val == end) { - printf (_("%s: Invalid specification `%s'\n"), com, val); + err: + fprintf (stderr, _("%s: Invalid time specification `%s'\n"), com, val); return 0; } - /* Search for a suffix. */ - switch (TOLOWER (*p)) + + switch (TOLOWER (end[-1])) { - case '\0': - /* None */ + case 's': + --end, mult = 1; /* seconds */ break; case 'm': - /* Minutes */ - result *= 60; + --end, mult = 60; /* minutes */ break; case 'h': - /* Seconds */ - result *= 3600; + --end, mult = 3600; /* hours */ break; case 'd': - /* Days (overflow on 16bit machines) */ - result *= 86400L; + --end, mult = 86400; /* days */ break; case 'w': - /* Weeks :-) */ - result *= 604800L; + --end, mult = 604800; /* weeks */ break; default: - printf (_("%s: Invalid specification `%s'\n"), com, val); - return 0; + /* Not a recognized suffix: treat it as part of number, and + assume seconds. */ + mult = 1; + } + + /* Skip leading and trailing whitespace. */ + while (val < end && ISSPACE (*val)) + ++val; + while (val > end && ISSPACE (end[-1])) + --end; + if (val == end) + goto err; + + /* Poor man's strtod: */ + result = 0; + seen_dot = seen_digit = 0; + divider = 1; + + p = val; + while (p < end) + { + char ch = *p++; + if (ISDIGIT (ch)) + { + if (!seen_dot) + result = (10 * result) + (ch - '0'); + else + result += (ch - '0') / (divider *= 10); + seen_digit = 1; + } + else if (ch == '.') + { + if (!seen_dot) + seen_dot = 1; + else + goto err; + } } - *(long *)closure = result; + if (!seen_digit) + goto err; + result *= mult; + *(double *)closure = result; return 1; } diff --git a/src/mswindows.c b/src/mswindows.c index 53219812..6cfc0555 100644 --- a/src/mswindows.c +++ b/src/mswindows.c @@ -74,7 +74,8 @@ sleep (unsigned seconds) /* Emulation of Unix usleep(). This has a granularity of milliseconds, but that's ok because: - a) Wget is only using it with milliseconds; + a) Wget is only using it with milliseconds [not anymore, but b) + still applies]; b) You can't rely on usleep's granularity anyway. If a caller expects usleep to respect every microsecond, he's in for a diff --git a/src/mswindows.h b/src/mswindows.h index 9a7a97f0..72fe8e96 100644 --- a/src/mswindows.h +++ b/src/mswindows.h @@ -133,5 +133,6 @@ void ws_changetitle (char*, int); char *ws_mypath (void); void ws_help (const char *); void windows_main_junk (int *, char **, char **); +int usleep (unsigned long); #endif /* MSWINDOWS_H */ diff --git a/src/options.h b/src/options.h index 5cb749f0..7b67169c 100644 --- a/src/options.h +++ b/src/options.h @@ -108,12 +108,11 @@ struct options char *proxy_user; /*oli*/ char *proxy_passwd; #ifdef HAVE_SELECT - long timeout; /* The value of read timeout in - seconds. */ + double timeout; /* The read/connect/DNS timeout. */ #endif int random_wait; /* vary from 0 .. wait secs by random()? */ - long wait; /* The wait period between retrievals. */ - long waitretry; /* The wait period between retries. - HEH */ + double wait; /* The wait period between retrievals. */ + double waitretry; /* The wait period between retries. - HEH */ int use_robots; /* Do we heed robots.txt? */ long limit_rate; /* Limit the download rate to this diff --git a/src/retr.c b/src/retr.c index 24b0782b..05111562 100644 --- a/src/retr.c +++ b/src/retr.c @@ -80,7 +80,7 @@ limit_bandwidth_reset (void) /* Limit the bandwidth by pausing the download for an amount of time. BYTES is the number of bytes received from the network, and DELTA - is how long it took to receive them. */ + is the number of milliseconds it took to receive them. */ static void limit_bandwidth (long bytes, double delta) @@ -648,7 +648,7 @@ sleep_between_retrievals (int count) if (count <= opt.waitretry) sleep (count - 1); else - sleep (opt.waitretry); + usleep (1000000L * opt.waitretry); } else if (opt.wait) { @@ -656,19 +656,16 @@ sleep_between_retrievals (int count) /* If random-wait is not specified, or if we are sleeping between retries of the same download, sleep the fixed interval. */ - sleep (opt.wait); + usleep (1000000L * opt.wait); else { /* Sleep a random amount of time averaging in opt.wait seconds. The sleeping amount ranges from 0 to opt.wait*2, inclusive. */ - int waitsecs = random_number (opt.wait * 2 + 1); - - DEBUGP (("sleep_between_retrievals: norm=%ld,fuzz=%ld,sleep=%d\n", - opt.wait, waitsecs - opt.wait, waitsecs)); - - if (waitsecs) - sleep (waitsecs); + double waitsecs = 2 * opt.wait * random_float (); + DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n", + opt.wait, waitsecs)); + usleep (1000000L * waitsecs); } } } diff --git a/src/sysdep.h b/src/sysdep.h index 271c5453..c47a243f 100644 --- a/src/sysdep.h +++ b/src/sysdep.h @@ -154,7 +154,8 @@ do { \ # define VERY_LONG_TYPE unsigned long long #endif /* use long long */ -/* Defined in cmpt.c: */ +/* These are defined in cmpt.c if missing, therefore it's generally + safe to declare their parameters. */ #ifndef HAVE_STRERROR char *strerror (); #endif @@ -174,7 +175,7 @@ char *strptime (); int vsnprintf (); #endif #ifndef HAVE_USLEEP -int usleep (); +int usleep PARAMS ((unsigned long)); #endif #ifndef HAVE_MEMMOVE void *memmove (); diff --git a/src/utils.c b/src/utils.c index bb45665f..85274e99 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1879,6 +1879,22 @@ random_number (int max) return (int)bounded; } +/* Return a random uniformly distributed floating point number in the + [0, 1) range. The precision of returned numbers is 9 digits. + + Modify this to use erand48() where available! */ + +double +random_float (void) +{ + /* We can't rely on any specific value of RAND_MAX, but I'm pretty + sure it's greater than 1000. */ + int rnd1 = random_number (1000); + int rnd2 = random_number (1000); + int rnd3 = random_number (1000); + return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0; +} + #if 0 /* A debugging function for checking whether an MD5 library works. */ @@ -1950,7 +1966,7 @@ abort_run_with_timeout (int sig) #endif /* USE_SIGNAL_TIMEOUT */ int -run_with_timeout (long timeout, void (*fun) (void *), void *arg) +run_with_timeout (double timeout, void (*fun) (void *), void *arg) { #ifndef USE_SIGNAL_TIMEOUT fun (arg); @@ -1964,6 +1980,13 @@ run_with_timeout (long timeout, void (*fun) (void *), void *arg) return 0; } + /* Calling alarm() rounds TIMEOUT. If it is smaller than 1, round + it to 1, not to 0, because alarm(0) means "never deliver the + alarm", i.e. "wait forever", which is not what someone who + specifies a 0.5s timeout would expect. */ + if (timeout < 1) + timeout = 1; + signal (SIGALRM, abort_run_with_timeout); if (SETJMP (run_with_timeout_env) != 0) { @@ -1971,7 +1994,7 @@ run_with_timeout (long timeout, void (*fun) (void *), void *arg) signal (SIGALRM, SIG_DFL); return 1; } - alarm (timeout); + alarm ((int) timeout); fun (arg); /* Preserve errno in case alarm() or signal() modifies it. */ @@ -1983,4 +2006,3 @@ run_with_timeout (long timeout, void (*fun) (void *), void *arg) return 0; #endif } - diff --git a/src/utils.h b/src/utils.h index 18752a5f..0783602d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -116,7 +116,8 @@ char *html_quote_string PARAMS ((const char *)); int determine_screen_width PARAMS ((void)); int random_number PARAMS ((int)); +double random_float PARAMS ((void)); -int run_with_timeout PARAMS ((long, void (*) (void *), void *)); +int run_with_timeout PARAMS ((double, void (*) (void *), void *)); #endif /* UTILS_H */ -- 2.39.2