From: MORITA Kazutaka <[email protected]> These operations take a long time to complete. Showing a prograss bar helps users.
Signed-off-by: MORITA Kazutaka <[email protected]> --- collie/vdi.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/collie/vdi.c b/collie/vdi.c index 660f792..91ed671 100644 --- a/collie/vdi.c +++ b/collie/vdi.c @@ -14,6 +14,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/ioctl.h> #include <fcntl.h> #include "collie.h" @@ -82,6 +83,68 @@ static int parse_option_size(const char *value, uint64_t *ret) return 0; } +#define DEFAULT_SCREEN_WIDTH 80 + +static int get_screen_width(void) +{ + struct winsize wsz; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) < 0) + return DEFAULT_SCREEN_WIDTH; + + return wsz.ws_col; +} + +/* + * Show prograss bar as follows. + * + * 45.0 % [===============> ] 180 MB / 400 MB + */ +static void show_progress(uint64_t done, uint64_t total) +{ + char done_str[256], total_str[256]; + int screen_width = get_screen_width(); + int bar_length = screen_width - 30; + char *buf; + + if (!is_stdout_console()) + return; + if (screen_width <= 0) + return; + + printf("\r"); /* move to the beginning of the line */ + + size_to_str(done, done_str, sizeof(done_str)); + size_to_str(total, total_str, sizeof(total_str)); + + buf = xmalloc(screen_width); + snprintf(buf, screen_width, "%5.1lf %% [", (double)done / total * 100); + + for (int i = 0; i < bar_length; i++) { + if (total * (i + 1) / bar_length <= done) + strcat(buf, "="); + else if (total * i / bar_length <= done && + done < total * (i + 1) / bar_length) + strcat(buf, ">"); + else + strcat(buf, " "); + } + snprintf(buf + strlen(buf), screen_width - strlen(buf), + "] %s / %s", done_str, total_str); + + /* fill the rest of buffer with blank characters */ + memset(buf + strlen(buf), ' ', screen_width - strlen(buf) - 1); + buf[screen_width - 1] = '\0'; + printf("%s", buf); + + if (done == total) + printf("\n"); + + fflush(stdout); + + free(buf); +} + static void print_vdi_list(uint32_t vid, const char *name, const char *tag, uint32_t snapid, uint32_t flags, const struct sd_inode *i, void *data) @@ -522,6 +585,7 @@ static int vdi_create(int argc, char **argv) max_idx = DIV_ROUND_UP(size, SD_DATA_OBJ_SIZE); for (idx = 0; idx < max_idx; idx++) { + show_progress(idx * SD_DATA_OBJ_SIZE, inode->vdi_size); oid = vid_to_data_oid(vid, idx); ret = sd_write_object(oid, 0, NULL, 0, 0, 0, inode->nr_copies, @@ -540,6 +604,7 @@ static int vdi_create(int argc, char **argv) goto out; } } + show_progress(idx * SD_DATA_OBJ_SIZE, inode->vdi_size); ret = EXIT_SUCCESS; out: free(inode); @@ -615,6 +680,7 @@ static int vdi_clone(int argc, char **argv) max_idx = DIV_ROUND_UP(inode->vdi_size, SD_DATA_OBJ_SIZE); for (idx = 0; idx < max_idx; idx++) { + show_progress(idx * SD_DATA_OBJ_SIZE, inode->vdi_size); if (inode->data_vdi_id[idx]) { oid = vid_to_data_oid(inode->data_vdi_id[idx], idx); ret = sd_read_object(oid, buf, SD_DATA_OBJ_SIZE, 0, true); @@ -641,6 +707,7 @@ static int vdi_clone(int argc, char **argv) goto out; } } + show_progress(idx * SD_DATA_OBJ_SIZE, inode->vdi_size); ret = EXIT_SUCCESS; out: free(inode); @@ -1433,6 +1500,7 @@ static int vdi_check(int argc, char **argv) do_check_repair(vid_to_vdi_oid(vid), inode->nr_copies); total = inode->vdi_size; while (done < total) { + show_progress(done, total); vid = inode->data_vdi_id[idx]; if (vid) { oid = vid_to_data_oid(vid, idx); @@ -1441,6 +1509,7 @@ static int vdi_check(int argc, char **argv) done += SD_DATA_OBJ_SIZE; idx++; } + show_progress(done, total); fprintf(stdout, "finish check&repair %s\n", vdiname); return EXIT_SUCCESS; -- 1.7.9.5 -- sheepdog mailing list [email protected] http://lists.wpkg.org/mailman/listinfo/sheepdog
