}
/* 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 the number of milliseconds it took to receive them. */
+ BYTES is the number of bytes received from the network, and TIMER
+ is the timer that started at the beginning of download. */
static void
-limit_bandwidth (long bytes, double *dltime, struct wget_timer *timer)
+limit_bandwidth (long bytes, struct wget_timer *timer)
{
- double delta_t = *dltime - limit_data.chunk_start;
+ double delta_t = wtimer_read (timer) - limit_data.chunk_start;
double expected;
limit_data.chunk_bytes += bytes;
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);
+ t0 = wtimer_read (timer);
+ xsleep (slp / 1000);
+ wtimer_update (timer);
+ t1 = wtimer_read (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.chunk_bytes = 0;
- limit_data.chunk_start = *dltime;
+ limit_data.chunk_start = wtimer_read (timer);
}
#define MIN(i, j) ((i) <= (j) ? (i) : (j))
static char dlbuf[16384];
int dlbufsize = sizeof (dlbuf);
- void *progress = NULL;
struct wget_timer *timer = wtimer_allocate ();
- double dltime = 0;
+ double last_successful_read_tm;
+
+ /* The progress gauge, set according to the user preferences. */
+ void *progress = NULL;
+
+ /* Non-zero if the progress gauge is interactive, i.e. if it can
+ continually update the display. When true, smaller timeout
+ values are used so that the gauge can update the display when
+ data arrives slowly. */
+ int progress_interactive = 0;
*len = restval;
if (opt.verbose)
- progress = progress_create (restval, expected);
+ {
+ progress = progress_create (restval, expected);
+ progress_interactive = progress_interactive_p (progress);
+ }
if (rbuf && RBUF_FD (rbuf) == fd)
{
if (opt.limit_rate)
limit_bandwidth_reset ();
wtimer_reset (timer);
+ last_successful_read_tm = 0;
/* Use a smaller buffer for low requested bandwidths. For example,
with --limit-rate=2k, it doesn't make sense to slurp in 16K of
{
int amount_to_read = (use_expected
? MIN (expected - *len, dlbufsize) : dlbufsize);
-#ifdef HAVE_SSL
- if (rbuf->ssl!=NULL)
- res = ssl_iread (rbuf->ssl, dlbuf, amount_to_read);
- else
-#endif /* HAVE_SSL */
- res = iread (fd, dlbuf, amount_to_read);
+ double tmout = opt.read_timeout;
+ if (progress_interactive)
+ {
+ double waittm;
+ /* For interactive progress gauges, always specify a ~1s
+ timeout, so that the gauge can be updated regularly even
+ when the data arrives very slowly or stalls. */
+ tmout = 0.95;
+ waittm = (wtimer_read (timer) - last_successful_read_tm) / 1000;
+ if (waittm + tmout > opt.read_timeout)
+ {
+ /* Don't allow waiting for data to exceed read timeout. */
+ tmout = opt.read_timeout - waittm;
+ if (tmout < 0)
+ {
+ /* We've already exceeded the timeout. */
+ res = -1;
+ errno = ETIMEDOUT;
+ break;
+ }
+ }
+ }
+ res = xread (fd, dlbuf, amount_to_read, tmout);
- if (res <= 0)
+ if (res == 0 || (res < 0 && errno != ETIMEDOUT))
break;
+ else if (res < 0)
+ res = 0; /* timeout */
- fwrite (dlbuf, 1, res, fp);
- /* Always flush the contents of the network packet. This should
- not hinder performance: fast downloads will be received in
- 16K chunks (which stdio would write out anyway), and slow
- downloads won't be limited with disk performance. */
- fflush (fp);
- if (ferror (fp))
+ wtimer_update (timer);
+ if (res > 0)
{
- res = -2;
- goto out;
+ fwrite (dlbuf, 1, res, fp);
+ /* Always flush the contents of the network packet. This
+ should not hinder performance: fast downloads will be
+ received in 16K chunks (which stdio would write out
+ anyway), and slow downloads won't be limited by disk
+ performance. */
+ fflush (fp);
+ if (ferror (fp))
+ {
+ res = -2;
+ goto out;
+ }
+ last_successful_read_tm = wtimer_read (timer);
}
- dltime = wtimer_elapsed (timer);
if (opt.limit_rate)
- limit_bandwidth (res, &dltime, timer);
+ limit_bandwidth (res, timer);
*len += res;
if (progress)
- progress_update (progress, res, dltime);
+ progress_update (progress, res, wtimer_read (timer));
#ifdef WINDOWS
if (use_expected && expected > 0)
ws_percenttitle (100.0 * (double)(*len) / (double)expected);
out:
if (progress)
- progress_finish (progress, dltime);
+ progress_finish (progress, wtimer_read (timer));
if (elapsed)
- *elapsed = dltime;
+ *elapsed = wtimer_read (timer);
wtimer_delete (timer);
return res;
/* If opt.waitretry is specified and this is a retry, wait for
COUNT-1 number of seconds, or for opt.waitretry seconds. */
if (count <= opt.waitretry)
- sleep (count - 1);
+ xsleep (count - 1);
else
- usleep (1000000L * opt.waitretry);
+ xsleep (opt.waitretry);
}
else if (opt.wait)
{
/* If random-wait is not specified, or if we are sleeping
between retries of the same download, sleep the fixed
interval. */
- usleep (1000000L * opt.wait);
+ xsleep (opt.wait);
else
{
/* Sleep a random amount of time averaging in opt.wait
double waitsecs = 2 * opt.wait * random_float ();
DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n",
opt.wait, waitsecs));
- usleep (1000000L * waitsecs);
+ xsleep (waitsecs);
}
}
}