summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2014-03-25 12:45:47 +0100
committerYorhel <git@yorhel.nl>2014-03-25 12:47:17 +0100
commitb872d036547f950a9613ec51d60cbe2376d05981 (patch)
tree197798c93eb27c4149628679618071f916affc47
parent30cdd2570faffbf13a608c8b2c3ceebf7deb07c7 (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.c13
-rw-r--r--src/dlfile.c81
2 files changed, 52 insertions, 42 deletions
diff --git a/src/dl.c b/src/dl.c
index 4b1f1ec..e546462 100644
--- a/src/dl.c
+++ b/src/dl.c
@@ -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. */