1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Adjust bandwidth limitation sleep for the error of previous sleeps.

Allow decimal numbers in bandwidth limit specification.
This commit is contained in:
hniksic 2003-09-20 21:05:12 -07:00
parent 0bc3dc073f
commit b8e416c6c7
4 changed files with 145 additions and 98 deletions

3
NEWS
View File

@ -52,7 +52,8 @@ as "//img.foo.com/foo.jpg".
values "yes" and "no" along with the traditional "on" and "off".
** It is now possible to specify decimal values for --timeout, --wait,
and --waitretry. For instance, `--wait=0.5' now works as expected.
--waitretry, and --limit-rate. For instance, `--wait=0.5' now
works as expected, and so does --limit-rate=2.5k.
* Wget 1.8.2 is a bugfix release with no user-visible changes.

View File

@ -1,3 +1,13 @@
2003-09-21 Hrvoje Niksic <hniksic@xemacs.org>
* init.c (simple_atof): New function.
(cmd_time): Use it.
(cmd_bytes): Accept things like "1.5k" and such. Use simple_atof
to parse decimals.
* retr.c (limit_bandwidth): Adjust each sleep by the error of the
previous one.
2003-09-21 Hrvoje Niksic <hniksic@xemacs.org>
* main.c (main): Use setoptval() for setting the options. Use

View File

@ -839,64 +839,115 @@ cmd_directory_vector (const char *com, const char *val, void *closure)
return 1;
}
/* Set the value stored in VAL to CLOSURE (which should point to a
long int), allowing several postfixes, with the following syntax
(regexp):
/* Poor man's atof: handles only <digits>.<digits>. Returns 1 on
success, 0 on failure. In case of success, stores its result to
*DEST. */
[0-9]+ -> bytes
[0-9]+[kK] -> bytes * 1024
[0-9]+[mM] -> bytes * 1024 * 1024
inf -> 0
static int
simple_atof (const char *beg, const char *end, double *dest)
{
double result = 0;
int seen_dot = 0;
int seen_digit = 0;
double divider = 1;
const char *p = beg;
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
return 0;
}
}
if (!seen_digit)
return 0;
*dest = result;
return 1;
}
/* Parse VAL as a number and set its value to CLOSURE (which should
point to a long int).
By default, the value is assumed to be in bytes. If "K", "M", or
"G" are appended, the value is multiplied with 1<<10, 1<<20, or
1<<30, respectively. Floating point values are allowed and are
cast to integer before use. The idea is to be able to use things
like 1.5k instead of "1536".
The string "inf" is returned as 0.
In case of error, 0 is returned and memory pointed to by CLOSURE
remains unmodified. */
Anything else is flagged as incorrect, and CLOSURE is unchanged. */
static int
cmd_bytes (const char *com, const char *val, void *closure)
{
long result;
long *out = (long *)closure;
const char *p;
long mult;
double number;
const char *end = val + strlen (val);
result = 0;
p = val;
/* Check for "inf". */
if (p[0] == 'i' && p[1] == 'n' && p[2] == 'f' && p[3] == '\0')
if (0 == strcmp (val, "inf"))
{
*out = 0;
*(long *)closure = 0;
return 1;
}
/* 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'))
/* Strip trailing whitespace. */
while (val < end && ISSPACE (end[-1]))
--end;
if (val == end)
{
printf (_("%s: Invalid specification `%s'\n"), com, val);
err:
fprintf (stderr, _("%s: Invalid byte value `%s'\n"), com, val);
return 0;
}
/* Search for a designator. */
switch (TOLOWER (*p))
switch (TOLOWER (end[-1]))
{
case '\0':
/* None */
break;
case 'k':
/* Kilobytes */
result *= 1024;
--end, mult = 1L<<10;
break;
case 'm':
/* Megabytes */
result *= (long)1024 * 1024;
--end, mult = 1L<<20;
break;
case 'g':
/* Gigabytes */
result *= (long)1024 * 1024 * 1024;
--end, mult = 1L<<30;
break;
default:
printf (_("%s: Invalid specification `%s'\n"), com, val);
return 0;
/* Not a recognized suffix: assume it belongs to the number.
(If not, atof simple_atof will raise an error.) */
mult = 1;
}
*out = result;
/* Skip leading and trailing whitespace. */
while (val < end && ISSPACE (*val))
++val;
while (val < end && ISSPACE (end[-1]))
--end;
if (val == end)
goto err;
if (!simple_atof (val, end, &number))
goto err;
*(long *)closure = (long)(number * mult);
return 1;
}
@ -907,14 +958,11 @@ cmd_bytes (const char *com, const char *val, void *closure)
static int
cmd_time (const char *com, const char *val, void *closure)
{
double result, mult, divider;
int seen_dot, seen_digit;
const char *p;
double number, mult;
const char *end = val + strlen (val);
/* Skip trailing whitespace. */
while (end > val && ISSPACE (end[-1]))
/* Strip trailing whitespace. */
while (val < end && ISSPACE (end[-1]))
--end;
if (val == end)
@ -936,54 +984,29 @@ cmd_time (const char *com, const char *val, void *closure)
--end, mult = 3600; /* hours */
break;
case 'd':
--end, mult = 86400; /* days */
--end, mult = 86400.0; /* days */
break;
case 'w':
--end, mult = 604800; /* weeks */
--end, mult = 604800.0; /* weeks */
break;
default:
/* Not a recognized suffix: treat it as part of number, and
assume seconds. */
/* Not a recognized suffix: assume it belongs to the number.
(If not, atof simple_atof will raise an error.) */
mult = 1;
}
/* Skip leading and trailing whitespace. */
while (val < end && ISSPACE (*val))
++val;
while (val > end && ISSPACE (end[-1]))
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;
if (!simple_atof (val, end, &number))
goto err;
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;
}
}
if (!seen_digit)
goto err;
result *= mult;
*(double *)closure = result;
*(double *)closure = number * mult;
return 1;
}

