summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRyo Nakamura <upa@haeena.net>2022-10-20 18:58:06 +0900
committerRyo Nakamura <upa@haeena.net>2022-10-20 18:58:06 +0900
commit808069ab9dc57dbebcf46d0ff95114581cb5315c (patch)
tree1c719853f59f9b43a1b0b0f2466ce4daba54e6c2 /src
parentdef9cfeba74357ca98fc25469d4285139ecd42ce (diff)
implement chunk fill
Diffstat (limited to 'src')
-rw-r--r--src/file.c96
-rw-r--r--src/file.h8
-rw-r--r--src/main.c17
3 files changed, 113 insertions, 8 deletions
diff --git a/src/file.c b/src/file.c
index 88614ec..7f1c1d0 100644
--- a/src/file.c
+++ b/src/file.c
@@ -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
diff --git a/src/file.h b/src/file.h
index d6a8681..0c22944 100644
--- a/src/file.h
+++ b/src/file.h
@@ -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_ */
diff --git a/src/main.c b/src/main.c
index 0771bbd..8f7f0fb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}