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

Reply via email to