--- a/application/davcontroller.c Tue Feb 06 14:17:22 2024 +0100 +++ b/application/davcontroller.c Tue Feb 06 19:01:52 2024 +0100 @@ -246,6 +246,14 @@ DavSession *sn; UiFileList files; char *base_path; + UiThreadpool *queue; + + size_t total_bytes; + size_t total_files; + size_t total_directories; + size_t uploaded_bytes; + size_t uploaded_files; + size_t uploaded_directories; UiObject *dialog; UiDouble *progress; @@ -256,30 +264,119 @@ typedef struct DUFile { char *path; char *upload_path; + size_t bytes; + DavBool isdirectory; + DavFileUpload *upload; + DavError error; } DUFile; -static int jobthr_file_upload(void *data) { +static double upload_progress(DavFileUpload *upload) { + return ((double)upload->uploaded_bytes / (double)upload->total_bytes) * 100; +} + +static int qthr_file_upload(void *data) { + DUFile *f = data; + DavFileUpload *upload = f->upload; + DavSession *sn = upload->sn; + + FILE *in = sys_fopen(f->path, "rb"); + if (!in) { + // TODO: error msg + return 0; + } + + DavResource *res = dav_resource_new(sn, f->upload_path); + dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); + if (dav_store(res)) { + f->error = sn->error; + } + dav_resource_free(res); + + fclose(in); + + return 0; +} + +static void uithr_file_uploaded(UiEvent *event, void *data) { + DUFile *file = data; + DavFileUpload *upload = file->upload; + + upload->uploaded_files++; + upload->uploaded_bytes += file->bytes; + + double progress = upload_progress(upload); + ui_set(upload->progress, upload_progress(upload)); + + free(file->path); + free(file->upload_path); +} + +static int qthr_dir_upload(void *data) { + DUFile *f = data; + DavFileUpload *upload = f->upload; + DavSession *sn = upload->sn; + + DavResource *res = dav_resource_new(sn, f->upload_path); + res->iscollection = TRUE; + + if (dav_create(res)) { + f->error = sn->error; + } + + dav_resource_free(res); + + return 0; +} + +static void uithr_dir_uploaded(UiEvent *event, void *data) { + DUFile *file = data; + DavFileUpload *upload = file->upload; + + upload->uploaded_directories++; + + free(file->path); + free(file->upload_path); +} + +static int qthr_upload_finished(void *data) { + return 0; +} + +static void uithr_upload_finished(UiEvent *event, void *data) { + DavFileUpload *upload = data; + ui_threadpool_destroy(upload->queue); + + free(upload->base_path); + dav_session_destroy(upload->sn); +} + +static int jobthr_upload_scan(void *data) { DavFileUpload *upload = data; - CxList *stack = cxLinkedListCreateSimple(sizeof(DUFile)); + CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); for (int i = 0; i < upload->files.nfiles; i++) { - DUFile f; - f.path = upload->files.files[i]; - f.upload_path = util_path_file_name(f.path); - cxListInsert(stack, 0, &f); + DUFile *f = malloc(sizeof(DUFile)); + f->path = strdup(upload->files.files[i]); + f->upload_path = util_concat_path(upload->base_path, util_path_file_name(f->path)); + f->isdirectory = FALSE; + f->bytes = 0; + f->upload = upload; + f->error = 0; + cxListInsert(stack, 0, f); } while (stack->size > 0) { DUFile *f = cxListAt(stack, 0); char *path = util_concat_path(upload->base_path, f->upload_path); - DavResource *res = dav_resource_new(upload->sn, path); + cxListRemove(stack, 0); SYS_STAT s; if (!stat(f->path, &s)) { if (S_ISDIR(s.st_mode)) { - res->iscollection = 1; - dav_create(res); + f->isdirectory = TRUE; + upload->total_directories++; + ui_threadpool_job(upload->queue, upload->ui, qthr_dir_upload, f, uithr_dir_uploaded, f); SYS_DIR dir = sys_opendir(f->path); if (dir) { @@ -289,43 +386,40 @@ if(!strcmp(entry->name, ".") || !strcmp(entry->name, "..")) { continue; } - + cxmutstr newpath = util_concat_sys_path(cx_str(f->path), cx_str(entry->name)); char *new_upload_path = util_concat_path(f->upload_path, entry->name); - DUFile child; - child.path = newpath.ptr; - child.upload_path = new_upload_path; - cxListAdd(stack, &child); + DUFile *child = malloc(sizeof(DUFile)); + child->path = newpath.ptr; + child->upload_path = new_upload_path; + child->isdirectory = FALSE; + child->bytes = 0; + child->upload = upload; + child->error = 0; + cxListAdd(stack, child); } sys_closedir(dir); } } else if (S_ISREG(s.st_mode)) { - FILE *in = sys_fopen(f->path, "rb"); - if (in) { - dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); - //dav_set_content_length(res, s.st_size); - int err = dav_store(res); - if (err) { - // TODO: error + f->isdirectory = FALSE; + f->bytes = s.st_size; + upload->total_files++; + upload->total_bytes += s.st_size; + ui_threadpool_job(upload->queue, upload->ui, qthr_file_upload, f, uithr_file_uploaded, f); + } + } + } // TODO: else error msg - } - fclose(in); - } - } - } // TODO: else error msg + ui_threadpool_job(upload->queue, upload->ui, qthr_upload_finished, upload, uithr_upload_finished, upload); - dav_resource_free(res); - free(path); - - cxListRemove(stack, 0); - } + ui_filelist_free(upload->files); return 0; } -static void uithr_file_upload_finished(UiEvent *event, void *data) { +static void uithr_upload_scan_finished(UiEvent *event, void *data) { DavFileUpload *upload = data; } @@ -341,11 +435,14 @@ // create upload obj, that contains all relevant data for the upload DavFileUpload *upload = malloc(sizeof(DavFileUpload)); + memset(upload, 0, sizeof(DavFileUpload)); + upload->ui = ui; upload->browser = browser; upload->sn = upload_session; upload->files = files; upload->base_path = strdup(browser->current->path); + upload->queue = ui_threadpool_create(1); // create upload progress window UiObject *dialog = ui_simple_window("Upload", upload); @@ -365,8 +462,8 @@ ui_set(upload->speed_label, ""); ui_set(upload->progress, 0); - //ui_show(dialog); + ui_show(dialog); // start upload and stat threads - ui_job(ui, jobthr_file_upload, upload, uithr_file_upload_finished, upload); + ui_job(ui, jobthr_upload_scan, upload, uithr_upload_scan_finished, upload); }