From 33bc3aae517e4884f08928be9d6e4c941ec3f489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D1=8F=D1=87=D0=B5=D1=81=D0=BB=D0=B0=D0=B2=20=D0=9F?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D0=B8=D1=89=D0=B5=D0=B2?= Date: Sat, 25 Jan 2020 00:30:09 +0600 Subject: [PATCH] Fix and cleanup progress bar code *src/progress.c (struct dot_progress) accumulated, rows: Type changed to wgint (print_row_stats): Fix missing unit name 'T' (dot_update): Add ability to reduce dot_draw runtime (bar_update): Avoid integer overflow --- src/progress.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/progress.c b/src/progress.c index 2fed72c0..296d8f30 100644 --- a/src/progress.c +++ b/src/progress.c @@ -220,11 +220,11 @@ struct dot_progress { wgint total_length; /* expected total byte count when the download finishes */ - int accumulated; /* number of bytes accumulated after + wgint accumulated; /* number of bytes accumulated after the last printed dot */ double dltime; /* download time so far */ - int rows; /* number of rows printed so far */ + wgint rows; /* number of rows printed so far */ int dots; /* number of dots printed in this row */ double last_timer_value; @@ -282,6 +282,21 @@ dot_create (const char *f_download _GL_UNUSED, wgint initial, wgint total) static const char *eta_to_human_short (int, bool); +/* ADD_DOT_ROWS_THRS - minimal (1 << ADD_DOT_ROWS_THRS) ROWS to be added + to the current row if dp->accumulated too much. + Allows to reduce dot_draw io, times. + According to the way progress_update is currently has being called, this + should happens only when fuzzing, or (paranoia) if somehow buffer will + be too large. + Can be disabled by default if this is not fuzzing build. */ +#ifndef ADD_DOT_ROWS_THRS +#if FUZZING +#define ADD_DOT_ROWS_THRS 2 +#else +#define ADD_DOT_ROWS_THRS 2 +#endif +#endif /* ADD_DOT_ROWS_THRS */ + /* Prints the stats (percentage of completion, speed, ETA) for current row. DLTIME is the time spent downloading the data in current row. @@ -291,7 +306,11 @@ static const char *eta_to_human_short (int, bool); might be worthwhile to split it to two different functions. */ static void +#if ADD_DOT_ROWS_THRS +print_row_stats (struct dot_progress *dp, double dltime, bool last, wgint added_rows) +#else print_row_stats (struct dot_progress *dp, double dltime, bool last) +#endif { const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line; @@ -316,12 +335,16 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) } { - static char names[] = {' ', 'K', 'M', 'G'}; + static char names[] = {' ', 'K', 'M', 'G', 'T'}; int units; double rate; wgint bytes_this_row; if (!last) +#if ADD_DOT_ROWS_THRS + bytes_this_row = ROW_BYTES * added_rows; +#else bytes_this_row = ROW_BYTES; +#endif else /* For last row also include bytes accumulated after last dot. */ bytes_this_row = dp->dots * opt.dot_bytes + dp->accumulated; @@ -391,8 +414,9 @@ dot_draw (void *progress) log_set_flush (false); - for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes) + while (dp->accumulated >= dot_bytes) { + dp->accumulated -= dot_bytes; if (dp->dots == 0) logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (dp->rows * ROW_BYTES / 1024)); @@ -404,11 +428,26 @@ dot_draw (void *progress) ++dp->dots; if (dp->dots >= opt.dots_in_line) { - if (dp->rows < INT_MAX) - ++dp->rows; dp->dots = 0; - +#if ADD_DOT_ROWS_THRS + { + wgint added_rows = 1; + if (dp->accumulated >= (ROW_BYTES << ADD_DOT_ROWS_THRS)) + { + added_rows += dp->accumulated / ROW_BYTES; + dp->accumulated %= ROW_BYTES; + } + if (WGINT_MAX - dp->rows >= added_rows) + dp->rows += added_rows; + else + dp->rows = WGINT_MAX; + print_row_stats (dp, dp->dltime, false, added_rows); + } +#else + if (dp->rows < WGINT_MAX) + ++dp->rows; print_row_stats (dp, dp->dltime, false); +#endif /* ADD_DOT_ROWS_THRS */ } } @@ -441,8 +480,11 @@ dot_finish (void *progress, double dltime) dltime = INT_MAX - 1; else if (dltime < 0) dltime = 0; - +#if ADD_DOT_ROWS_THRS + print_row_stats (dp, dltime, true, 1); +#else print_row_stats (dp, dltime, true); +#endif logputs (LOG_VERBOSE, "\n\n"); log_set_flush (false); @@ -721,7 +763,10 @@ bar_update (void *progress, wgint howmuch, double dltime) struct bar_progress *bp = progress; bp->dltime = dltime; - bp->count += howmuch; + if (WGINT_MAX - (bp->count + bp->initial_length) >= howmuch) + bp->count += howmuch; + else + bp->count = WGINT_MAX - bp->initial_length; if (bp->total_length > 0 && bp->count + bp->initial_length > bp->total_length) /* We could be downloading more than total_length, e.g. when the