diff options
author | Ryo Nakamura <upa@haeena.net> | 2022-10-20 18:58:06 +0900 |
---|---|---|
committer | Ryo Nakamura <upa@haeena.net> | 2022-10-20 18:58:06 +0900 |
commit | 808069ab9dc57dbebcf46d0ff95114581cb5315c (patch) | |
tree | 1c719853f59f9b43a1b0b0f2466ce4daba54e6c2 /src | |
parent | def9cfeba74357ca98fc25469d4285139ecd42ce (diff) |
implement chunk fill
Diffstat (limited to 'src')
-rw-r--r-- | src/file.c | 96 | ||||
-rw-r--r-- | src/file.h | 8 | ||||
-rw-r--r-- | src/main.c | 17 |
3 files changed, 113 insertions, 8 deletions
@@ -97,7 +97,7 @@ int file_is_directory(char *path, sftp_session sftp) return ret; } -static struct file *file_allocate(char *path, size_t size, bool remote) +static struct file *file_alloc(char *path, size_t size, bool remote) { struct file *f; @@ -167,12 +167,12 @@ static int file_fill_local_recursive(char *path, struct list_head *head) if ((statbuf.st_mode & S_IFMT) == S_IFREG || (statbuf.st_mode & S_IFMT) == S_IFLNK) { - struct file *f = file_allocate(path, statbuf.st_size, false); + struct file *f = file_alloc(path, statbuf.st_size, false); if (!f) { pr_err("%s\n", strerrno()); return -1; } - list_add(&f->list, head); + list_add_tail(&f->list, head); } } @@ -234,7 +234,7 @@ static int file_fill_remote_recursive(char *path, sftp_session sftp, /* skip special and unknown files */ if (attr->type == SSH_FILEXFER_TYPE_REGULAR || attr->type == SSH_FILEXFER_TYPE_SYMLINK) { - struct file *f = file_allocate(path, attr->size, true); + struct file *f = file_alloc(path, attr->size, true); if (!f) { pr_err("%s\n", strerrno()); return -1; @@ -269,13 +269,97 @@ int file_fill(sftp_session sftp, struct list_head *head, char **src_array, int c #ifdef DEBUG -void file_dump(struct list_head *head) +void file_dump(struct list_head *file_head) { struct file *f; - list_for_each_entry(f, head, list) { + list_for_each_entry(f, file_head, list) { pr_debug("%s %s %lu-byte\n", f->path, f->remote ? "(remote)" : "(local)", f->size); } } #endif + + +static void *chunk_alloc(struct file *f) +{ + struct chunk *c; + + c = malloc(sizeof(*c)); + if (!c) { + pr_err("%s\n", strerrno()); + return NULL; + } + memset(c, 0, sizeof(*c)); + + c->f = f; + c->off = 0; + c->len = 0; + return c; +} + +static int get_page_mask(void) +{ + int n; + long page_sz = sysconf(_SC_PAGESIZE); + size_t page_mask = 0; + + for (n = 0; page_sz > 0; page_sz >>= 1, n++) { + page_mask <<= 1; + page_mask |= 1; + } + + return page_mask >> 1; +} + +int chunk_fill(struct list_head *file_head, struct list_head *chunk_head, + int nr_conn, int min_chunk_sz, int max_chunk_sz) +{ + struct chunk *c; + struct file *f; + size_t page_mask; + size_t chunk_sz; + size_t size; + + page_mask = get_page_mask(); + + list_for_each_entry(f, file_head, list) { + if (f->size <= min_chunk_sz) + chunk_sz = f->size; + else if (max_chunk_sz) + chunk_sz = max_chunk_sz; + else { + chunk_sz = (f->size - (f->size % nr_conn)) / nr_conn; + chunk_sz &= ~page_mask; /* align in page_sz */ + if (chunk_sz <= min_chunk_sz) + chunk_sz = min_chunk_sz; + } + + pr_debug("%s chunk_sz %lu-byte\n", f->path, chunk_sz); + + for (size = f->size; size > 0;) { + c = chunk_alloc(f); + if (!c) + return -1; + c->off = f->size - size; + c->len = size < chunk_sz ? size : chunk_sz; + size -= c->len; + list_add_tail(&c->list, chunk_head); + } + } + + return 0; +} + +#ifdef DEBUG +void chunk_dump(struct list_head *chunk_head) +{ + struct chunk *c; + + list_for_each_entry(c, chunk_head, list) { + pr_debug("%s %s 0x%010lx-0x%010lx %lu-byte\n", + c->f->path, c->f->remote ? "(remote)" : "(local)", + c->off, c->off + c->len, c->len); + } +} +#endif @@ -14,6 +14,7 @@ struct file { }; struct chunk { + struct list_head list; /* sscp->chunk_list */ struct file *f; size_t off; /* offset of this chunk on the file f */ size_t len; /* length of this chunk */ @@ -25,8 +26,13 @@ int file_is_directory(char *path, sftp_session sftp); int file_fill(sftp_session sftp, struct list_head *head, char **src_array, int count); +int chunk_fill(struct list_head *file_head, struct list_head *chunk_head, + int nr_conn, int min_chunk_sz, int max_chunk_sz); + #ifdef DEBUG -void file_dump(struct list_head *head); +void file_dump(struct list_head *file_head); +void chunk_dump(struct list_head *chunk_head); #endif + #endif /* _FILE_H_ */ @@ -18,6 +18,7 @@ struct sscp { sftp_session ctrl; /* control sftp session */ struct list_head file_list; + struct list_head chunk_list; char *target; bool target_is_remote; }; @@ -109,6 +110,7 @@ int main(int argc, char **argv) memset(&opts, 0, sizeof(opts)); memset(&sscp, 0, sizeof(sscp)); INIT_LIST_HEAD(&sscp.file_list); + INIT_LIST_HEAD(&sscp.chunk_list); while ((ch = getopt(argc, argv, "n:s:S:l:p:i:c:Cvh")) != -1) { switch (ch) { @@ -211,16 +213,29 @@ int main(int argc, char **argv) return 1; } + /* fill file list */ ret = file_fill(sscp.ctrl, &sscp.file_list, &argv[optind], argc - optind - 1); if (ret < 0) { ssh_sftp_close(sscp.ctrl); return 1; } - #ifdef DEBUG file_dump(&sscp.file_list); #endif + /* fill chunk list */ + ret = chunk_fill(&sscp.file_list, &sscp.chunk_list, + nr_conn, min_chunk_sz, max_chunk_sz); + if (ret < 0) { + ssh_sftp_close(sscp.ctrl); + return 1; + } +#ifdef DEBUG + chunk_dump(&sscp.chunk_list); +#endif + + + ssh_sftp_close(sscp.ctrl); return 0; } |