From: Michael Tremer Date: Sat, 10 Apr 2021 17:24:36 +0000 (+0000) Subject: downloader: Make retrieve use easy cURL interface X-Git-Tag: 0.9.28~1285^2~375 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b8c77018324ec7e7708bfa5bd704a0261773d21b;p=pakfire.git downloader: Make retrieve use easy cURL interface Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/downloader.c b/src/libpakfire/downloader.c index edafd5859..ce558380f 100644 --- a/src/libpakfire/downloader.c +++ b/src/libpakfire/downloader.c @@ -28,8 +28,10 @@ #include #include +#include #include #include +#include #include #include @@ -75,6 +77,7 @@ struct pakfire_downloader { Pakfire pakfire; int nrefs; + struct pakfire_progressbar* progressbar; unsigned int parallel; // cURL multi handle @@ -158,6 +161,9 @@ static void pakfire_downloader_free(struct pakfire_downloader* downloader) { pakfire_transfer_free(transfer); } + if (downloader->progressbar) + pakfire_progressbar_unref(downloader->progressbar); + if (downloader->curl) curl_multi_cleanup(downloader->curl); @@ -191,6 +197,11 @@ int pakfire_downloader_create(struct pakfire_downloader** downloader, Pakfire pa if (r) goto ERROR; + // Create the progressbar + r = pakfire_progressbar_create(&d->progressbar, d->pakfire, NULL); + if (r) + goto ERROR; + *downloader = d; return 0; @@ -252,19 +263,21 @@ static int debug_callback(CURL *handle, curl_infotype type, } #endif -int pakfire_downloader_add_transfer(struct pakfire_downloader* downloader, - struct pakfire_mirrorlist* mirrors, const char* url, const char* path) { +static struct pakfire_transfer* pakfire_downloader_create_transfer( + struct pakfire_downloader* downloader, struct pakfire_mirrorlist* mirrors, + const char* url, const char* path) { DEBUG(downloader->pakfire, "Adding download of %s\n", url); // Do not allow relative URLs when no mirrors are set if (!pakfire_url_is_absolute(url) && !mirrors) { ERROR(downloader->pakfire, "Relative URLs cannot be used without a mirrorlist\n"); - return EINVAL; + errno = EINVAL; + return NULL; } struct pakfire_transfer* transfer = calloc(1, sizeof(*transfer)); if (!transfer) - return ENOMEM; + return NULL; // Copy URL snprintf(transfer->url, sizeof(transfer->url) - 1, "%s", url); @@ -312,16 +325,26 @@ int pakfire_downloader_add_transfer(struct pakfire_downloader* downloader, curl_easy_setopt(transfer->handle, CURLOPT_WRITEDATA, transfer->f); - // Push this transfer onto the queue - TAILQ_INSERT_HEAD(&downloader->transfers, transfer, nodes); - // Success - return 0; + return transfer; ERROR: pakfire_transfer_free(transfer); - return 1; + return NULL; +} + +int pakfire_downloader_add_transfer(struct pakfire_downloader* downloader, + struct pakfire_mirrorlist* mirrors, const char* url, const char* path) { + struct pakfire_transfer* transfer = pakfire_downloader_create_transfer( + downloader, mirrors, url, path); + if (!transfer) + return 1; + + // Push this transfer onto the queue + TAILQ_INSERT_HEAD(&downloader->transfers, transfer, nodes); + + return 0; } static int pakfire_transfer_select_mirror(struct pakfire_downloader* downloader, @@ -398,7 +421,7 @@ static int pakfire_transfer_save(struct pakfire_downloader* downloader, } static int pakfire_transfer_fail(struct pakfire_downloader* downloader, - struct pakfire_transfer* transfer) { + struct pakfire_transfer* transfer, int code) { int r; DEBUG(downloader->pakfire, "Transfer failed\n"); @@ -428,7 +451,7 @@ static int pakfire_transfer_fail(struct pakfire_downloader* downloader, } static int pakfire_transfer_done(struct pakfire_downloader* downloader, - struct pakfire_transfer* transfer, CURLMsg* msg) { + struct pakfire_transfer* transfer, int code) { CURL* h = transfer->handle; int r; @@ -441,7 +464,7 @@ static int pakfire_transfer_done(struct pakfire_downloader* downloader, curl_off_t speed; DEBUG(downloader->pakfire, "cURL transfer done: %d - %s\n", - msg->data.result, curl_easy_strerror(msg->data.result)); + code, curl_easy_strerror(code)); // Protocol curl_easy_getinfo(h, CURLINFO_PROTOCOL, &protocol); @@ -494,7 +517,7 @@ static int pakfire_transfer_done(struct pakfire_downloader* downloader, // Treat all other response codes as an error default: - r = pakfire_transfer_fail(downloader, transfer); + r = pakfire_transfer_fail(downloader, transfer, code); if (r) return r; @@ -508,22 +531,7 @@ static int pakfire_transfer_done(struct pakfire_downloader* downloader, return 0; } -int pakfire_downloader_retrieve(struct pakfire_downloader* downloader, - struct pakfire_mirrorlist* mirrors, const char* url, const char* path) { - // Do not run this when there are transfers pending - if (!TAILQ_EMPTY(&downloader->transfers)) - return EBUSY; - - // Add the transfer - int r = pakfire_downloader_add_transfer(downloader, mirrors, url, path); - if (r) - return r; - - // Run it - return pakfire_downloader_run(downloader); -} - -static int pakfire_downloader_activate_transfer(struct pakfire_downloader* downloader, +static int pakfire_downloader_prepare_transfer(struct pakfire_downloader* downloader, struct pakfire_transfer* transfer) { // Increment tries transfer->tries++; @@ -566,14 +574,47 @@ static int pakfire_downloader_activate_transfer(struct pakfire_downloader* downl return 1; } - // Add the handle to cURL - int r = curl_multi_add_handle(downloader->curl, transfer->handle); - if (r) { - ERROR(downloader->pakfire, "Adding handle failed\n"); + return 0; +} + +/* + This function performs one single transfer in blocking mode. +*/ +static int pakfire_downloader_perform( + struct pakfire_downloader* downloader, struct pakfire_transfer* transfer) { + int r; + + // Prepare the transfer + r = pakfire_downloader_prepare_transfer(downloader, transfer); + if (r) return r; - } - return 0; + // Perform the download + r = curl_easy_perform(transfer->handle); + + if (r == CURLE_OK) + return pakfire_transfer_done(downloader, transfer, r); + + // Handle errors + r = pakfire_transfer_fail(downloader, transfer, r); + if (r == EAGAIN) + return pakfire_downloader_perform(downloader, transfer); + + return r; +} + +int pakfire_downloader_retrieve(struct pakfire_downloader* downloader, + struct pakfire_mirrorlist* mirrors, const char* url, const char* path) { + struct pakfire_transfer* transfer = pakfire_downloader_create_transfer( + downloader, mirrors, url, path); + if (!transfer) + return 1; + + // Perform the download + int r = pakfire_downloader_perform(downloader, transfer); + pakfire_transfer_free(transfer); + + return r; } int pakfire_downloader_run(struct pakfire_downloader* downloader) { @@ -592,11 +633,19 @@ int pakfire_downloader_run(struct pakfire_downloader* downloader) { transfer = TAILQ_LAST(&downloader->transfers, transfers); TAILQ_REMOVE(&downloader->transfers, transfer, nodes); - r = pakfire_downloader_activate_transfer(downloader, transfer); + // Prepare the transfer + r = pakfire_downloader_prepare_transfer(downloader, transfer); + if (r) { + pakfire_transfer_free(transfer); + return r; + } + + // Add the handle to cURL + r = curl_multi_add_handle(downloader->curl, transfer->handle); if (r) { - ERROR(downloader->pakfire, "Could not activate transfer\n"); + ERROR(downloader->pakfire, "Adding handle failed\n"); pakfire_transfer_free(transfer); - continue; + return r; } transfers++; @@ -614,7 +663,7 @@ int pakfire_downloader_run(struct pakfire_downloader* downloader) { curl_multi_remove_handle(downloader->curl, transfer->handle); // Handle whatever comes after the transfer - r = pakfire_transfer_done(downloader, transfer, msg); + r = pakfire_transfer_done(downloader, transfer, msg->data.result); if (r) { // We will try another mirror and therefore insert this // transfer to be picked up again next diff --git a/tests/libpakfire/downloader.c b/tests/libpakfire/downloader.c index a5353dcd8..ccf80d6cc 100644 --- a/tests/libpakfire/downloader.c +++ b/tests/libpakfire/downloader.c @@ -58,7 +58,7 @@ static int test_retrieve_with_pending_transfers(const struct test* t) { // Retrieve a file r = pakfire_downloader_retrieve(d, NULL, DOWNLOAD_URL, DOWNLOAD_PATH); - ASSERT(r == EBUSY); + ASSERT(r == 0); // Cleanup pakfire_downloader_unref(d);