#ifndef LIBREPOMGR_SERVER_SETUP_H #define LIBREPOMGR_SERVER_SETUP_H #include "./authentication.h" #include "./buildactions/buildaction.h" #include "./buildactions/buildactiontemplate.h" #include "./globallock.h" #include "../libpkg/data/config.h" #include "../libpkg/data/lockable.h" #include #include #include #include #include #include #include namespace LibRepoMgr { struct LIBREPOMGR_EXPORT ThreadPool { explicit ThreadPool(const char *name, boost::asio::io_context &ioContext, unsigned short threadCount); ~ThreadPool(); const char *const name; std::vector threads; }; struct ServiceStatus; struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable { // the overall configuration (databases, packages, ...) used at various places // -> acquire the config lock for these LibPkg::Config config; // service global configuration; only changed when (re)loading config // -> acquire the setup lock for these std::string configFilePath = "server.conf"; std::string pacmanConfigFilePath = "/etc/pacman.conf"; std::string workingDirectory = "workingdir"; // variables relevant for the web server; only changed when (re)loading config struct LIBREPOMGR_EXPORT WebServerSetup { // only read by build actions and routes; changed when (re)loading config // -> acquire the setup lock for these std::string staticFilesPath; // never changed after setup boost::asio::ip::address address = boost::asio::ip::make_address("127.0.0.1"); unsigned short port = 8090; unsigned short threadCount = 1; boost::asio::io_context ioContext; boost::asio::ssl::context sslContext{ boost::asio::ssl::context::sslv23_client }; bool verifySslCertificates = true; bool logSslCertificateValidation = false; void applyConfig(const std::multimap &multimap); void initSsl(); static bool logCertificateValidation(bool preVerified, boost::asio::ssl::verify_context &context); } webServer; // variables relevant for build actions and web server routes dealing with them struct LIBREPOMGR_EXPORT BuildSetup : public LibPkg::Lockable { struct LIBREPOMGR_EXPORT Worker : private boost::asio::executor_work_guard, public ThreadPool { explicit Worker(BuildSetup &setup); ~Worker(); BuildSetup &setup; }; // read/written by build actions and routes // -> acquire the build lock for these std::vector> actions; std::unordered_set invalidActions; // fields which have their own locking // -> acquire the object's lock BuildActionMetaInfo metaInfo; // only static data so far but maybe extended to allow defining custom build actions // only read by build actions and routes; changed when (re)loading config // -> acquire the setup lock for these std::string workingDirectory = "building"; std::vector pkgbuildsDirs; std::regex ignoreLocalPkgbuildsRegex; std::string makePkgPath = "makepkg"; std::string makeChrootPkgPath = "makechrootpkg"; std::string updatePkgSumsPath = "updpkgsums"; std::string repoAddPath = "repo-add"; std::string repoRemovePath = "repo-remove"; std::string gpgPath = "gpg"; std::string ccacheDir; std::string chrootDir; std::string chrootRootUser = "root"; std::string chrootDefaultUser = "buildservice"; std::string defaultGpgKey; std::string pacmanConfigFilePath; // FIXME: not useful after all?; using config-$arch directory within chrootDir instead std::string makepkgConfigFilePath; // FIXME: not useful after all?; using config-$arch directory within chrootDir instead std::vector makechrootpkgFlags; std::vector makepkgFlags; std::string packageCacheDir; std::uint64_t packageDownloadSizeLimit = 500 * 1024 * 1024; std::string testFilesDir; BuildPresets presets; bool loadFilesDbs = false; // never changed after startup unsigned short threadCount = 4; boost::asio::io_context ioContext; void applyConfig(const std::multimap &multimap); void readPresets(const std::string &configFilePath, const std::string &presetsFile); Worker allocateBuildWorker(); BuildAction::IdType allocateBuildActionID(); std::shared_ptr getBuildAction(BuildAction::IdType id); std::vector> getBuildActions(const std::vector &ids); } building; struct LIBREPOMGR_EXPORT Authentication : public LibPkg::Lockable { std::unordered_map users; void applyConfig(const std::string &userName, const std::multimap &multimap); UserPermissions authenticate(std::string_view authorizationHeader) const; } auth; struct LIBREPOMGR_EXPORT Locks { using LockTable = std::unordered_map; [[nodiscard]] SharedLoggingLock acquireToRead(LogContext &log, std::string &&lockName); [[nodiscard]] UniqueLoggingLock acquireToWrite(LogContext &log, std::string &&lockName); [[nodiscard]] std::pair> acquireLockTable(); void clear(); static std::string forDatabase(std::string_view dbName, std::string_view dbArch); static std::string forDatabase(const LibPkg::Database &db); private: std::mutex m_mutex; LockTable m_locksByName; } locks; void loadConfigFiles(bool restoreStateAndDiscardDatabases); void printDatabases(); std::string_view cacheFilePath() const; RAPIDJSON_NAMESPACE::Document libraryDependenciesToJson() const; void restoreLibraryDependenciesFromJson(const std::string &json, ReflectiveRapidJSON::JsonDeserializationErrors *errors); std::size_t restoreState(); std::size_t saveState(); void run(); ServiceStatus computeStatus() const; }; inline std::shared_ptr ServiceSetup::BuildSetup::getBuildAction(BuildAction::IdType id) { return id < actions.size() ? actions[id] : nullptr; } inline SharedLoggingLock ServiceSetup::Locks::acquireToRead(LogContext &log, std::string &&lockName) { const auto lock = std::lock_guard(m_mutex); return m_locksByName[lockName].lockToRead(log, std::move(lockName)); } inline UniqueLoggingLock ServiceSetup::Locks::acquireToWrite(LogContext &log, std::string &&lockName) { const auto lock = std::lock_guard(m_mutex); return m_locksByName[lockName].lockToWrite(log, std::move(lockName)); } inline std::pair> ServiceSetup::Locks::acquireLockTable() { return std::make_pair(&m_locksByName, std::unique_lock(m_mutex)); } struct LIBREPOMGR_EXPORT ServiceStatus : public ReflectiveRapidJSON::JsonSerializable { ServiceStatus(const ServiceSetup &setup); const char *const version = nullptr; const LibPkg::Status config; const BuildActionMetaInfo &actions; const BuildPresets &presets; }; inline ServiceStatus ServiceSetup::computeStatus() const { return ServiceStatus(*this); } } // namespace LibRepoMgr #endif // LIBREPOMGR_SERVER_SETUP_H