X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fprogress.c;h=be841590abee1379139f7cd13e69918cbc68876f;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hp=27501c6739b044fea6187ba185c606a3e2321e86;hpb=40f4de9ae9d4e6527b6e04c76f3a309cc94325a6;p=wget diff --git a/src/progress.c b/src/progress.c index 27501c67..be841590 100644 --- a/src/progress.c +++ b/src/progress.c @@ -1,11 +1,11 @@ /* Download progress. - Copyright (C) 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 2001-2006 Free Software Foundation, Inc. This file is part of GNU Wget. GNU Wget is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Wget is distributed in the hope that it will be useful, @@ -14,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +along with Wget. If not, see . In addition, as a special exception, the Free Software Foundation gives permission to link the code of its release of Wget with the @@ -175,7 +174,7 @@ progress_interactive_p (void *progress) } /* Inform the progress gauge of newly received bytes. DLTIME is the - time in milliseconds since the beginning of the download. */ + time since the beginning of the download. */ void progress_update (void *progress, wgint howmuch, double dltime) @@ -306,7 +305,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) bytes_this_row -= dp->initial_length % ROW_BYTES; rate = calc_rate (bytes_this_row, dltime - dp->last_timer_value, &units); logprintf (LOG_VERBOSE, " %4.*f%c", - rate >= 100 ? 0 : rate >= 9.995 ? 1 : 2, + rate >= 99.95 ? 0 : rate >= 9.995 ? 1 : 2, rate, names[units]); dp->last_timer_value = dltime; } @@ -320,20 +319,20 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) wgint bytes_remaining = dp->total_length - bytes_displayed; /* The quantity downloaded in this download run. */ wgint bytes_sofar = bytes_displayed - dp->initial_length; - double secs_sofar = dltime / 1000; - int eta = (int) (secs_sofar * bytes_remaining / bytes_sofar + 0.5); - logprintf (LOG_VERBOSE, " %s", eta_to_human_short (eta, true)); + double eta = dltime * bytes_remaining / bytes_sofar; + if (eta < INT_MAX - 1) + logprintf (LOG_VERBOSE, " %s", + eta_to_human_short ((int) (eta + 0.5), true)); } } else { /* When done, print the total download time */ - double secs = dltime / 1000; - if (secs >= 10) + if (dltime >= 10) logprintf (LOG_VERBOSE, "=%s", - eta_to_human_short ((int) (secs + 0.5), true)); + eta_to_human_short ((int) (dltime + 0.5), true)); else - logprintf (LOG_VERBOSE, "=%ss", print_decimal (secs)); + logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime)); } } @@ -362,10 +361,6 @@ dot_update (void *progress, wgint howmuch, double dltime) ++dp->dots; if (dp->dots >= opt.dots_in_line) { - wgint row_qty = ROW_BYTES; - if (dp->rows == dp->initial_length / ROW_BYTES) - row_qty -= dp->initial_length % ROW_BYTES; - ++dp->rows; dp->dots = 0; @@ -482,12 +477,20 @@ static volatile sig_atomic_t received_sigwinch; sample is at least 150ms long, which means that, over the course of 20 samples, "current" download speed spans at least 3s into the past. */ -#define DLSPEED_SAMPLE_MIN 150 +#define DLSPEED_SAMPLE_MIN 0.15 /* 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 +#define STALL_START_TIME 5 + +/* Time between screen refreshes will not be shorter than this, so + that Wget doesn't swamp the TTY with output. */ +#define REFRESH_INTERVAL 0.2 + +/* Don't refresh the ETA too often to avoid jerkiness in predictions. + This allows ETA to change approximately once per second. */ +#define ETA_REFRESH_INTERVAL 0.99 struct bar_progress { wgint initial_length; /* how many bytes have been downloaded @@ -517,12 +520,12 @@ struct bar_progress { details. */ struct bar_progress_hist { int pos; - wgint times[DLSPEED_HISTORY_SIZE]; + double times[DLSPEED_HISTORY_SIZE]; wgint bytes[DLSPEED_HISTORY_SIZE]; /* The sum of times and bytes respectively, maintained for efficiency. */ - wgint total_time; + double total_time; wgint total_bytes; } hist; @@ -622,7 +625,7 @@ bar_update (void *progress, wgint howmuch, double dltime) received_sigwinch = 0; } - if (dltime - bp->last_screen_update < 200 && !force_screen_update) + if (dltime - bp->last_screen_update < REFRESH_INTERVAL && !force_screen_update) /* Don't update more often than five times per second. */ return; @@ -712,7 +715,7 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime) 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; + recent_age = 1; } /* Store "recent" bytes and download time to history ring at the @@ -747,8 +750,14 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime) sumt += hist->times[i]; sumb += hist->bytes[i]; } - assert (sumt == hist->total_time); assert (sumb == hist->total_bytes); + /* We can't use assert(sumt==hist->total_time) because some + precision is lost by adding and subtracting floating-point + numbers. But during a download this precision should not be + detectable, i.e. no larger than 1ns. */ + double diff = sumt - hist->total_time; + if (diff < 0) diff = -diff; + assert (diff < 1e-9); } #endif } @@ -791,13 +800,13 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) "xx% " or "100%" - percentage - 4 chars "[]" - progress bar decorations - 2 chars " nnn,nnn,nnn" - downloaded bytes - 12 chars or very rarely more - " 1012.56K/s" - dl rate - 11 chars + " 12.5K/s" - download rate - 8 chars " eta 36m 51s" - ETA - 13 chars "=====>..." - progress bar - the rest */ int dlbytes_size = 1 + MAX (size_grouped_len, 11); - int progress_size = bp->width - (4 + 2 + dlbytes_size + 11 + 13); + int progress_size = bp->width - (4 + 2 + dlbytes_size + 8 + 13); if (progress_size < 5) progress_size = 0; @@ -882,8 +891,8 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) sprintf (p, " %-11s", size_grouped); move_to_end (p); - /* " 1012.45K/s" */ - if (hist->total_time && hist->total_bytes) + /* " 12.52K/s" */ + if (hist->total_time > 0 && hist->total_bytes) { static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" }; int units = 0; @@ -892,18 +901,19 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) wgint dlquant = hist->total_bytes + bp->recent_bytes; double dltime = hist->total_time + (dl_total_time - bp->recent_start); double dlspeed = calc_rate (dlquant, dltime, &units); - sprintf (p, " %7.2f%s", dlspeed, short_units[units]); + sprintf (p, " %4.*f%s", dlspeed >= 99.95 ? 0 : dlspeed >= 9.995 ? 1 : 2, + dlspeed, short_units[units]); move_to_end (p); } else - APPEND_LITERAL (" --.--K/s"); + APPEND_LITERAL (" --.-K/s"); if (!done) { /* " eta ..m ..s"; wait for three seconds before displaying the ETA. That's because the ETA value needs a while to become reliable. */ - if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3000) + if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3) { int eta; @@ -912,7 +922,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) any value to the user. */ if (bp->total_length != size && bp->last_eta_value != 0 - && dl_total_time - bp->last_eta_time < 900) + && dl_total_time - bp->last_eta_time < ETA_REFRESH_INTERVAL) eta = bp->last_eta_value; else { @@ -922,9 +932,11 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) hist->total_time and bp->count with hist->total_bytes. I found that doing that results in a very jerky and ultimately unreliable ETA. */ - double time_sofar = (double) dl_total_time / 1000; wgint bytes_remaining = bp->total_length - size; - eta = (int) (time_sofar * bytes_remaining / bp->count + 0.5); + double eta_ = dl_total_time * bytes_remaining / bp->count; + if (eta_ >= INT_MAX - 1) + goto skip_eta; + eta = (int) (eta_ + 0.5); bp->last_eta_value = eta; bp->last_eta_time = dl_total_time; } @@ -936,21 +948,22 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) } else if (bp->total_length > 0) { + skip_eta: APPEND_LITERAL (" "); } } else { /* When the download is done, print the elapsed time. */ - double secs = dl_total_time / 1000; + /* Note to translators: this should not take up more room than available here. Abbreviate if necessary. */ strcpy (p, _(" in ")); move_to_end (p); /* not p+=6, think translations! */ - if (secs >= 10) - strcpy (p, eta_to_human_short ((int) (secs + 0.5), false)); + if (dl_total_time >= 10) + strcpy (p, eta_to_human_short ((int) (dl_total_time + 0.5), false)); else - sprintf (p, "%ss", print_decimal (secs)); + sprintf (p, "%ss", print_decimal (dl_total_time)); move_to_end (p); } @@ -1051,7 +1064,7 @@ eta_to_human_short (int secs, bool condensed) sprintf (buf, "%ds", secs); else if (secs < 100 * 60) sprintf (buf, "%dm%s%ds", secs / 60, space, secs % 60); - else if (secs < 100 * 3600) + else if (secs < 48 * 3600) sprintf (buf, "%dh%s%dm", secs / 3600, space, (secs / 60) % 60); else if (secs < 100 * 86400) sprintf (buf, "%dd%s%dh", secs / 86400, space, (secs / 3600) % 60);