diff options
author | Ryo Nakamura <upa@haeena.net> | 2022-10-25 01:47:39 +0900 |
---|---|---|
committer | Ryo Nakamura <upa@haeena.net> | 2022-10-25 01:47:39 +0900 |
commit | 47f6983148047975e00f48b1ef77f8c4c7f2fd73 (patch) | |
tree | 5ce9ac01f3b8b9c2bd66c7ffad0ffca35ff89e72 | |
parent | c83927cd5a56111a11c2f7879c6e444b31eddb27 (diff) |
wrap print progress in pprint
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/file.c | 21 | ||||
-rw-r--r-- | src/main.c | 41 | ||||
-rw-r--r-- | src/pprint.c | 32 | ||||
-rw-r--r-- | src/pprint.h | 14 | ||||
-rw-r--r-- | src/util.h | 14 |
6 files changed, 84 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a05f854..688df62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_C_FLAGS "-Wall -g") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") -add_executable(sscp src/main.c src/platform.c src/ssh.c src/file.c) +add_executable(sscp src/main.c src/platform.c src/ssh.c src/file.c src/pprint.c) target_include_directories(sscp PUBLIC ./src /usr/local/include) target_link_directories(sscp PUBLIC /usr/local/lib) target_link_libraries(sscp ssh pthread m) @@ -7,6 +7,7 @@ #include <ssh.h> #include <util.h> #include <file.h> +#include <pprint.h> #include <platform.h> bool file_has_hostname(char *path) @@ -450,6 +451,8 @@ int chunk_fill(struct list_head *file_list, struct list_head *chunk_list, c->len = size < chunk_sz ? size : chunk_sz; size -= c->len; list_add_tail(&c->list, chunk_list); + pprint4("chunk %s 0x%010lx-0x%010lx %luB\n", + c->f->path, c->off, c->off + c->len, c->len); } } @@ -487,7 +490,6 @@ struct chunk *chunk_acquire(struct list_head *chunk_list) int chunk_prepare(struct chunk *c, sftp_session sftp) { - char output[PATH_MAX + 32]; struct file *f = c->f; int ret = 0; @@ -497,10 +499,8 @@ int chunk_prepare(struct chunk *c, sftp_session sftp) ret = -1; goto out; } - snprintf(output, sizeof(output), "\r\033[Kcopy start: %s\n", f->path); - fputs(output, stderr); - fflush(stderr); f->state = FILE_STATE_OPENED; + pprint2("copy start: %s\n", f->path); } out: @@ -731,12 +731,15 @@ int chunk_copy(struct chunk *c, sftp_session sftp, size_t sftp_buf_sz, size_t io { struct file *f = c->f; int ret = 0; - char output[PATH_MAX + 16]; pr_debug("copy %s %s -> %s %s off=0x%010lx\n", f->path, f->remote ? "(remote)" : "(local)", f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off); + pprint4("copy start: chunk %s 0x%010lx-0x%010lx %luB\n", + c->f->path, c->off, c->off + c->len, c->len); + + if (f->dst_remote) ret = chunk_copy_local_to_remote(c, sftp, sftp_buf_sz, io_buf_sz, counter); @@ -751,12 +754,14 @@ int chunk_copy(struct chunk *c, sftp_session sftp, size_t sftp_buf_sz, size_t io f->path, f->remote ? "(remote)" : "(local)", f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off); + pprint4("copy done: chunk %s 0x%010lx-0x%010lx %luB\n", + c->f->path, c->off, c->off + c->len, c->len); + if (refcnt_dec(&f->refcnt) == 0) { - snprintf(output, sizeof(output), "\r\033[Kcopy done: %s\n", f->path); - fputs(output, stderr); - fflush(stderr); f->state = FILE_STATE_DONE; + pprint2("copy done: %s\n", f->path); } + return ret; } @@ -12,12 +12,10 @@ #include <util.h> #include <ssh.h> #include <file.h> +#include <pprint.h> #include <atomic.h> #include <platform.h> -int verbose = 0; /* util.h */ - - #define DEFAULT_MIN_CHUNK_SZ (64 << 20) /* 64MB */ #define DEFAULT_SFTP_BUF_SZ 131072 /* derived from qemu/block/ssh.c */ #define DEFAULT_IO_BUF_SZ DEFAULT_SFTP_BUF_SZ @@ -69,29 +67,31 @@ void stop_copy_threads(int sig) void usage(bool print_help) { printf("sscp: super scp, copy files over multiple ssh connections\n" "\n" - "Usage: sscp [Cvh] [-n max_conns] [-s min_chunk_sz] [-S max_chunk_sz]\n" + "Usage: sscp [Cvqdh] [-n nr_conns] [-s min_chunk_sz] [-S max_chunk_sz]\n" " [-b sftp_buf_sz] [-B io_buf_sz]\n" " [-l login_name] [-p port] [-i identity_file]\n" - " [-c cipher_spec] source ... target_directory\n" + " [-c cipher_spec] []source ... target_directory\n" "\n"); if (!print_help) return; - printf(" -n NR_CONNECTIONS max number of connections (default: # of cpu cores)\n" + printf(" -n NR_CONNECTIONS number of connections (default: half of # of cpu cores)\n" " -s MIN_CHUNK_SIZE min chunk size (default: 64MB)\n" " -S MAX_CHUNK_SIZE max chunk size (default: filesize / nr_conn)\n" " -b SFTP_BUF_SIZE buf size for sftp_read/write (default 131072B)\n" " -B IO_BUF_SIZE buf size for read/write (default 131072B)\n" " Note that this value is derived from\n" " qemu/block/ssh.c. need investigation...\n" + " -v increment verbose output level\n" + " -q disable output\n" "\n" " -l LOGIN_NAME login name\n" " -p PORT port number\n" " -i IDENTITY identity file for publickey authentication\n" " -c CIPHER cipher spec, see `ssh -Q cipher`\n" " -C enable compression on libssh\n" - " -v increment output level\n" + " -d increment ssh debug output level\n" " -h print this help\n" "\n"); @@ -151,6 +151,7 @@ int main(int argc, char **argv) struct ssh_opts opts; int min_chunk_sz = DEFAULT_MIN_CHUNK_SZ; int max_chunk_sz = 0; + int verbose = 1; int ret = 0, n; char ch; @@ -162,9 +163,10 @@ int main(int argc, char **argv) sscp.sftp_buf_sz = DEFAULT_SFTP_BUF_SZ; sscp.io_buf_sz = DEFAULT_IO_BUF_SZ; - nr_threads = nr_cpus(); + nr_threads = (int)(nr_cpus() / 2); + nr_threads = nr_threads == 0 ? 1 : nr_threads; - while ((ch = getopt(argc, argv, "n:s:S:b:B:l:p:i:c:Cvh")) != -1) { + while ((ch = getopt(argc, argv, "n:s:S:b:B:vql:p:i:c:Cdh")) != -1) { switch (ch) { case 'n': nr_threads = atoi(optarg); @@ -217,6 +219,12 @@ int main(int argc, char **argv) return -1; } break; + case 'v': + verbose++; + break; + case 'q': + verbose = -1; + break; case 'l': opts.login_name = optarg; break; @@ -232,9 +240,8 @@ int main(int argc, char **argv) case 'C': opts.compress++; break; - case 'v': + case 'd': opts.debuglevel++; - verbose++; break; case 'h': usage(true); @@ -245,6 +252,8 @@ int main(int argc, char **argv) } } + pprint_set_level(verbose); + if (max_chunk_sz > 0 && min_chunk_sz > max_chunk_sz) { pr_err("smaller max chunk size than min chunk size: %d < %d\n", max_chunk_sz, min_chunk_sz); @@ -265,6 +274,7 @@ int main(int argc, char **argv) pr_err("no remote host given\n"); return 1; } + pprint3("connecting to %s for checking destinations...\n", sscp.host); sscp.ctrl = ssh_make_sftp_session(sscp.host, &opts); if (!sscp.ctrl) return 1; @@ -317,6 +327,7 @@ int main(int argc, char **argv) struct sscp_thread *t = &threads[n]; t->sscp = &sscp; t->finished = false; + pprint3("connecting to %s for a copy thread...\n", sscp.host); t->sftp = ssh_make_sftp_session(sscp.host, sscp.opts); if (!t->sftp) goto join_out; @@ -451,10 +462,7 @@ static void print_progress_bar(double percent, char *suffix) " %3d%% ", (int)floor(percent)); } - fputs("\r\033[K", stderr); - fputs(buf, stderr); - fputs(suffix, stderr); - fflush(stderr); + pprint1("%s%s", buf, suffix); } static void print_progress(struct timeval *start, struct timeval *end, @@ -513,6 +521,7 @@ void sscp_monitor_thread_cleanup(void *arg) } print_progress(&sscp->start, &end, total, 0, done); + fputs("\n", stdout); /* the final ouput. we need \n */ } void *sscp_monitor_thread(void *arg) @@ -560,7 +569,5 @@ void *sscp_monitor_thread(void *arg) pthread_cleanup_pop(1); - fputs("\n", stderr); - return NULL; } diff --git a/src/pprint.c b/src/pprint.c new file mode 100644 index 0000000..51eb4ad --- /dev/null +++ b/src/pprint.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <stdarg.h> +#include <pthread.h> + +static int pprint_level = 1; +/* level 1: print progress bar only. + * level 2: print copy start/done messages. + * level 3: print ssh connection establishment/disconnection. + * level 4: print chunk information. + */ + +static pthread_mutex_t pprint_lock = PTHREAD_MUTEX_INITIALIZER; + +void pprint_set_level(int level) +{ + pprint_level = level; +} + +void pprint(int level, const char *fmt, ...) +{ + va_list va; + + if (level <= pprint_level) { + pthread_mutex_lock(&pprint_lock); + va_start(va, fmt); + vfprintf(stdout, fmt, va); + fflush(stdout); + va_end(va); + pthread_mutex_unlock(&pprint_lock); + } +} + diff --git a/src/pprint.h b/src/pprint.h new file mode 100644 index 0000000..7fa303e --- /dev/null +++ b/src/pprint.h @@ -0,0 +1,14 @@ +#ifndef _PPRINT_H_ +#define _PPRINT_H_ + +/* progress print functions */ + +void pprint_set_level(int level); +void pprint(int level, const char *fmt, ...); + +#define pprint1(fmt, ...) pprint(1, "\r\033[K" fmt, ##__VA_ARGS__) +#define pprint2(fmt, ...) pprint(2, "\r\033[K" fmt, ##__VA_ARGS__) +#define pprint3(fmt, ...) pprint(3, "\r\033[K" fmt, ##__VA_ARGS__) +#define pprint4(fmt, ...) pprint(4, "\r\033[K" fmt, ##__VA_ARGS__) + +#endif /* _PPRRINT_H_ */ @@ -8,20 +8,6 @@ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) -extern int verbose; - -#define pr_v(level, fmt, ...) do { \ - if (verbose >= level) { \ - fprintf(stdout, "\x1b[1m\x1b[34m" \ - "%s(): \x1b[0m" fmt, \ - __func__, ##__VA_ARGS__); \ - } \ - } while (0) - -#define pr_v1(fmt, ...) pr_v(1, fmt, ##__VA_ARGS__) -#define pr_v2(fmt, ...) pr_v(2, fmt, ##__VA_ARGS__) -#define pr_v3(fmt, ...) pr_v(3, fmt, ##__VA_ARGS__) - #define pr(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) |