View File

@ -67,15 +67,16 @@ int global_download_count;
static struct {
long bytes;
double dltime;
long chunk_bytes;
double chunk_start;
double sleep_adjust;
} limit_data;
static void
limit_bandwidth_reset (void)
{
limit_data.bytes = 0;
limit_data.dltime = 0;
limit_data.chunk_bytes = 0;
limit_data.chunk_start = 0;
}
/* Limit the bandwidth by pausing the download for an amount of time.
@ -83,30 +84,48 @@ limit_bandwidth_reset (void)
is the number of milliseconds it took to receive them. */
static void
limit_bandwidth (long bytes, double delta)
limit_bandwidth (long bytes, double *dltime, struct wget_timer *timer)
{
double delta_t = *dltime - limit_data.chunk_start;
double expected;
limit_data.bytes += bytes;
limit_data.dltime += delta;
limit_data.chunk_bytes += bytes;
expected = 1000.0 * limit_data.bytes / opt.limit_rate;
/* Calculate the amount of time we expect downloading the chunk
should take. If in reality it took less time, sleep to
compensate for the difference. */
expected = 1000.0 * limit_data.chunk_bytes / opt.limit_rate;
if (expected > limit_data.dltime)
if (expected > delta_t)
{
double slp = expected - limit_data.dltime;
double slp = expected - delta_t + limit_data.sleep_adjust;
double t0, t1;
if (slp < 200)
{
DEBUGP (("deferring a %.2f ms sleep (%ld/%.2f).\n",
slp, limit_data.bytes, limit_data.dltime));
slp, limit_data.chunk_bytes, delta_t));
return;
}
DEBUGP (("sleeping %.2f ms\n", slp));
DEBUGP (("\nsleeping %.2f ms for %ld bytes, adjust %.2f ms\n",
slp, limit_data.chunk_bytes, limit_data.sleep_adjust));
t0 = *dltime;
usleep ((unsigned long) (1000 * slp));
t1 = wtimer_elapsed (timer);
/* Due to scheduling, we probably slept slightly longer (or
shorter) than desired. Calculate the difference between the
desired and the actual sleep, and adjust the next sleep by
that amount. */
limit_data.sleep_adjust = slp - (t1 - t0);
/* Since we've called wtimer_elapsed, we might as well update
the caller's dltime. */
*dltime = t1;
}
limit_data.bytes = 0;
limit_data.dltime = 0;
limit_data.chunk_bytes = 0;
limit_data.chunk_start = *dltime;
}
#define MIN(i, j) ((i) <= (j) ? (i) : (j))
@ -143,7 +162,7 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
void *progress = NULL;
struct wget_timer *timer = wtimer_allocate ();
double dltime = 0, last_dltime = 0;
double dltime = 0;
*len = restval;
@ -210,15 +229,9 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
goto out;
}
/* If bandwidth is not limited, one call to wtimer_elapsed is
sufficient. */
dltime = wtimer_elapsed (timer);
if (opt.limit_rate)
{
limit_bandwidth (res, dltime - last_dltime);
dltime = wtimer_elapsed (timer);
last_dltime = dltime;
}
limit_bandwidth (res, &dltime, timer);
if (progress)
progress_update (progress, res, dltime);