void notify_progress (uint64_t position, uint64_t total) { struct timeval now_t; int64_t last_us, now_us, elapsed_us; gettimeofday (&now_t, NULL); /* Always send a notification at 100%. This simplifies callers by * allowing them to 'finish' the progress bar at 100% without * needing special code. */ if (count_progress > 0 && position == total) { notify_progress_no_ratelimit (position, total, &now_t); return; } /* Calculate time in microseconds since the last progress message * was sent out (or since the start of the call). */ last_us = (int64_t) last_progress_t.tv_sec * 1000000 + last_progress_t.tv_usec; now_us = (int64_t) now_t.tv_sec * 1000000 + now_t.tv_usec; elapsed_us = now_us - last_us; /* Rate limit. */ if ((count_progress == 0 && elapsed_us < NOTIFICATION_INITIAL_DELAY) || (count_progress > 0 && elapsed_us < NOTIFICATION_PERIOD)) return; notify_progress_no_ratelimit (position, total, &now_t); }
/* Generate progress notification messages in order to test progress bars. */ static char * debug_progress (const char *subcmd, size_t argc, char *const *const argv) { uint64_t secs, rate = 0; char *ret; if (argc < 1) { error: reply_with_error ("progress: expecting one or more args: time in seconds [, rate in microseconds]"); return NULL; } if (sscanf (argv[0], "%" SCNu64, &secs) != 1) goto error; if (secs == 0 || secs > 1000000) { /* RHBZ#816839 */ reply_with_error ("progress: argument is 0, less than 0, or too large"); return NULL; } if (argc >= 2) { if (sscanf (argv[1], "%" SCNu64, &rate) != 1) goto error; if (rate == 0 || rate > 1000000) { reply_with_error ("progress: rate is 0 or too large"); return NULL; } } /* Note the inner loops go to '<= limit' because we want to ensure * that the final 100% completed message is set. */ if (rate == 0) { /* Ordinary rate-limited progress messages. */ uint64_t tsecs = secs * 10; /* 1/10ths of seconds */ uint64_t i; for (i = 1; i <= tsecs; ++i) { usleep (100000); notify_progress (i, tsecs); } } else { /* Send messages at a given rate. */ uint64_t usecs = secs * 1000000; /* microseconds */ uint64_t i; struct timeval now; for (i = rate; i <= usecs; i += rate) { usleep (rate); gettimeofday (&now, NULL); notify_progress_no_ratelimit (i, usecs, &now); } } ret = strdup ("ok"); if (ret == NULL) { reply_with_perror ("strdup"); return NULL; } return ret; }