mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Include ETA information in dot progress.
This commit is contained in:
parent
276f66fc14
commit
e289d2ecc4
@ -1,3 +1,18 @@
|
||||
2005-06-29 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* main.c (secs_to_human_time): Use print_decimal when printing
|
||||
total download time in seconds.
|
||||
|
||||
* progress.c (print_row_stats): Use it to print total download
|
||||
time at the end of the download.
|
||||
(create_image): Ditto.
|
||||
|
||||
* utils.c (print_decimal): New function; print small decimal
|
||||
numbers with more precision than large ones.
|
||||
|
||||
* progress.c (print_row_stats): New function. Print ETA after the
|
||||
download rate at the end of each row.
|
||||
|
||||
2005-06-28 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* init.c (parse_line): Check for alphanumerics.
|
||||
|
@ -168,8 +168,8 @@ convert_all_links (void)
|
||||
|
||||
secs = ptimer_measure (timer) / 1000;
|
||||
ptimer_destroy (timer);
|
||||
logprintf (LOG_VERBOSE, _("Converted %d files in %.*f seconds.\n"),
|
||||
file_count, secs < 10 ? 3 : 1, secs);
|
||||
logprintf (LOG_VERBOSE, _("Converted %d files in %s seconds.\n"),
|
||||
file_count, print_decimal (secs));
|
||||
}
|
||||
|
||||
static void write_backup_file (const char *, downloaded_file_t);
|
||||
|
10
src/main.c
10
src/main.c
@ -643,16 +643,8 @@ secs_to_human_time (double interval)
|
||||
sprintf (buf, "%dh %dm %ds", hours, mins, secs);
|
||||
else if (mins)
|
||||
sprintf (buf, "%dm %ds", mins, secs);
|
||||
else if (interval >= 10)
|
||||
sprintf (buf, "%ds", secs);
|
||||
else
|
||||
/* For very quick downloads show more exact timing information. */
|
||||
sprintf (buf, "%.*fs",
|
||||
interval < 0.001 ? 0 : /* 0s instead of 0.000s */
|
||||
interval < 0.01 ? 3 : /* 0.00x */
|
||||
interval < 0.1 ? 2 : /* 0.0x */
|
||||
1, /* 0.x, 1.x, ..., 9.x */
|
||||
interval);
|
||||
sprintf (buf, "%ss", print_decimal (interval));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
169
src/progress.c
169
src/progress.c
@ -205,6 +205,7 @@ struct dot_progress {
|
||||
|
||||
int rows; /* number of rows printed so far */
|
||||
int dots; /* number of dots printed in this row */
|
||||
|
||||
double last_timer_value;
|
||||
};
|
||||
|
||||
@ -220,26 +221,28 @@ dot_create (wgint initial, wgint total)
|
||||
if (dp->initial_length)
|
||||
{
|
||||
int dot_bytes = opt.dot_bytes;
|
||||
wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
|
||||
const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
|
||||
|
||||
int remainder = dp->initial_length % row_bytes;
|
||||
int remainder = dp->initial_length % ROW_BYTES;
|
||||
wgint skipped = dp->initial_length - remainder;
|
||||
|
||||
if (skipped)
|
||||
{
|
||||
int skipped_k = skipped / 1024; /* skipped amount in K */
|
||||
wgint skipped_k = skipped / 1024; /* skipped amount in K */
|
||||
int skipped_k_len = numdigit (skipped_k);
|
||||
if (skipped_k_len < 5)
|
||||
skipped_k_len = 5;
|
||||
if (skipped_k_len < 6)
|
||||
skipped_k_len = 6;
|
||||
|
||||
/* Align the [ skipping ... ] line with the dots. To do
|
||||
that, insert the number of spaces equal to the number of
|
||||
digits in the skipped amount in K. */
|
||||
logprintf (LOG_VERBOSE, _("\n%*s[ skipping %dK ]"),
|
||||
2 + skipped_k_len, "", skipped_k);
|
||||
logprintf (LOG_VERBOSE, _("\n%*s[ skipping %sK ]"),
|
||||
2 + skipped_k_len, "",
|
||||
number_to_static_string (skipped_k));
|
||||
}
|
||||
|
||||
logprintf (LOG_VERBOSE, "\n%5ldK", (long) (skipped / 1024));
|
||||
logprintf (LOG_VERBOSE, "\n%6sK",
|
||||
number_to_static_string (skipped / 1024));
|
||||
for (; remainder >= dot_bytes; remainder -= dot_bytes)
|
||||
{
|
||||
if (dp->dots % opt.dot_spacing == 0)
|
||||
@ -250,28 +253,86 @@ dot_create (wgint initial, wgint total)
|
||||
assert (dp->dots < opt.dots_in_line);
|
||||
|
||||
dp->accumulated = remainder;
|
||||
dp->rows = skipped / row_bytes;
|
||||
dp->rows = skipped / ROW_BYTES;
|
||||
}
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
static void
|
||||
print_percentage (wgint bytes, wgint expected)
|
||||
{
|
||||
/* Round to the floor value in order to gauge how much data *has*
|
||||
been retrieved. 12.8% will round to 12% because the 13% mark has
|
||||
not yet been reached. 100% is only shown when done. */
|
||||
int percentage = 100.0 * bytes / expected;
|
||||
logprintf (LOG_VERBOSE, "%3d%%", percentage);
|
||||
}
|
||||
static const char *eta_to_human_short (int, bool);
|
||||
|
||||
/* Prints the stats (percentage of completion, speed, ETA) for current
|
||||
row. DLTIME is the time spent downloading the data in current
|
||||
row.
|
||||
|
||||
#### This function is somewhat uglified by the fact that current
|
||||
row and last row have somewhat different stats requirements. It
|
||||
might be worthwhile to split it to two different functions. */
|
||||
|
||||
static void
|
||||
print_download_speed (struct dot_progress *dp, wgint bytes, double dltime)
|
||||
print_row_stats (struct dot_progress *dp, double dltime, bool last)
|
||||
{
|
||||
logprintf (LOG_VERBOSE, " %7s",
|
||||
retr_rate (bytes, dltime - dp->last_timer_value));
|
||||
const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
|
||||
|
||||
/* bytes_displayed is the number of bytes indicated to the user by
|
||||
dots printed so far, includes the initially "skipped" amount */
|
||||
wgint bytes_displayed = dp->rows * ROW_BYTES + dp->dots * opt.dot_bytes;
|
||||
|
||||
if (last)
|
||||
/* For last row also count bytes accumulated after last dot */
|
||||
bytes_displayed += dp->accumulated;
|
||||
|
||||
if (dp->total_length)
|
||||
{
|
||||
/* Round to floor value to provide gauge how much data *has*
|
||||
been retrieved. 12.8% will round to 12% because the 13% mark
|
||||
has not yet been reached. 100% is only shown when done. */
|
||||
int percentage = 100.0 * bytes_displayed / dp->total_length;
|
||||
logprintf (LOG_VERBOSE, "%3d%%", percentage);
|
||||
}
|
||||
|
||||
{
|
||||
static char names[] = {' ', 'K', 'M', 'G'};
|
||||
int units;
|
||||
double rate;
|
||||
wgint bytes_this_row;
|
||||
if (!last)
|
||||
bytes_this_row = ROW_BYTES;
|
||||
else
|
||||
/* For last row also include bytes accumulated after last dot. */
|
||||
bytes_this_row = dp->dots * opt.dot_bytes + dp->accumulated;
|
||||
if (dp->rows == dp->initial_length / ROW_BYTES)
|
||||
/* Don't count the portion of the row belonging to initial_length */
|
||||
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, names[units]);
|
||||
dp->last_timer_value = dltime;
|
||||
}
|
||||
|
||||
if (!last)
|
||||
{
|
||||
if (dp->total_length)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When done, print the total download time */
|
||||
double secs = dltime / 1000;
|
||||
if (secs >= 10)
|
||||
logprintf (LOG_VERBOSE, "=%s",
|
||||
eta_to_human_short ((int) (secs + 0.5), true));
|
||||
else
|
||||
logprintf (LOG_VERBOSE, "=%ss", print_decimal (secs));
|
||||
}
|
||||
}
|
||||
|
||||
/* Dot-progress backend for progress_update. */
|
||||
@ -281,7 +342,7 @@ dot_update (void *progress, wgint howmuch, double dltime)
|
||||
{
|
||||
struct dot_progress *dp = progress;
|
||||
int dot_bytes = opt.dot_bytes;
|
||||
wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
|
||||
wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
|
||||
|
||||
log_set_flush (false);
|
||||
|
||||
@ -289,7 +350,8 @@ dot_update (void *progress, wgint howmuch, double dltime)
|
||||
for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes)
|
||||
{
|
||||
if (dp->dots == 0)
|
||||
logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024));
|
||||
logprintf (LOG_VERBOSE, "\n%6sK",
|
||||
number_to_static_string (dp->rows * ROW_BYTES / 1024));
|
||||
|
||||
if (dp->dots % opt.dot_spacing == 0)
|
||||
logputs (LOG_VERBOSE, " ");
|
||||
@ -298,16 +360,14 @@ 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;
|
||||
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;
|
||||
|
||||
if (dp->total_length)
|
||||
print_percentage (dp->rows * row_bytes, dp->total_length);
|
||||
print_download_speed (dp, row_qty, dltime);
|
||||
print_row_stats (dp, dltime, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,35 +380,22 @@ static void
|
||||
dot_finish (void *progress, double dltime)
|
||||
{
|
||||
struct dot_progress *dp = progress;
|
||||
int dot_bytes = opt.dot_bytes;
|
||||
wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
|
||||
wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
|
||||
int i;
|
||||
|
||||
log_set_flush (false);
|
||||
|
||||
if (dp->dots == 0)
|
||||
logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024));
|
||||
logprintf (LOG_VERBOSE, "\n%6sK",
|
||||
number_to_static_string (dp->rows * ROW_BYTES / 1024));
|
||||
for (i = dp->dots; i < opt.dots_in_line; i++)
|
||||
{
|
||||
if (i % opt.dot_spacing == 0)
|
||||
logputs (LOG_VERBOSE, " ");
|
||||
logputs (LOG_VERBOSE, " ");
|
||||
}
|
||||
if (dp->total_length)
|
||||
{
|
||||
print_percentage (dp->rows * row_bytes
|
||||
+ dp->dots * dot_bytes
|
||||
+ dp->accumulated,
|
||||
dp->total_length);
|
||||
}
|
||||
|
||||
{
|
||||
wgint row_qty = dp->dots * dot_bytes + dp->accumulated;
|
||||
if (dp->rows == dp->initial_length / row_bytes)
|
||||
row_qty -= dp->initial_length % row_bytes;
|
||||
print_download_speed (dp, row_qty, dltime);
|
||||
}
|
||||
|
||||
print_row_stats (dp, dltime, true);
|
||||
logputs (LOG_VERBOSE, "\n\n");
|
||||
log_set_flush (false);
|
||||
|
||||
@ -704,8 +751,6 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime)
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *eta_to_human_short (int);
|
||||
|
||||
#define APPEND_LITERAL(s) do { \
|
||||
memcpy (p, s, sizeof (s) - 1); \
|
||||
p += sizeof (s) - 1; \
|
||||
@ -884,7 +929,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
||||
|
||||
/* Translation note: "ETA" is English-centric, but this must
|
||||
be short, ideally 3 chars. Abbreviate if necessary. */
|
||||
sprintf (p, _(" eta %s"), eta_to_human_short (eta));
|
||||
sprintf (p, _(" eta %s"), eta_to_human_short (eta, false));
|
||||
move_to_end (p);
|
||||
}
|
||||
else if (bp->total_length > 0)
|
||||
@ -901,15 +946,9 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
|
||||
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)));
|
||||
strcpy (p, eta_to_human_short ((int) (secs + 0.5), false));
|
||||
else
|
||||
/* For very quick downloads show more exact timing information. */
|
||||
sprintf (p, "%.*fs",
|
||||
secs < 0.001 ? 0 : /* 0s instead of 0.000s */
|
||||
secs < 0.01 ? 3 : /* 0.00x */
|
||||
secs < 0.1 ? 2 : /* 0.0x */
|
||||
1, /* 0.x, 1.x, ..., 9.x */
|
||||
secs);
|
||||
sprintf (p, "%ss", print_decimal (secs));
|
||||
move_to_end (p);
|
||||
}
|
||||
|
||||
@ -984,18 +1023,20 @@ progress_handle_sigwinch (int sig)
|
||||
and hours are shown. This ensures brevity while still displaying
|
||||
as much as possible.
|
||||
|
||||
If SEP is false, the separator between minutes and seconds (and
|
||||
hours and minutes, etc.) is not included, shortening the display by
|
||||
one additional character. This is used for dot progress.
|
||||
If CONDENSED is true, the separator between minutes and seconds
|
||||
(and hours and minutes, etc.) is not included, shortening the
|
||||
display by one additional character. This is used for dot
|
||||
progress.
|
||||
|
||||
The display never occupies more than 7 characters of screen
|
||||
space. */
|
||||
|
||||
static const char *
|
||||
eta_to_human_short (int secs)
|
||||
eta_to_human_short (int secs, bool condensed)
|
||||
{
|
||||
static char buf[10]; /* 8 should be enough, but just in case */
|
||||
static int last = -1;
|
||||
const char *space = condensed ? "" : " ";
|
||||
|
||||
/* Trivial optimization. create_image can call us every 200 msecs
|
||||
(see bar_update) for fast downloads, but ETA will only change
|
||||
@ -1007,11 +1048,11 @@ eta_to_human_short (int secs)
|
||||
if (secs < 100)
|
||||
sprintf (buf, "%ds", secs);
|
||||
else if (secs < 100 * 60)
|
||||
sprintf (buf, "%dm %ds", secs / 60, secs % 60);
|
||||
sprintf (buf, "%dm%s%ds", secs / 60, space, secs % 60);
|
||||
else if (secs < 100 * 3600)
|
||||
sprintf (buf, "%dh %dm", secs / 3600, (secs / 60) % 60);
|
||||
sprintf (buf, "%dh%s%dm", secs / 3600, space, (secs / 60) % 60);
|
||||
else if (secs < 100 * 86400)
|
||||
sprintf (buf, "%dd %dh", secs / 86400, (secs / 3600) % 60);
|
||||
sprintf (buf, "%dd%s%dh", secs / 86400, space, (secs / 3600) % 60);
|
||||
else
|
||||
/* even (2^31-1)/86400 doesn't overflow BUF. */
|
||||
sprintf (buf, "%dd", secs / 86400);
|
||||
|
35
src/utils.c
35
src/utils.c
@ -2039,3 +2039,38 @@ stable_sort (void *base, size_t nmemb, size_t size,
|
||||
mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a decimal number. If it is equal to or larger than ten, the
|
||||
number is rounded. Otherwise it is printed with one significant
|
||||
digit without trailing zeros and with no more than three fractional
|
||||
digits total. For example, 0.1 is printed as "0.1", 0.035 is
|
||||
printed as "0.04", 0.0091 as "0.009", and 0.0003 as simply "0".
|
||||
|
||||
This is useful for displaying durations because it provides
|
||||
order-of-magnitude information without unnecessary clutter --
|
||||
long-running downloads are shown without the fractional part, and
|
||||
short ones still retain one significant digit. */
|
||||
|
||||
const char *
|
||||
print_decimal (double number)
|
||||
{
|
||||
static char buf[32];
|
||||
double n = number >= 0 ? number : -number;
|
||||
|
||||
if (n >= 9.95)
|
||||
/* Cut off at 9.95 because the below %.1f would round 9.96 to
|
||||
"10.0" instead of "10". OTOH 9.94 will print as "9.9". */
|
||||
snprintf (buf, sizeof buf, "%.0f", number);
|
||||
else if (n >= 0.95)
|
||||
snprintf (buf, sizeof buf, "%.1f", number);
|
||||
else if (n >= 0.001)
|
||||
snprintf (buf, sizeof buf, "%.1g", number);
|
||||
else if (n >= 0.0005)
|
||||
/* round [0.0005, 0.001) to 0.001 */
|
||||
snprintf (buf, sizeof buf, "%.3f", number);
|
||||
else
|
||||
/* print numbers close to 0 as 0, not 0.000 */
|
||||
strcpy (buf, "0");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -126,4 +126,6 @@ int base64_decode (const char *, char *);
|
||||
|
||||
void stable_sort (void *, size_t, size_t, int (*) (const void *, const void *));
|
||||
|
||||
const char *print_decimal (double);
|
||||
|
||||
#endif /* UTILS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user