From: Michael Tremer Date: Fri, 31 Jan 2025 12:00:34 +0000 (+0000) Subject: mirrors: Refactor mirror handling X-Git-Tag: 0.9.30~218 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f3ee06895d01e11c6cfe53e0079ee3ae9ede0335;p=pakfire.git mirrors: Refactor mirror handling 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 --- diff --git a/src/pakfire/mirrorlist.c b/src/pakfire/mirrorlist.c index 8e262a78..60ffda58 100644 --- a/src/pakfire/mirrorlist.c +++ b/src/pakfire/mirrorlist.c @@ -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; diff --git a/src/pakfire/repo.c b/src/pakfire/repo.c index bbded6c2..486ab41d 100644 --- a/src/pakfire/repo.c +++ b/src/pakfire/repo.c @@ -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); diff --git a/src/pakfire/xfer.c b/src/pakfire/xfer.c index 91294117..cf291164 100644 --- a/src/pakfire/xfer.c +++ b/src/pakfire/xfer.c @@ -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);