diff options
author | Yorhel <git@yorhel.nl> | 2014-03-25 12:45:47 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2014-03-25 12:47:17 +0100 |
commit | b872d036547f950a9613ec51d60cbe2376d05981 (patch) | |
tree | 197798c93eb27c4149628679618071f916affc47 | |
parent | 30cdd2570faffbf13a608c8b2c3ceebf7deb07c7 (diff) |
dl: Fix download of 0-byte files + resume finalize on priority change
The latter is required to recover from errors in download finalization.
(Errors will be properly handled in next commit)
0-byte files also take a shorter route, no attempt to open a connection
to the user is made.
-rw-r--r-- | src/dl.c | 13 | ||||
-rw-r--r-- | src/dlfile.c | 81 |
2 files changed, 52 insertions, 42 deletions
@@ -586,6 +586,9 @@ static gboolean dl_queue_addfile(guint64 uid, char *hash, guint64 size, char *fn dl_queue_insert(dl, FALSE); dl_user_add(dl, uid, 0, NULL); db_dl_adduser(dl->hash, uid, 0, NULL); + // Empty files get a shortcut here + if(!size) + dlfile_finished(dl); return TRUE; } @@ -715,9 +718,13 @@ void dl_queue_setprio(dl_t *dl, signed char prio) { int i; for(i=0; i<dl->u->len; i++) g_sequence_sort_changed(g_ptr_array_index(dl->u, i), dl_user_dl_sort, NULL); - // Start the download if it is enabled - if(enabled) - dl_queue_start(); + // Start downloading or re-attempt finalization if it is enabled + if(enabled) { + if(!dl->active_threads && (dl->hassize || !dl->islist) && dl->have == dl->size) + dlfile_finished(dl); + else + dl_queue_start(); + } /* TODO: Disconnect active users if the dl item is disabled */ } diff --git a/src/dlfile.c b/src/dlfile.c index ce9dcdf..f942ad9 100644 --- a/src/dlfile.c +++ b/src/dlfile.c @@ -341,8 +341,49 @@ void dlfile_rm(dl_t *dl) { } +/* Create the inc file and initialize the necessary structs to prepare for + * handling downloaded data. */ +static gboolean dlfile_open(dl_t *dl) { + if(dl->incfd <= 0) + dl->incfd = open(dl->inc, O_WRONLY|O_CREAT, 0666); + if(dl->incfd < 0) { + g_warning("Error opening %s: %s", dl->inc, g_strerror(errno)); + dl_queue_seterr(dl, DLE_IO_INC, g_strerror(errno)); + return FALSE; + } + + /* Everything else has already been initialized if we have a thread */ + if(dl->threads) + return TRUE; + + if(!dl->islist) { + dl->bitmap = bita_new(dlfile_chunks(dl->size)); + if(!dlfile_save_bitmap(dl, dl->incfd)) { + g_warning("Error writing bitmap for `%s': %s.", dl->dest, g_strerror(errno)); + dl_queue_seterr(dl, DLE_IO_INC, g_strerror(errno)); + free(dl->bitmap); + dl->bitmap = NULL; + return FALSE; + } + } + + dlfile_thread_t *t = g_slice_new0(dlfile_thread_t); + t->dl = dl; + t->chunk = 0; + t->allocated = 0; + if(!dl->islist) + t->avail = dlfile_chunks(dl->size); + tth_init(&t->hash_tth); + dl->threads = g_slist_prepend(dl->threads, t); + return TRUE; +} + + /* XXX: This function may block in the main thread for a while. Perhaps do it in a threadpool? */ -static void dlfile_finished(dl_t *dl) { +void dlfile_finished(dl_t *dl) { + if(dl->incfd <= 0 && !dlfile_open(dl)) + return; + /* Regular files: Remove bitmap from the file * File lists: Ensure that the file size is correct after we've downloaded a * longer file list before that got interrupted. */ @@ -386,44 +427,6 @@ static void dlfile_finished(dl_t *dl) { } -/* Create the inc file and initialize the necessary structs to prepare for - * handling downloaded data. */ -static gboolean dlfile_open(dl_t *dl) { - if(dl->incfd <= 0) - dl->incfd = open(dl->inc, O_WRONLY|O_CREAT, 0666); - if(dl->incfd < 0) { - g_warning("Error opening %s: %s", dl->inc, g_strerror(errno)); - dl_queue_seterr(dl, DLE_IO_INC, g_strerror(errno)); - return FALSE; - } - - /* Everything else has already been initialized if we have a thread */ - if(dl->threads) - return TRUE; - - if(!dl->islist) { - dl->bitmap = bita_new(dlfile_chunks(dl->size)); - if(!dlfile_save_bitmap(dl, dl->incfd)) { - g_warning("Error writing bitmap for `%s': %s.", dl->dest, g_strerror(errno)); - dl_queue_seterr(dl, DLE_IO_INC, g_strerror(errno)); - free(dl->bitmap); - dl->bitmap = NULL; - return FALSE; - } - } - - dlfile_thread_t *t = g_slice_new0(dlfile_thread_t); - t->dl = dl; - t->chunk = 0; - t->allocated = 0; - if(!dl->islist) - t->avail = dlfile_chunks(dl->size); - tth_init(&t->hash_tth); - dl->threads = g_slist_prepend(dl->threads, t); - return TRUE; -} - - /* The 'speed' argument should be a pessimistic estimate of the peers' speed, * in bytes/s. I think this is best obtained from a 30 second average. * Returns the thread pointer. */ |