]> git.ipfire.org Git - pakfire.git/commitdiff
mirrors: Refactor mirror handling
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 31 Jan 2025 12:00:34 +0000 (12:00 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 31 Jan 2025 12:00:34 +0000 (12:00 +0000)
xfers will now immediately get a mirror assigned when they have a
mirrorlist set so that we don't have to play any games later.

When an xfer has failed, we will ask for another mirror and run again.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/mirrorlist.c
src/pakfire/repo.c
src/pakfire/xfer.c

index 8e262a783a585cd6c148586cd9febac645496059..60ffda5837bb93ea831dec1543cb5b60f0212ac4 100644 (file)
@@ -145,6 +145,8 @@ ERROR:
 }
 
 int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
+       int r;
+
        if (!path || !*path) {
                errno = EINVAL;
                return 1;
@@ -165,7 +167,7 @@ int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
        struct json_object* mirrors = NULL;
 
        // Check if we found a valid mirrorlist
-       int r = pakfire_mirrorlist_check_mirrorlist(list, json);
+       r = pakfire_mirrorlist_check_mirrorlist(list, json);
        if (r)
                goto ERROR;
 
@@ -233,22 +235,44 @@ int pakfire_mirrorlist_empty(struct pakfire_mirrorlist* list) {
        return list->num_mirrors == 0;
 }
 
+/*
+       Return the first mirror that isn't broken
+*/
 struct pakfire_mirror* pakfire_mirrorlist_get_first(struct pakfire_mirrorlist* list) {
-       if (!list->num_mirrors)
-               return NULL;
+       for (unsigned int i = 0; i < list->num_mirrors; i++) {
+               if (pakfire_mirror_is_broken(list->mirrors[i]))
+                       continue;
+
+               return pakfire_mirror_ref(list->mirrors[i]);
+       }
 
-       return pakfire_mirror_ref(list->mirrors[0]);
+       return NULL;
 }
 
 struct pakfire_mirror* pakfire_mirrorlist_get_next(
                struct pakfire_mirrorlist* list, struct pakfire_mirror* mirror) {
+       // Return NULL if we have reached the end of the list
+       if (!mirror)
+               return NULL;
+
+       int found = 0;
+
+       // Walk through all mirrors until we have found the current one
        for (unsigned int i = 0; i < list->num_mirrors; i++) {
-               if (list->mirrors[i] == mirror) {
-                       if (i < list->num_mirrors)
-                               return list->mirrors[i+1];
+               if (!found) {
+                       // Set found once we found our mirror
+                       if (list->mirrors[i] == mirror)
+                               found = 1;
 
-                       break;
+                       continue;
                }
+
+               // Skip any broken mirrors
+               if (pakfire_mirror_is_broken(list->mirrors[i]))
+                       continue;
+
+               // Return the mirror
+               return pakfire_mirror_ref(list->mirrors[i]);
        }
 
        return NULL;
index bbded6c2ea18dbed837530b208e5e75ee2d5a4f9..486ab41dcae59badb398f8153cd824e95604a1c3 100644 (file)
@@ -729,12 +729,10 @@ static int pakfire_repo_refresh_mirrorlist(struct pakfire_repo* self, const int
        if (r < 0)
                goto ERROR;
 
-#if 0 // This function seems to SEGV really hard
        // Read the mirrorlist
        r = pakfire_mirrorlist_read(mirrorlist, path);
        if (r < 0)
                goto ERROR;
-#endif
 
        // Store the mirrorlist
        self->appdata->mirrorlist = pakfire_mirrorlist_ref(mirrorlist);
index 91294117a3ef1dc681988190a9ce9b769f796838..cf291164865b0fc0f0979ff745e682e6a58a751b 100644 (file)
@@ -519,10 +519,25 @@ const char* pakfire_xfer_get_effective_url(struct pakfire_xfer* xfer) {
 }
 
 int pakfire_xfer_set_mirrorlist(struct pakfire_xfer* xfer, struct pakfire_mirrorlist* mirrors) {
-       if (xfer->mirrors)
+       // Drop all references to a former mirrorlist
+       if (xfer->mirrors) {
                pakfire_mirrorlist_unref(xfer->mirrors);
+               xfer->mirrors = NULL;
+       }
+
+       // Drop all references to the formerly selected mirror
+       if (xfer->mirror) {
+               pakfire_mirror_unref(xfer->mirror);
+               xfer->mirror = NULL;
+       }
 
-       xfer->mirrors = pakfire_mirrorlist_ref(mirrors);
+       // If a new list was passed, we store a reference to it
+       if (mirrors) {
+               xfer->mirrors = pakfire_mirrorlist_ref(mirrors);
+
+               // Select the first mirror from the list
+               xfer->mirror = pakfire_mirrorlist_get_first(xfer->mirrors);
+       }
 
        return 0;
 }
@@ -900,6 +915,36 @@ static pakfire_xfer_error_code_t pakfire_xfer_code(CURLcode code, int http_statu
        }
 }
 
+static int pakfire_xfer_next_mirror(struct pakfire_xfer* xfer) {
+       struct pakfire_mirror* mirror = NULL;
+
+       // If our mirror is broken, we select the next one
+       if (xfer->mirror) {
+               // Choose the next mirror
+               mirror = pakfire_mirrorlist_get_next(xfer->mirrors, xfer->mirror);
+
+               // Free the previous mirror
+               pakfire_mirror_unref(xfer->mirror);
+
+               // Store the new mirror
+               if (mirror) {
+                       DEBUG(xfer->ctx, "Selected mirror %s\n", pakfire_mirror_get_url(mirror));
+
+                       xfer->mirror = pakfire_mirror_ref(mirror);
+
+               // If we could not find a mirror, we clear the pointer
+               } else {
+                       xfer->mirror = NULL;
+               }
+       }
+
+       // Cleanup
+       if (mirror)
+               pakfire_mirror_unref(mirror);
+
+       return 0;
+}
+
 static int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code) {
        int r;
 
@@ -929,6 +974,11 @@ static int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code) {
        if (xfer->mirror) {
                pakfire_mirror_xfer_failed(xfer->mirror);
 
+               // Select the next mirror
+               r = pakfire_xfer_next_mirror(xfer);
+               if (r < 0)
+                       return r;
+
                // Try again with another mirror
                return -EAGAIN;
        }
@@ -947,34 +997,6 @@ static int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code) {
        return code;
 }
 
-static int pakfire_xfer_select_mirror(struct pakfire_xfer* xfer) {
-       // Choose the next mirror
-       if (xfer->mirror)
-               xfer->mirror = pakfire_mirrorlist_get_next(xfer->mirrors, xfer->mirror);
-
-       // If no mirror has been selected yet, choose the first one
-       else
-               xfer->mirror = pakfire_mirrorlist_get_first(xfer->mirrors);
-
-       // Skip this mirror if it is broken
-       while (xfer->mirror && pakfire_mirror_is_broken(xfer->mirror)) {
-               // Move on to the next mirror
-               xfer->mirror = pakfire_mirrorlist_get_next(xfer->mirrors, xfer->mirror);
-       }
-
-       // No mirror found
-       if (!xfer->mirror) {
-               ERROR(xfer->ctx, "No mirrors left to try\n");
-
-               // No mirrors left
-               return ENOENT;
-       }
-
-       DEBUG(xfer->ctx, "Selected mirror %s\n", pakfire_mirror_get_url(xfer->mirror));
-
-       return 0;
-}
-
 static const char* curl_http_version(long v) {
        switch (v) {
 #ifdef CURL_HTTP_VERSION_3_0
@@ -1481,12 +1503,8 @@ static int pakfire_xfer_prepare_url(struct pakfire_xfer* xfer) {
                if (r)
                        goto ERROR;
 
-       // Join path if we are using mirrors
-       } else if (xfer->mirrors && !pakfire_mirrorlist_empty(xfer->mirrors)) {
-               r = pakfire_xfer_select_mirror(xfer);
-               if (r)
-                       goto ERROR;
-
+       // Join path if we are using a mirror
+       } else if (xfer->mirror) {
                // Set the mirror's base URL first
                r = curl_url_set(xfer->fullurl, CURLUPART_URL,
                        pakfire_mirror_get_url(xfer->mirror), 0);