[pacman-dev] [PATCH] handle time changes during progress display

Martin Panter vadmium+patch at gmail.com
Fri Dec 6 18:13:41 EST 2013


On 7 December 2013 05:32, Andrew Gregory <andrew.gregory.8 at gmail.com> wrote:
> Previously, if the system time was adjusted backwards during a progress
> display, get_update_timediff return negative values prevent the progress
> bar from updating.  Instead, on negative values, the saved time is
> reset.  Additionally, the download callback ignores the amount
> downloaded to avoid skewing the rate.

Have you considered using clock_gettime(CLOCK_MONOTONIC) rather than
gettimeofday()? Or is it not available on some platforms? Even if you
have to use a different function for OS X or something it mightn’t be
much worse than these backwards time hacks.

> Fixes FS#36983
>
> Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
> ---
>  src/pacman/callback.c | 33 +++++++++++++++++++--------------
>  1 file changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/src/pacman/callback.c b/src/pacman/callback.c
> index a181fa5..0ffb2ef 100644
> --- a/src/pacman/callback.c
> +++ b/src/pacman/callback.c
> @@ -73,8 +73,8 @@ static long get_update_timediff(int first_call)
>
>                 retval = (diff_sec * 1000) + (diff_usec / 1000);
>
> -               /* do not update last_time if interval was too short */
> -               if(retval >= UPDATE_SPEED_MS) {
> +               /* update last_time if it is in the future or interval was long enough */
> +               if(retval < 0 || retval >= UPDATE_SPEED_MS) {
>                         last_time = this_time;
>                 }
>         }
> @@ -554,7 +554,7 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
>  {
>         static double rate_last;
>         static off_t xfered_last;
> -       static struct timeval initial_time;
> +       static long elapsed_time = 0;
>         int infolen;
>         int filenamelen;
>         char *fname, *p;
> @@ -616,25 +616,23 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
>                 /* set default starting values, ensure we only call this once
>                  * if TotalDownload is enabled */
>                 if(!totaldownload || (totaldownload && list_xfered == 0)) {
> -                       gettimeofday(&initial_time, NULL);
> +                       elapsed_time = 0;
>                         xfered_last = (off_t)0;
>                         rate_last = 0.0;
>                         get_update_timediff(1);
>                 }
>         } else if(file_xfered == file_total) {
>                 /* compute final values */
> -               struct timeval current_time;
> -               time_t diff_sec;
> -               suseconds_t diff_usec;
> +               timediff = get_update_timediff(0);
>
> -               gettimeofday(&current_time, NULL);
> -               diff_sec = current_time.tv_sec - initial_time.tv_sec;
> -               diff_usec = current_time.tv_usec - initial_time.tv_usec;
> -               timediff = (diff_sec * 1000) + (diff_usec / 1000);
>                 if(timediff > 0) {
> -                       rate = (double)xfered / (timediff / 1000.0);
> +                       elapsed_time += timediff;
> +               }
> +
> +               if(elapsed_time > 0) {
> +                       rate = (double)xfered / (elapsed_time / 1000.0);
>                         /* round elapsed time (in ms) to the nearest second */
> -                       eta_s = (unsigned int)(timediff + 500) / 1000;
> +                       eta_s = (unsigned int)(elapsed_time + 500) / 1000;
>                 } else {
>                         eta_s = 0;
>                 }
> @@ -642,10 +640,17 @@ void cb_dl_progress(const char *filename, off_t file_xfered, off_t file_total)
>                 /* compute current average values */
>                 timediff = get_update_timediff(0);
>
> -               if(timediff < UPDATE_SPEED_MS) {
> +               if(timediff < 0) {
> +                       /* we lost a chunk of time due to a clock change, including the amount
> +                        * xfered during that period in the next update would skew the rate */
> +                       xfered_last = xfered;
> +                       return;
> +               } else if(timediff < UPDATE_SPEED_MS) {
>                         /* return if the calling interval was too short */
>                         return;
>                 }
> +
> +               elapsed_time += timediff;
>                 rate = (double)(xfered - xfered_last) / (timediff / 1000.0);
>                 /* average rate to reduce jumpiness */
>                 rate = (rate + 2 * rate_last) / 3;
> --
> 1.8.4.2


More information about the pacman-dev mailing list