void stop_progress_msg(struct progress **p_progress, const char *msg) { struct progress *progress = *p_progress; if (!progress) return; *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ char buf[128], *bufp; size_t len = strlen(msg) + 5; struct throughput *tp = progress->throughput; bufp = (len < sizeof(buf)) ? buf : xmalloc(len + 1); if (tp) { struct strbuf strbuf = STRBUF_INIT; unsigned int rate = !tp->avg_misecs ? 0 : tp->avg_bytes / tp->avg_misecs; throughput_string(&strbuf, tp->curr_total, rate); strncpy(tp->display, strbuf.buf, sizeof(tp->display)); strbuf_release(&strbuf); } progress_update = 1; sprintf(bufp, ", %s.\n", msg); display(progress, progress->last_value, bufp); if (buf != bufp) free(bufp); } clear_progress_signal(); free(progress->throughput); free(progress); }
void stop_progress_msg(struct progress **p_progress, const char *msg) { struct progress *progress = *p_progress; if (!progress) return; *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ char *buf; struct throughput *tp = progress->throughput; if (tp) { uint64_t now_ns = getnanotime(); unsigned int misecs, rate; misecs = ((now_ns - progress->start_ns) * 4398) >> 32; rate = tp->curr_total / (misecs ? misecs : 1); throughput_string(&tp->display, tp->curr_total, rate); } progress_update = 1; buf = xstrfmt(", %s.\n", msg); display(progress, progress->last_value, buf); free(buf); }
void display_throughput(struct progress *progress, off_t total) { struct throughput *tp; uint64_t now_ns; unsigned int misecs, count, rate; if (!progress) return; tp = progress->throughput; now_ns = getnanotime(); if (!tp) { progress->throughput = tp = calloc(1, sizeof(*tp)); if (tp) { tp->prev_total = tp->curr_total = total; tp->prev_ns = now_ns; strbuf_init(&tp->display, 0); } return; } tp->curr_total = total; /* only update throughput every 0.5 s */ if (now_ns - tp->prev_ns <= 500000000) return; /* * We have x = bytes and y = nanosecs. We want z = KiB/s: * * z = (x / 1024) / (y / 1000000000) * z = x / y * 1000000000 / 1024 * z = x / (y * 1024 / 1000000000) * z = x / y' * * To simplify things we'll keep track of misecs, or 1024th of a sec * obtained with: * * y' = y * 1024 / 1000000000 * y' = y * (2^10 / 2^42) * (2^42 / 1000000000) * y' = y / 2^32 * 4398 * y' = (y * 4398) >> 32 */ misecs = ((now_ns - tp->prev_ns) * 4398) >> 32; count = total - tp->prev_total; tp->prev_total = total; tp->prev_ns = now_ns; tp->avg_bytes += count; tp->avg_misecs += misecs; rate = tp->avg_bytes / tp->avg_misecs; tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; tp->last_bytes[tp->idx] = count; tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; throughput_string(&tp->display, total, rate); if (progress->last_value != -1 && progress_update) display(progress, progress->last_value, NULL); }
void display_throughput(struct progress *progress, off_t total) { struct throughput *tp; struct timeval tv; unsigned int misecs; if (!progress) return; tp = progress->throughput; gettimeofday(&tv, NULL); if (!tp) { progress->throughput = tp = calloc(1, sizeof(*tp)); if (tp) { tp->prev_total = tp->curr_total = total; tp->prev_tv = tv; } return; } tp->curr_total = total; /* * We have x = bytes and y = microsecs. We want z = KiB/s: * * z = (x / 1024) / (y / 1000000) * z = x / y * 1000000 / 1024 * z = x / (y * 1024 / 1000000) * z = x / y' * * To simplify things we'll keep track of misecs, or 1024th of a sec * obtained with: * * y' = y * 1024 / 1000000 * y' = y / (1000000 / 1024) * y' = y / 977 */ misecs = (tv.tv_sec - tp->prev_tv.tv_sec) * 1024; misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; if (misecs > 512) { struct strbuf buf = STRBUF_INIT; unsigned int count, rate; count = total - tp->prev_total; tp->prev_total = total; tp->prev_tv = tv; tp->avg_bytes += count; tp->avg_misecs += misecs; rate = tp->avg_bytes / tp->avg_misecs; tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; tp->last_bytes[tp->idx] = count; tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; throughput_string(&buf, total, rate); strncpy(tp->display, buf.buf, sizeof(tp->display)); strbuf_release(&buf); if (progress->last_value != -1 && progress_update) display(progress, progress->last_value, NULL); } }