diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/main/main.cpp | 80 | ||||
-rw-r--r-- | src/buildtool/serve_api/remote/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/serve_api/remote/config.hpp | 186 |
3 files changed, 196 insertions, 71 deletions
diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index bdd1bed5..357bf7e9 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -23,6 +23,7 @@ #include <unordered_map> #include <unordered_set> #include <utility> +#include <variant> #include "gsl/gsl" #include "nlohmann/json.hpp" @@ -152,45 +153,38 @@ void SetupExecutionConfig(EndpointArguments const& eargs, } } -void SetupServeConfig(ServeArguments const& srvargs, - CommonArguments const& cargs, - BuildArguments const& bargs, - TCArguments const& tc) { - if (srvargs.remote_serve_address) { - if (not RemoteServeConfig::Instance().SetRemoteAddress( - *srvargs.remote_serve_address)) { - Logger::Log(LogLevel::Error, - "Setting serve service address '{}' failed.", - *srvargs.remote_serve_address); - std::exit(kExitFailure); - } - } - if (not srvargs.repositories.empty() and - not RemoteServeConfig::Instance().SetKnownRepositories( - srvargs.repositories)) { - Logger::Log(LogLevel::Error, - "Setting serve service repositories failed."); - std::exit(kExitFailure); - } - // make parallelism and build options available for remote builds - if (not RemoteServeConfig::Instance().SetJobs(cargs.jobs)) { - Logger::Log(LogLevel::Error, "Setting jobs failed."); - std::exit(kExitFailure); - } - if (bargs.build_jobs > 0 and - not RemoteServeConfig::Instance().SetBuildJobs(bargs.build_jobs)) { - Logger::Log(LogLevel::Error, "Setting build jobs failed."); - std::exit(kExitFailure); +[[nodiscard]] auto CreateServeConfig(ServeArguments const& srvargs, + CommonArguments const& cargs, + BuildArguments const& bargs, + TCArguments const& tc) noexcept + -> std::optional<RemoteServeConfig> { + RemoteServeConfig::Builder builder; + builder.SetRemoteAddress(srvargs.remote_serve_address) + .SetKnownRepositories(srvargs.repositories) + .SetJobs(cargs.jobs) + .SetActionTimeout(bargs.timeout) + .SetTCStrategy(tc.target_cache_write_strategy); + + if (bargs.build_jobs > 0) { + builder.SetBuildJobs(bargs.build_jobs); } - if (not RemoteServeConfig::Instance().SetActionTimeout(bargs.timeout)) { - Logger::Log(LogLevel::Error, "Setting action timeout failed."); - std::exit(kExitFailure); + + auto result = builder.Build(); + if (auto* config = std::get_if<RemoteServeConfig>(&result)) { + if (config->TCStrategy() == TargetCacheWriteStrategy::Disable) { + Logger::Log( + LogLevel::Info, + "Target-level cache writing of serve service is disabled."); + } + return std::move(*config); } - RemoteServeConfig::Instance().SetTCStrategy(tc.target_cache_write_strategy); - if (tc.target_cache_write_strategy == TargetCacheWriteStrategy::Disable) { - Logger::Log(LogLevel::Info, - "Target-level cache writing of serve service is disabled."); + + if (auto* error = std::get_if<std::string>(&result)) { + Logger::Log(LogLevel::Error, *error); + return std::nullopt; } + Logger::Log(LogLevel::Error, "Unknown error occured"); + return std::nullopt; } void SetupAuthConfig(CommonAuthArguments const& authargs, @@ -845,8 +839,13 @@ auto main(int argc, char* argv[]) -> int { SetupFileChunker(); SetupExecutionConfig( arguments.endpoint, arguments.build, arguments.rebuild); - SetupServeConfig( + + auto serve_config = CreateServeConfig( arguments.serve, arguments.common, arguments.build, arguments.tc); + if (not serve_config) { + return kExitFailure; + } + SetupAuthConfig(arguments.auth, arguments.cauth, arguments.sauth); if (arguments.cmd == SubCommand::kGc) { @@ -867,9 +866,9 @@ auto main(int argc, char* argv[]) -> int { if (arguments.cmd == SubCommand::kServe) { SetupServeServiceConfig(arguments.service); - auto serve = ServeApi::Create(RemoteServeConfig::Instance()); + auto serve = ServeApi::Create(*serve_config); if (!ServeServerImpl::Instance().Run( - RemoteServeConfig::Instance(), + *serve_config, serve, !RemoteExecutionConfig::RemoteAddress())) { return kExitFailure; @@ -952,8 +951,7 @@ auto main(int argc, char* argv[]) -> int { DetermineRoots(&repo_config, arguments.common, arguments.analysis); #ifndef BOOTSTRAP_BUILD_TOOL - std::optional<ServeApi> serve = - ServeApi::Create(RemoteServeConfig::Instance()); + std::optional<ServeApi> serve = ServeApi::Create(*serve_config); #else std::optional<ServeApi> serve; #endif // BOOTSTRAP_BUILD_TOOL diff --git a/src/buildtool/serve_api/remote/TARGETS b/src/buildtool/serve_api/remote/TARGETS index e1a90e2e..1d2a0917 100644 --- a/src/buildtool/serve_api/remote/TARGETS +++ b/src/buildtool/serve_api/remote/TARGETS @@ -5,6 +5,7 @@ , "deps": [ ["src/buildtool/common/remote", "remote_common"] , ["src/buildtool/main", "build_utils"] + , ["@", "fmt", "", "fmt"] ] , "stage": ["src", "buildtool", "serve_api", "remote"] } diff --git a/src/buildtool/serve_api/remote/config.hpp b/src/buildtool/serve_api/remote/config.hpp index 30197b53..4e5c3c21 100644 --- a/src/buildtool/serve_api/remote/config.hpp +++ b/src/buildtool/serve_api/remote/config.hpp @@ -19,13 +19,19 @@ #include <cstddef> #include <filesystem> #include <iterator> +#include <optional> +#include <string> +#include <utility> +#include <variant> #include <vector> +#include "fmt/core.h" #include "src/buildtool/common/remote/remote_common.hpp" #include "src/buildtool/main/build_utils.hpp" -class RemoteServeConfig { - public: +struct RemoteServeConfig final { + class Builder; + // Obtain global instance [[nodiscard]] static auto Instance() noexcept -> RemoteServeConfig& { static RemoteServeConfig config; @@ -33,90 +39,210 @@ class RemoteServeConfig { } // Set remote execution and cache address, unsets if parsing `address` fails - [[nodiscard]] auto SetRemoteAddress(std::string const& address) noexcept + [[nodiscard]] auto SetRemoteAddress(std::string const& value) noexcept -> bool { - return static_cast<bool>(remote_address_ = ParseAddress(address)); + return static_cast<bool>(remote_address = ParseAddress(value)); } // Set the list of known repositories [[nodiscard]] auto SetKnownRepositories( - std::vector<std::filesystem::path> const& repos) noexcept -> bool { - repositories_ = std::vector<std::filesystem::path>( - std::make_move_iterator(repos.begin()), - std::make_move_iterator(repos.end())); - return repos.size() == repositories_.size(); + std::vector<std::filesystem::path> const& value) noexcept -> bool { + known_repositories = std::vector<std::filesystem::path>( + std::make_move_iterator(value.begin()), + std::make_move_iterator(value.end())); + return value.size() == known_repositories.size(); } // Set the number of jobs - [[nodiscard]] auto SetJobs(std::size_t jobs) noexcept -> bool { - return static_cast<bool>(jobs_ = jobs); + [[nodiscard]] auto SetJobs(std::size_t value) noexcept -> bool { + return static_cast<bool>(jobs = value); } // Set the number of build jobs - [[nodiscard]] auto SetBuildJobs(std::size_t build_jobs) noexcept -> bool { - return static_cast<bool>(build_jobs_ = build_jobs); + [[nodiscard]] auto SetBuildJobs(std::size_t value) noexcept -> bool { + return static_cast<bool>(build_jobs = value); } // Set the action timeout [[nodiscard]] auto SetActionTimeout( - std::chrono::milliseconds const& timeout) noexcept -> bool { - timeout_ = timeout; - return timeout_ > std::chrono::seconds{0}; + std::chrono::milliseconds const& value) noexcept -> bool { + action_timeout = value; + return action_timeout > std::chrono::seconds{0}; } - void SetTCStrategy(TargetCacheWriteStrategy strategy) noexcept { - tc_strategy_ = strategy; + void SetTCStrategy(TargetCacheWriteStrategy value) noexcept { + tc_strategy = value; } // Remote execution address, if set [[nodiscard]] auto RemoteAddress() const noexcept -> std::optional<ServerAddress> { - return remote_address_; + return remote_address; } // Repositories known to 'just serve' [[nodiscard]] auto KnownRepositories() const noexcept -> const std::vector<std::filesystem::path>& { - return repositories_; + return known_repositories; } // Get the number of jobs - [[nodiscard]] auto Jobs() const noexcept -> std::size_t { return jobs_; } + [[nodiscard]] auto Jobs() const noexcept -> std::size_t { return jobs; } // Get the number of build jobs [[nodiscard]] auto BuildJobs() const noexcept -> std::size_t { - return build_jobs_; + return build_jobs; } // Get the action timeout [[nodiscard]] auto ActionTimeout() const noexcept -> std::chrono::milliseconds { - return timeout_; + return action_timeout; } // Get the target-level cache write strategy [[nodiscard]] auto TCStrategy() const noexcept -> TargetCacheWriteStrategy { - return tc_strategy_; + return tc_strategy; + } + + // Server address of remote execution. + std::optional<ServerAddress> remote_address{}; + + // Known Git repositories to serve server. + std::vector<std::filesystem::path> known_repositories{}; + + // Number of jobs + std::size_t jobs = 0; + + // Number of build jobs + std::size_t build_jobs = 0; + + // Action timeout + std::chrono::milliseconds action_timeout{}; + + // Strategy for synchronizing target-level cache + TargetCacheWriteStrategy tc_strategy{TargetCacheWriteStrategy::Sync}; +}; + +class RemoteServeConfig::Builder final { + public: + // Set remote execution and cache address, unsets if parsing `address` fails + auto SetRemoteAddress(std::optional<std::string> value) noexcept + -> Builder& { + remote_address_ = std::move(value); + return *this; + } + + // Set the list of known repositories + auto SetKnownRepositories(std::vector<std::filesystem::path> value) noexcept + -> Builder& { + known_repositories_ = std::move(value); + return *this; + } + + // Set the number of jobs + auto SetJobs(std::size_t value) noexcept -> Builder& { + jobs_ = value; + return *this; + } + + // Set the number of build jobs + auto SetBuildJobs(std::size_t value) noexcept -> Builder& { + build_jobs_ = value; + return *this; + } + + // Set the action timeout + auto SetActionTimeout(std::chrono::milliseconds const& value) noexcept + -> Builder& { + action_timeout_ = value; + return *this; + } + + auto SetTCStrategy(TargetCacheWriteStrategy value) noexcept -> Builder& { + tc_strategy_ = value; + return *this; + } + + /// \brief Finalize building and create RemoteServeConfig. + /// \return RemoteServeConfig on success or an error on failure. + [[nodiscard]] auto Build() noexcept + -> std::variant<RemoteServeConfig, std::string> { + // To not duplicate default arguments of RemoteServeConfig in builder, + // create a default config and copy default arguments from there. + RemoteServeConfig const default_config; + + auto remote_address = default_config.remote_address; + if (remote_address_.has_value()) { + remote_address = ParseAddress(*remote_address_); + if (not remote_address) { + return fmt::format("Setting serve service address '{}' failed.", + *remote_address_); + } + } + + auto known_repositories = default_config.known_repositories; + if (known_repositories_.has_value()) { + known_repositories = std::move(*known_repositories_); + } + + auto jobs = default_config.jobs; + if (jobs_.has_value()) { + jobs = *jobs_; + if (jobs == 0) { + return "Setting jobs failed."; + } + } + + auto build_jobs = default_config.jobs; + if (build_jobs_.has_value()) { + build_jobs = *build_jobs_; + if (build_jobs == 0) { + return "Setting build jobs failed."; + } + } + + auto action_timeout = default_config.action_timeout; + if (action_timeout_.has_value()) { + action_timeout = *action_timeout_; + if (bool const valid = action_timeout > std::chrono::seconds{0}; + not valid) { + return "Setting action timeout failed."; + } + } + + auto tc_strategy = default_config.tc_strategy; + if (tc_strategy_.has_value()) { + tc_strategy = *tc_strategy_; + } + + return RemoteServeConfig{ + .remote_address = std::move(remote_address), + .known_repositories = std::move(known_repositories), + .jobs = jobs, + .build_jobs = build_jobs, + .action_timeout = action_timeout, + .tc_strategy = tc_strategy}; } private: // Server address of remote execution. - std::optional<ServerAddress> remote_address_{}; + std::optional<std::string> remote_address_; // Known Git repositories to serve server. - std::vector<std::filesystem::path> repositories_{}; + std::optional<std::vector<std::filesystem::path>> known_repositories_; // Number of jobs - std::size_t jobs_{}; + std::optional<std::size_t> jobs_; // Number of build jobs - std::size_t build_jobs_{}; + std::optional<std::size_t> build_jobs_; // Action timeout - std::chrono::milliseconds timeout_{}; + std::optional<std::chrono::milliseconds> action_timeout_; // Strategy for synchronizing target-level cache - TargetCacheWriteStrategy tc_strategy_{TargetCacheWriteStrategy::Sync}; + std::optional<TargetCacheWriteStrategy> tc_strategy_; }; #endif // INCLUDED_SRC_BUILDTOOL_SERVE_API_REMOTE_CONFIG_HPP |