diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/other_tools/just_mr/TARGETS | 6 | ||||
-rw-r--r-- | src/other_tools/just_mr/mirrors.hpp | 62 |
2 files changed, 67 insertions, 1 deletions
diff --git a/src/other_tools/just_mr/TARGETS b/src/other_tools/just_mr/TARGETS index b31efa8d..5a8869c6 100644 --- a/src/other_tools/just_mr/TARGETS +++ b/src/other_tools/just_mr/TARGETS @@ -195,7 +195,11 @@ { "type": ["@", "rules", "CC", "library"] , "name": ["mirrors"] , "hdrs": ["mirrors.hpp"] - , "deps": [["@", "json", "", "json"], ["src/buildtool/logging", "logging"]] + , "deps": + [ ["@", "json", "", "json"] + , ["src/buildtool/logging", "logging"] + , ["src/other_tools/utils", "curl_url_handle"] + ] , "stage": ["src", "other_tools", "just_mr"] } , "rc": diff --git a/src/other_tools/just_mr/mirrors.hpp b/src/other_tools/just_mr/mirrors.hpp index 5801e323..4db387aa 100644 --- a/src/other_tools/just_mr/mirrors.hpp +++ b/src/other_tools/just_mr/mirrors.hpp @@ -18,10 +18,13 @@ #include <exception> #include <memory> #include <string> +#include <unordered_map> +#include <unordered_set> #include <vector> #include "nlohmann/json.hpp" #include "src/buildtool/logging/logger.hpp" +#include "src/other_tools/utils/curl_url_handle.hpp" struct Mirrors { nlohmann::json local_mirrors{}; // maps URLs to list of local mirrors @@ -97,6 +100,65 @@ namespace MirrorsUtils { }; } +/// \brief Sort mirrors by the order of given hostnames. +[[nodiscard]] static inline auto SortByHostname( + std::vector<std::string> const& mirrors, + std::vector<std::string> const& hostnames) -> std::vector<std::string> { + using map_t = std::unordered_map<std::string, std::vector<std::string>>; + map_t mirrors_by_hostname{}; + mirrors_by_hostname.reserve(hostnames.size() + 1); + + // initialize map with known hostnames + std::transform( + hostnames.begin(), + hostnames.end(), + std::inserter(mirrors_by_hostname, mirrors_by_hostname.end()), + [](auto const& hostname) -> typename map_t::value_type { + return {hostname, {/*empty*/}}; + }); + + // fill mirrors list per hostname + for (auto const& mirror : mirrors) { + auto hostname = + CurlURLHandle::GetHostname(mirror).value_or(std::string{}); + auto it = mirrors_by_hostname.find(hostname); + if (it != mirrors_by_hostname.end()) { + mirrors_by_hostname.at(hostname).emplace_back(mirror); + } + else { + // add missing or unknown hostnames to fallback list with key "" + mirrors_by_hostname[""].emplace_back(mirror); + } + } + + std::vector<std::string> ordered{}; + ordered.reserve(mirrors.size()); + + // first, add mirrors in the order defined by hostnames + for (auto const& hostname : hostnames) { + auto it = mirrors_by_hostname.find(hostname); + if (it != mirrors_by_hostname.end()) { + auto& list = it->second; + ordered.insert(ordered.end(), + std::make_move_iterator(list.begin()), + std::make_move_iterator(list.end())); + // clear for safe revisit in case hostnames contains any duplicates + list.clear(); + } + } + + // second, append remaining mirrors from fallback list with key "" + auto it = mirrors_by_hostname.find(""); + if (it != mirrors_by_hostname.end()) { + auto& list = it->second; + ordered.insert(ordered.end(), + std::make_move_iterator(list.begin()), + std::make_move_iterator(list.end())); + } + + return ordered; +} + } // namespace MirrorsUtils #endif // INCLUDED_SRC_OTHER_TOOLS_JUST_MR_MIRRORS_HPP |