mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Update the progress gauge even when the data does not arrive.
This commit is contained in:
parent
cb393a062d
commit
94ca33d2fb
@ -1,3 +1,12 @@
|
||||
2003-11-08 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* progress.c (update_speed_ring): Clear the speed ring when the
|
||||
download stalls.
|
||||
|
||||
* retr.c (get_contents): Specify 0.95s read timeout, so that the
|
||||
progress gauge can be updated even when data arrives very slowly
|
||||
or stalls.
|
||||
|
||||
2003-11-08 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* utils.c (wtimer_allocate): Bless the use of wtimer_read on a
|
||||
|
@ -51,6 +51,7 @@ so, delete this exception statement from your version. */
|
||||
|
||||
struct progress_implementation {
|
||||
char *name;
|
||||
int interactive;
|
||||
void *(*create) PARAMS ((long, long));
|
||||
void (*update) PARAMS ((void *, long, double));
|
||||
void (*finish) PARAMS ((void *, double));
|
||||
@ -70,8 +71,8 @@ static void bar_finish PARAMS ((void *, double));
|
||||
static void bar_set_params PARAMS ((const char *));
|
||||
|
||||
static struct progress_implementation implementations[] = {
|
||||
{ "dot", dot_create, dot_update, dot_finish, dot_set_params },
|
||||
{ "bar", bar_create, bar_update, bar_finish, bar_set_params }
|
||||
{ "dot", 0, dot_create, dot_update, dot_finish, dot_set_params },
|
||||
{ "bar", 1, bar_create, bar_update, bar_finish, bar_set_params }
|
||||
};
|
||||
static struct progress_implementation *current_impl;
|
||||
static int current_impl_locked;
|
||||
@ -168,6 +169,17 @@ progress_create (long initial, long total)
|
||||
return current_impl->create (initial, total);
|
||||
}
|
||||
|
||||
/* Return non-zero if the progress gauge is "interactive", i.e. if it
|
||||
can profit from being called regularly even in absence of data.
|
||||
The progress bar is interactive because it regularly updates the
|
||||
ETA and current update. */
|
||||
|
||||
int
|
||||
progress_interactive_p (void *progress)
|
||||
{
|
||||
return current_impl->interactive;
|
||||
}
|
||||
|
||||
/* Inform the progress gauge of newly received bytes. DLTIME is the
|
||||
time in milliseconds since the beginning of the download. */
|
||||
|
||||
@ -425,6 +437,11 @@ static volatile sig_atomic_t received_sigwinch;
|
||||
past. */
|
||||
#define DLSPEED_SAMPLE_MIN 150
|
||||
|
||||
/* The time after which the download starts to be considered
|
||||
"stalled", i.e. the current bandwidth is not printed and the recent
|
||||
download speeds are scratched. */
|
||||
#define STALL_START_TIME 5000
|
||||
|
||||
struct bar_progress {
|
||||
long initial_length; /* how many bytes have been downloaded
|
||||
previously. */
|
||||
@ -466,8 +483,12 @@ struct bar_progress {
|
||||
position. */
|
||||
long recent_bytes; /* bytes downloaded so far. */
|
||||
|
||||
int stalled; /* set when no data arrives for longer
|
||||
than STALL_START_TIME, then reset
|
||||
when new data arrives. */
|
||||
|
||||
/* create_image() uses these to make sure that ETA information
|
||||
doesn't flash. */
|
||||
doesn't flicker. */
|
||||
double last_eta_time; /* time of the last update to download
|
||||
speed and ETA, measured since the
|
||||
beginning of download. */
|
||||
@ -615,6 +636,38 @@ update_speed_ring (struct bar_progress *bp, long howmuch, double dltime)
|
||||
if (recent_age < DLSPEED_SAMPLE_MIN)
|
||||
return;
|
||||
|
||||
if (howmuch == 0)
|
||||
{
|
||||
/* If we're not downloading anything, we might be stalling,
|
||||
i.e. not downloading anything for an extended period of time.
|
||||
Since 0-reads do not enter the history ring, recent_age
|
||||
effectively measures the time since last read. */
|
||||
if (recent_age >= STALL_START_TIME)
|
||||
{
|
||||
/* If we're stalling, reset the ring contents because it's
|
||||
stale and because it will make bar_update stop printing
|
||||
the (bogus) current bandwidth. */
|
||||
bp->stalled = 1;
|
||||
xzero (*hist);
|
||||
bp->recent_bytes = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* We now have a non-zero amount of to store to the speed ring. */
|
||||
|
||||
/* If the stall status was acquired, reset it. */
|
||||
if (bp->stalled)
|
||||
{
|
||||
bp->stalled = 0;
|
||||
/* "recent_age" includes the the entired stalled period, which
|
||||
could be very long. Don't update the speed ring with that
|
||||
value because the current bandwidth would start too small.
|
||||
Start with an arbitrary (but more reasonable) time value and
|
||||
let it level out. */
|
||||
recent_age = 1000;
|
||||
}
|
||||
|
||||
/* Store "recent" bytes and download time to history ring at the
|
||||
position POS. */
|
||||
|
||||
@ -637,7 +690,7 @@ update_speed_ring (struct bar_progress *bp, long howmuch, double dltime)
|
||||
if (++hist->pos == DLSPEED_HISTORY_SIZE)
|
||||
hist->pos = 0;
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
/* Sledgehammer check to verify that the totals are accurate. */
|
||||
{
|
||||
int i;
|
||||
|
@ -35,6 +35,7 @@ void set_progress_implementation PARAMS ((const char *));
|
||||
void progress_schedule_redirect PARAMS ((void));
|
||||
|
||||
void *progress_create PARAMS ((long, long));
|
||||
int progress_interactive_p PARAMS ((void *));
|
||||
void progress_update PARAMS ((void *, long, double));
|
||||
void progress_finish PARAMS ((void *, double));
|
||||
|
||||
|
74
src/retr.c
74
src/retr.c
@ -161,13 +161,25 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
|
||||
static char dlbuf[16384];
|
||||
int dlbufsize = sizeof (dlbuf);
|
||||
|
||||
void *progress = NULL;
|
||||
struct wget_timer *timer = wtimer_allocate ();
|
||||
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)
|
||||
{
|
||||
@ -192,6 +204,7 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
|
||||
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
|
||||
@ -209,24 +222,53 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
|
||||
{
|
||||
int amount_to_read = (use_expected
|
||||
? MIN (expected - *len, dlbufsize) : dlbufsize);
|
||||
res = xread (fd, dlbuf, amount_to_read, -1);
|
||||
|
||||
if (res <= 0)
|
||||
break;
|
||||
|
||||
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))
|
||||
double tmout = opt.read_timeout;
|
||||
if (progress_interactive)
|
||||
{
|
||||
res = -2;
|
||||
goto out;
|
||||
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 || (res < 0 && errno != ETIMEDOUT))
|
||||
break;
|
||||
else if (res < 0)
|
||||
res = 0; /* timeout */
|
||||
|
||||
wtimer_update (timer);
|
||||
if (res > 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (opt.limit_rate)
|
||||
limit_bandwidth (res, timer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user