]> git.ipfire.org Git - pakfire.git/commitdiff
downloader: Make retrieve use easy cURL interface
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 10 Apr 2021 17:24:36 +0000 (17:24 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 10 Apr 2021 17:29:29 +0000 (17:29 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/downloader.c
tests/libpakfire/downloader.c

index edafd5859b7415bad1031baf93ca304995f07dfd..ce558380f2af5019b842e631e0e690c8f0287860 100644 (file)
 #include <json.h>
 
 #include <pakfire/downloader.h>
+#include <pakfire/i18n.h>
 #include <pakfire/logging.h>
 #include <pakfire/pakfire.h>
+#include <pakfire/progressbar.h>
 #include <pakfire/types.h>
 #include <pakfire/util.h>
 
@@ -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
index a5353dcd8f8f65e476896e7a748a69e99e57ae64..ccf80d6cc0aac020ded58613ce20322851d12523 100644 (file)
@@ -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);