diff options
| author | Stefan Boberg <[email protected]> | 2025-10-15 09:51:52 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-10-15 09:51:52 +0200 |
| commit | e747932819e2a64a1396cfbc3422a9b61c9470dc (patch) | |
| tree | 1db1d13cf7fe873d71128a7879d269174f8eaf16 /src | |
| parent | refactor builds cmd part3 (#573) (diff) | |
| download | zen-e747932819e2a64a1396cfbc3422a9b61c9470dc.tar.xz zen-e747932819e2a64a1396cfbc3422a9b61c9470dc.zip | |
restructured zenserver configuration (#575)
this breaks out the configuration logic to allow multiple applications to share common configuration and initialization logic whilst customizing chosen aspects of the process
Diffstat (limited to 'src')
| -rw-r--r-- | src/zenserver/config/config.cpp | 152 | ||||
| -rw-r--r-- | src/zenserver/config/config.h | 54 | ||||
| -rw-r--r-- | src/zenserver/diag/logging.cpp | 2 | ||||
| -rw-r--r-- | src/zenserver/diag/logging.h | 4 | ||||
| -rw-r--r-- | src/zenserver/main.cpp | 109 | ||||
| -rw-r--r-- | src/zenserver/storage/admin/admin.cpp | 2 | ||||
| -rw-r--r-- | src/zenserver/storage/admin/admin.h | 18 | ||||
| -rw-r--r-- | src/zenserver/storage/storageconfig.cpp | 86 | ||||
| -rw-r--r-- | src/zenserver/storage/storageconfig.h | 50 | ||||
| -rw-r--r-- | src/zenserver/storage/zenstorageserver.cpp | 17 | ||||
| -rw-r--r-- | src/zenserver/storage/zenstorageserver.h | 19 | ||||
| -rw-r--r-- | src/zenserver/zenserver.cpp | 4 | ||||
| -rw-r--r-- | src/zenserver/zenserver.h | 10 |
13 files changed, 317 insertions, 210 deletions
diff --git a/src/zenserver/config/config.cpp b/src/zenserver/config/config.cpp index d044c61d5..70590b4e6 100644 --- a/src/zenserver/config/config.cpp +++ b/src/zenserver/config/config.cpp @@ -88,19 +88,21 @@ ReadAllCentralManifests(const std::filesystem::path& SystemRoot) } void -ParseEnvVariables(ZenServerOptions& ServerOptions, const cxxopts::ParseResult& CmdLineResult) +ZenServerConfiguratorBase::ParseEnvVariables(const cxxopts::ParseResult& CmdLineResult) { using namespace std::literals; EnvironmentOptions Options; - Options.AddOption("UE_ZEN_SENTRY_ALLOWPERSONALINFO"sv, ServerOptions.SentryConfig.AllowPII, "sentry-allow-personal-info"sv); - Options.AddOption("UE_ZEN_SENTRY_DSN"sv, ServerOptions.SentryConfig.Dsn, "sentry-dsn"sv); - Options.AddOption("UE_ZEN_SENTRY_ENVIRONMENT"sv, ServerOptions.SentryConfig.Environment, "sentry-environment"sv); + ZenServerConfig& ServerOptions = m_ServerOptions; + bool EnvEnableSentry = !ServerOptions.SentryConfig.Disable; - bool EnvEnableSentry = !ServerOptions.SentryConfig.Disable; - Options.AddOption("UE_ZEN_SENTRY_ENABLED"sv, EnvEnableSentry, "no-sentry"sv); - - Options.AddOption("UE_ZEN_SENTRY_DEBUG"sv, ServerOptions.SentryConfig.Debug, "sentry-debug"sv); + // clang-format off + Options.AddOption("UE_ZEN_SENTRY_ALLOWPERSONALINFO"sv, ServerOptions.SentryConfig.AllowPII, "sentry-allow-personal-info"sv); + Options.AddOption("UE_ZEN_SENTRY_DSN"sv, ServerOptions.SentryConfig.Dsn, "sentry-dsn"sv); + Options.AddOption("UE_ZEN_SENTRY_ENVIRONMENT"sv, ServerOptions.SentryConfig.Environment, "sentry-environment"sv); + Options.AddOption("UE_ZEN_SENTRY_ENABLED"sv, EnvEnableSentry, "no-sentry"sv); + Options.AddOption("UE_ZEN_SENTRY_DEBUG"sv, ServerOptions.SentryConfig.Debug, "sentry-debug"sv); + // clang-format on Options.Parse(CmdLineResult); @@ -111,10 +113,12 @@ ParseEnvVariables(ZenServerOptions& ServerOptions, const cxxopts::ParseResult& C } void -AddServerConfigOptions(LuaConfig::Options& LuaOptions, ZenServerOptions& ServerOptions) +ZenServerConfiguratorBase::AddCommonConfigOptions(LuaConfig::Options& LuaOptions) { using namespace std::literals; + ZenServerConfig& ServerOptions = m_ServerOptions; + // server LuaOptions.AddOption("server.dedicated"sv, ServerOptions.IsDedicated, "dedicated"sv); @@ -177,13 +181,14 @@ struct ZenServerCmdLineOptions std::string ContentDir; std::string DataDir; std::string AbsLogFile; + std::string BaseSnapshotDir; - void AddCliOptions(cxxopts::Options& options, ZenServerOptions& ServerOptions); - void ApplyOptions(ZenServerOptions& ServerOptions); + void AddCliOptions(cxxopts::Options& options, ZenServerConfig& ServerOptions); + void ApplyOptions(cxxopts::Options& options, ZenServerConfig& ServerOptions); }; void -ZenServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenServerOptions& ServerOptions) +ZenServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenServerConfig& ServerOptions) { const char* DefaultHttp = "asio"; @@ -209,6 +214,9 @@ ZenServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenServerOptio options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::string>(ContentDir)); options.add_options()("config", "Path to Lua config file", cxxopts::value<std::string>(ConfigFile)); options.add_options()("write-config", "Path to output Lua config file", cxxopts::value<std::string>(OutputConfigFile)); + options.add_options()("snapshot-dir", + "Specify a snapshot of server state to mirror into the persistence root at startup", + cxxopts::value<std::string>(BaseSnapshotDir)); options.add_options()("no-sentry", "Disable Sentry crash handler", @@ -227,6 +235,7 @@ ZenServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenServerOptio options.add_options()("malloc", "Configure memory allocator subsystem", cxxopts::value(ServerOptions.MemoryOptions)->default_value("mimalloc")); + options.add_options()("corelimit", "Limit concurrency", cxxopts::value(ServerOptions.CoreLimit)); options.add_options()("powercycle", "Exit immediately after initialization is complete", cxxopts::value<bool>(ServerOptions.IsPowerCycle)); @@ -368,35 +377,55 @@ ZenServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenServerOptio } void -ZenServerCmdLineOptions::ApplyOptions(ZenServerOptions& ServerOptions) +ZenServerCmdLineOptions::ApplyOptions(cxxopts::Options& options, ZenServerConfig& ServerOptions) +{ + if (!BaseSnapshotDir.empty()) + { + if (ServerOptions.DataDir.empty()) + throw OptionParseException("'--snapshot-dir' requires '--data-dir'", options.help()); + + if (!IsDir(ServerOptions.BaseSnapshotDir)) + throw std::runtime_error(fmt::format("'--snapshot-dir' ('{}') must be a directory", ServerOptions.BaseSnapshotDir)); + } + + ServerOptions.SystemRootDir = MakeSafeAbsolutePath(SystemRootDir); + ServerOptions.DataDir = MakeSafeAbsolutePath(DataDir); + ServerOptions.ContentDir = MakeSafeAbsolutePath(ContentDir); + ServerOptions.AbsLogFile = MakeSafeAbsolutePath(AbsLogFile); + ServerOptions.ConfigFile = MakeSafeAbsolutePath(ConfigFile); + ServerOptions.BaseSnapshotDir = MakeSafeAbsolutePath(BaseSnapshotDir); +} + +////////////////////////////////////////////////////////////////////////// + +ZenServerConfiguratorBase::ZenServerConfiguratorBase(ZenServerConfig& BaseServerOptions) : m_ServerOptions(BaseServerOptions) +{ +} + +ZenServerConfiguratorBase::~ZenServerConfiguratorBase() { - ServerOptions.SystemRootDir = MakeSafeAbsolutePath(SystemRootDir); - ServerOptions.DataDir = MakeSafeAbsolutePath(DataDir); - ServerOptions.ContentDir = MakeSafeAbsolutePath(ContentDir); - ServerOptions.AbsLogFile = MakeSafeAbsolutePath(AbsLogFile); - ServerOptions.ConfigFile = MakeSafeAbsolutePath(ConfigFile); } void -ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) +ZenServerConfiguratorBase::Configure(int argc, char* argv[]) { for (int i = 0; i < argc; ++i) { if (i) { - ServerOptions.CommandLine.push_back(' '); + m_ServerOptions.CommandLine.push_back(' '); } - ServerOptions.CommandLine += argv[i]; + m_ServerOptions.CommandLine += argv[i]; } cxxopts::Options options("zenserver", "Zen Storage Server"); ZenServerCmdLineOptions BaseOptions; - BaseOptions.AddCliOptions(options, ServerOptions); + BaseOptions.AddCliOptions(options, m_ServerOptions); - ZenStorageServerCmdLineOptions StorageOptions; - StorageOptions.AddCliOptions(options, ServerOptions); + // Add subclass' command line options + AddCliOptions(options); try { @@ -426,18 +455,18 @@ ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) exit(0); } - if (!ServerOptions.HasTraceCommandlineOptions) + if (!m_ServerOptions.HasTraceCommandlineOptions) { // Apply any Lua settings if we don't have them set from the command line - TraceConfigure(ServerOptions.TraceOptions); + TraceConfigure(m_ServerOptions.TraceOptions); } - if (ServerOptions.QuietConsole) + if (m_ServerOptions.QuietConsole) { bool HasExplicitConsoleLevel = false; for (int i = 0; i < logging::level::LogLevelCount; ++i) { - if (ServerOptions.Loggers[i].find("console") != std::string::npos) + if (m_ServerOptions.Loggers[i].find("console") != std::string::npos) { HasExplicitConsoleLevel = true; break; @@ -446,7 +475,7 @@ ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) if (!HasExplicitConsoleLevel) { - std::string& WarnLoggers = ServerOptions.Loggers[logging::level::Warn]; + std::string& WarnLoggers = m_ServerOptions.Loggers[logging::level::Warn]; if (!WarnLoggers.empty()) { WarnLoggers += ","; @@ -457,32 +486,29 @@ ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) for (int i = 0; i < logging::level::LogLevelCount; ++i) { - logging::ConfigureLogLevels(logging::level::LogLevel(i), ServerOptions.Loggers[i]); + logging::ConfigureLogLevels(logging::level::LogLevel(i), m_ServerOptions.Loggers[i]); } logging::RefreshLogLevels(); - BaseOptions.ApplyOptions(ServerOptions); - StorageOptions.ApplyOptions(options, ServerOptions); + BaseOptions.ApplyOptions(options, m_ServerOptions); + ApplyOptions(options); + + // Handle any environment variables - ParseEnvVariables(ServerOptions, Result); + ParseEnvVariables(Result); ZEN_TRACE_CPU("ConfigParse"); - if (!ServerOptions.ConfigFile.empty()) + if (!m_ServerOptions.ConfigFile.empty()) { - ParseConfigFile(ServerOptions.ConfigFile, ServerOptions, Result, BaseOptions.OutputConfigFile); + ParseConfigFile(m_ServerOptions.ConfigFile, Result, BaseOptions.OutputConfigFile); } else { - ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions, Result, BaseOptions.OutputConfigFile); + ParseConfigFile(m_ServerOptions.DataDir / "zen_cfg.lua", Result, BaseOptions.OutputConfigFile); } - if (!ServerOptions.PluginsConfigFile.empty()) - { - ParsePluginsConfigFile(ServerOptions.PluginsConfigFile, ServerOptions, ServerOptions.BasePort); - } - - ValidateOptions(ServerOptions); + ValidateOptions(); // subclass validation } catch (const OptionParseException& e) { @@ -491,22 +517,50 @@ ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) throw; } - if (ServerOptions.SystemRootDir.empty()) + if (m_ServerOptions.SystemRootDir.empty()) { - ServerOptions.SystemRootDir = PickDefaultSystemRootDirectory(); + m_ServerOptions.SystemRootDir = PickDefaultSystemRootDirectory(); } - if (ServerOptions.DataDir.empty()) + if (m_ServerOptions.DataDir.empty()) { - ServerOptions.DataDir = PickDefaultStateDirectory(ServerOptions.SystemRootDir); + m_ServerOptions.DataDir = PickDefaultStateDirectory(m_ServerOptions.SystemRootDir); } - if (ServerOptions.AbsLogFile.empty()) + if (m_ServerOptions.AbsLogFile.empty()) { - ServerOptions.AbsLogFile = ServerOptions.DataDir / "logs" / "zenserver.log"; + m_ServerOptions.AbsLogFile = m_ServerOptions.DataDir / "logs" / "zenserver.log"; } - ServerOptions.HttpServerConfig.IsDedicatedServer = ServerOptions.IsDedicated; + m_ServerOptions.HttpServerConfig.IsDedicatedServer = m_ServerOptions.IsDedicated; +} + +void +ZenServerConfiguratorBase::ParseConfigFile(const std::filesystem::path& Path, + const cxxopts::ParseResult& CmdLineResult, + std::string_view OutputConfigFile) +{ + ZEN_TRACE_CPU("ParseConfigFile"); + + LuaConfig::Options LuaOptions; + + AddCommonConfigOptions(LuaOptions); + AddConfigOptions(LuaOptions); // subclass options + + LuaOptions.Parse(Path, CmdLineResult); + + OnConfigFileParsed(LuaOptions); // subclass hook + + if (!OutputConfigFile.empty()) + { + ExtendableStringBuilder<512> ConfigStringBuilder; + LuaOptions.Print(ConfigStringBuilder, CmdLineResult); + + BasicFile Output; + std::filesystem::path WritePath(MakeSafeAbsolutePath(OutputConfigFile)); + Output.Open(WritePath, BasicFile::Mode::kTruncate); + Output.Write(ConfigStringBuilder.Data(), ConfigStringBuilder.Size(), 0); + } } } // namespace zen diff --git a/src/zenserver/config/config.h b/src/zenserver/config/config.h index 8471ee89b..467f26ee7 100644 --- a/src/zenserver/config/config.h +++ b/src/zenserver/config/config.h @@ -19,7 +19,7 @@ class ParseResult; } // namespace cxxopts namespace zen { -struct ZenStorageServerOptions; +// Common server configuration struct ZenStatsConfig { @@ -37,10 +37,11 @@ struct ZenSentryConfig bool Debug = false; // Enable debug mode for Sentry }; -struct ZenServerOptions +struct ZenServerConfig { HttpServerConfig HttpServerConfig; ZenSentryConfig SentryConfig; + ZenStatsConfig StatsConfig; int BasePort = 8558; // Service listen port (used for both UDP and TCP) int OwnerPid = 0; // Parent process id (zero for standalone) bool IsDebug = false; @@ -54,13 +55,14 @@ struct ZenServerOptions bool IsDedicated = false; // Indicates a dedicated/shared instance, with larger resource requirements bool ShouldCrash = false; // Option for testing crash handling bool IsFirstRun = false; - std::filesystem::path ConfigFile; // Path to Lua config file - std::filesystem::path SystemRootDir; // System root directory (used for machine level config) - std::filesystem::path ContentDir; // Root directory for serving frontend content (experimental) - std::filesystem::path DataDir; // Root directory for state (used for testing) - std::filesystem::path AbsLogFile; // Absolute path to main log file - std::string ChildId; // Id assigned by parent process (used for lifetime management) - std::string LogId; // Id for tagging log output + std::filesystem::path ConfigFile; // Path to Lua config file + std::filesystem::path SystemRootDir; // System root directory (used for machine level config) + std::filesystem::path ContentDir; // Root directory for serving frontend content (experimental) + std::filesystem::path DataDir; // Root directory for state (used for testing) + std::filesystem::path AbsLogFile; // Absolute path to main log file + std::filesystem::path BaseSnapshotDir; // Path to server state snapshot (will be copied into data dir on start) + std::string ChildId; // Id assigned by parent process (used for lifetime management) + std::string LogId; // Id for tagging log output std::string Loggers[zen::logging::level::LogLevelCount]; #if ZEN_WITH_TRACE bool HasTraceCommandlineOptions = false; @@ -71,17 +73,41 @@ struct ZenServerOptions std::string EncryptionKey; // 256 bit AES encryption key std::string EncryptionIV; // 128 bit AES initialization vector - ZenStatsConfig StatsConfig; - bool InstallService = false; // Flag used to initiate service install (temporary) bool UninstallService = false; // Flag used to initiate service uninstall (temporary) }; -void ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions); +/** Configuration helper - pulls together command line, environment variables + and config file parsing logic. Designed to allow a set of common configuration + options to be shared among a set of applications which may or may not all be + linked into a single executable. + + The virtual functions are used by derived classes to extend and customize the + configuration process. + */ +struct ZenServerConfiguratorBase +{ + ZenServerConfiguratorBase(ZenServerConfig& BaseServerOptions); + virtual ~ZenServerConfiguratorBase(); + + void Configure(int argc, char* argv[]); + +protected: + virtual void AddCliOptions(cxxopts::Options& options) = 0; + virtual void ApplyOptions(cxxopts::Options& options) = 0; + virtual void ValidateOptions() = 0; + virtual void AddConfigOptions(LuaConfig::Options& Options) = 0; + virtual void OnConfigFileParsed(LuaConfig::Options& LuaOptions) = 0; + +private: + ZenServerConfig& m_ServerOptions; + + void ParseEnvVariables(const cxxopts::ParseResult& CmdLineResult); + void ParseConfigFile(const std::filesystem::path& Path, const cxxopts::ParseResult& CmdLineResult, std::string_view OutputConfigFile); + void AddCommonConfigOptions(LuaConfig::Options& LuaOptions); +}; void EmitCentralManifest(const std::filesystem::path& SystemRoot, Oid Identifier, CbObject Manifest, std::filesystem::path ManifestPath); std::vector<CbObject> ReadAllCentralManifests(const std::filesystem::path& SystemRoot); -void AddServerConfigOptions(LuaConfig::Options& LuaOptions, ZenServerOptions& ServerOptions); - } // namespace zen diff --git a/src/zenserver/diag/logging.cpp b/src/zenserver/diag/logging.cpp index ee36b2ca9..50cf62274 100644 --- a/src/zenserver/diag/logging.cpp +++ b/src/zenserver/diag/logging.cpp @@ -19,7 +19,7 @@ ZEN_THIRD_PARTY_INCLUDES_END namespace zen { void -InitializeServerLogging(const ZenServerOptions& InOptions) +InitializeServerLogging(const ZenServerConfig& InOptions) { ZEN_MEMSCOPE(ELLMTag::Logging); diff --git a/src/zenserver/diag/logging.h b/src/zenserver/diag/logging.h index 46aab100f..4b27a50cf 100644 --- a/src/zenserver/diag/logging.h +++ b/src/zenserver/diag/logging.h @@ -6,9 +6,9 @@ namespace zen { -struct ZenServerOptions; +struct ZenServerConfig; -void InitializeServerLogging(const ZenServerOptions& LogOptions); +void InitializeServerLogging(const ZenServerConfig& LogOptions); void ShutdownServerLogging(); } // namespace zen diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index 3119b37c6..43ddc14c9 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -63,7 +63,7 @@ template<class T> class ZenWindowsService : public WindowsService { public: - ZenWindowsService(ZenStorageServerOptions& ServerOptions) : m_EntryPoint(ServerOptions) {} + ZenWindowsService(typename T::Config& ServerOptions) : m_EntryPoint(ServerOptions) {} ZenWindowsService(const ZenWindowsService&) = delete; ZenWindowsService& operator=(const ZenWindowsService&) = delete; @@ -80,60 +80,31 @@ private: ////////////////////////////////////////////////////////////////////////// -#if ZEN_WITH_TESTS -int -test_main(int argc, char** argv) -{ - zen::logging::InitializeLogging(); - zen::logging::SetLogLevel(zen::logging::level::Debug); - - zen::MaximizeOpenFileCount(); - - return ZEN_RUN_TESTS(argc, argv); -} -#endif +namespace zen { +template<class Main> int -main(int argc, char* argv[]) +AppMain(int argc, char* argv[]) { - using namespace zen; - - if (argc >= 2) - { - if (argv[1] == "test"sv) - { -#if ZEN_WITH_TESTS - return test_main(argc, argv); -#else - fprintf(stderr, "test option not available in release mode!\n"); - exit(5); -#endif - } - } - - signal(SIGINT, utils::SignalCallbackHandler); - signal(SIGTERM, utils::SignalCallbackHandler); - -#if ZEN_PLATFORM_LINUX - IgnoreChildSignals(); -#endif + using namespace std::literals; try { - ZenStorageServerOptions ServerOptions; + typename Main::Config ServerOptions; - { #if ZEN_WITH_TRACE - TraceInit("zenserver"); - ServerOptions.HasTraceCommandlineOptions = GetTraceOptionsFromCommandline(ServerOptions.TraceOptions); - if (ServerOptions.HasTraceCommandlineOptions) - { - TraceConfigure(ServerOptions.TraceOptions); - } -#endif // ZEN_WITH_TRACE + TraceInit("zenserver"); + ServerOptions.HasTraceCommandlineOptions = GetTraceOptionsFromCommandline(/* out */ ServerOptions.TraceOptions); + if (ServerOptions.HasTraceCommandlineOptions) + { + TraceConfigure(ServerOptions.TraceOptions); } +#endif // ZEN_WITH_TRACE - ParseCliOptions(argc, argv, ServerOptions); + { + typename Main::Configurator Configurator(ServerOptions); + Configurator.Configure(argc, argv); + } if (ServerOptions.Detach) { @@ -194,7 +165,7 @@ main(int argc, char* argv[]) std::exit(0); } - ZenWindowsService<ZenStorageServerMain> App(ServerOptions); + ZenWindowsService<Main> App(ServerOptions); return App.ServiceMain(); #else if (ServerOptions.InstallService || ServerOptions.UninstallService) @@ -202,7 +173,7 @@ main(int argc, char* argv[]) throw std::runtime_error("Service mode is not supported on this platform"); } - ZenStorageServerMain App(ServerOptions); + Main App(ServerOptions); return App.Run(); #endif } @@ -224,3 +195,47 @@ main(int argc, char* argv[]) return 1; } } +} // namespace zen + +////////////////////////////////////////////////////////////////////////// + +#if ZEN_WITH_TESTS +int +test_main(int argc, char** argv) +{ + zen::logging::InitializeLogging(); + zen::logging::SetLogLevel(zen::logging::level::Debug); + + zen::MaximizeOpenFileCount(); + + return ZEN_RUN_TESTS(argc, argv); +} +#endif + +int +main(int argc, char* argv[]) +{ + using namespace zen; + + if (argc >= 2) + { + if (argv[1] == "test"sv) + { +#if ZEN_WITH_TESTS + return test_main(argc, argv); +#else + fprintf(stderr, "test option not available in release mode!\n"); + exit(5); +#endif + } + } + + signal(SIGINT, utils::SignalCallbackHandler); + signal(SIGTERM, utils::SignalCallbackHandler); + +#if ZEN_PLATFORM_LINUX + IgnoreChildSignals(); +#endif + + return AppMain<ZenStorageServerMain>(argc, argv); +} diff --git a/src/zenserver/storage/admin/admin.cpp b/src/zenserver/storage/admin/admin.cpp index 4803063d7..68b91825d 100644 --- a/src/zenserver/storage/admin/admin.cpp +++ b/src/zenserver/storage/admin/admin.cpp @@ -102,7 +102,7 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler, ZenCacheStore* CacheStore, std::function<void()>&& FlushFunction, const LogPaths& LogPaths, - const ZenServerOptions& ServerOptions) + const ZenServerConfig& ServerOptions) : m_GcScheduler(Scheduler) , m_BackgroundJobQueue(BackgroundJobQueue) , m_CacheStore(CacheStore) diff --git a/src/zenserver/storage/admin/admin.h b/src/zenserver/storage/admin/admin.h index 9a49f5120..ee3da4579 100644 --- a/src/zenserver/storage/admin/admin.h +++ b/src/zenserver/storage/admin/admin.h @@ -11,7 +11,7 @@ namespace zen { class GcScheduler; class JobQueue; class ZenCacheStore; -struct ZenServerOptions; +struct ZenServerConfig; class HttpAdminService : public zen::HttpService { @@ -27,20 +27,20 @@ public: ZenCacheStore* CacheStore, std::function<void()>&& FlushFunction, const LogPaths& LogPaths, - const ZenServerOptions& ServerOptions); + const ZenServerConfig& ServerOptions); ~HttpAdminService(); virtual const char* BaseUri() const override; virtual void HandleRequest(zen::HttpServerRequest& Request) override; private: - HttpRequestRouter m_Router; - GcScheduler& m_GcScheduler; - JobQueue& m_BackgroundJobQueue; - ZenCacheStore* m_CacheStore; - std::function<void()> m_FlushFunction; - LogPaths m_LogPaths; - const ZenServerOptions& m_ServerOptions; + HttpRequestRouter m_Router; + GcScheduler& m_GcScheduler; + JobQueue& m_BackgroundJobQueue; + ZenCacheStore* m_CacheStore; + std::function<void()> m_FlushFunction; + LogPaths m_LogPaths; + const ZenServerConfig& m_ServerOptions; }; } // namespace zen diff --git a/src/zenserver/storage/storageconfig.cpp b/src/zenserver/storage/storageconfig.cpp index 86bb09c21..61844140e 100644 --- a/src/zenserver/storage/storageconfig.cpp +++ b/src/zenserver/storage/storageconfig.cpp @@ -18,8 +18,10 @@ ZEN_THIRD_PARTY_INCLUDES_END namespace zen { void -ValidateOptions(ZenStorageServerOptions& ServerOptions) +ZenStorageServerConfigurator::ValidateOptions() { + auto& ServerOptions = m_ServerOptions; + if (ServerOptions.EncryptionKey.empty() == false) { const auto Key = AesKey256Bit::FromString(ServerOptions.EncryptionKey); @@ -363,18 +365,11 @@ MakeOption(std::vector<std::pair<std::string, ZenStructuredCacheBucketConfig>>& }; void -ParseConfigFile(const std::filesystem::path& Path, - ZenStorageServerOptions& ServerOptions, - const cxxopts::ParseResult& CmdLineResult, - std::string_view OutputConfigFile) +ZenStorageServerConfigurator::AddConfigOptions(LuaConfig::Options& LuaOptions) { - ZEN_TRACE_CPU("ParseConfigFile"); - using namespace std::literals; - LuaConfig::Options LuaOptions; - - AddServerConfigOptions(LuaOptions, ServerOptions); + auto& ServerOptions = m_ServerOptions; ////// server LuaOptions.AddOption("server.pluginsconfigfile"sv, ServerOptions.PluginsConfigFile, "plugins-config"sv); @@ -507,36 +502,50 @@ ParseConfigFile(const std::filesystem::path& Path, LuaOptions.AddOption("workspaces.allowconfigchanges"sv, ServerOptions.WorksSpacesConfig.AllowConfigurationChanges, "workspaces-allow-changes"sv); +} - LuaOptions.Parse(Path, CmdLineResult); +void +ZenStorageServerConfigurator::OnConfigFileParsed(LuaConfig::Options& LuaOptions) +{ + using namespace std::literals; // These have special command line processing so we make sure we export them if they were configured on command line - if (!ServerOptions.AuthConfig.OpenIdProviders.empty()) + + if (!m_ServerOptions.AuthConfig.OpenIdProviders.empty()) { LuaOptions.Touch("security.openidproviders"sv); } - if (!ServerOptions.ObjectStoreConfig.Buckets.empty()) + if (!m_ServerOptions.ObjectStoreConfig.Buckets.empty()) { LuaOptions.Touch("server.objectstore.buckets"sv); } - if (!ServerOptions.StructuredCacheConfig.PerBucketConfigs.empty()) + if (!m_ServerOptions.StructuredCacheConfig.PerBucketConfigs.empty()) { LuaOptions.Touch("cache.buckets"sv); } - if (!OutputConfigFile.empty()) + // Also parse plugins config file + + if (!m_ServerOptions.PluginsConfigFile.empty()) { - std::filesystem::path WritePath(MakeSafeAbsolutePath(OutputConfigFile)); - ExtendableStringBuilder<512> ConfigStringBuilder; - LuaOptions.Print(ConfigStringBuilder, CmdLineResult); - BasicFile Output; - Output.Open(WritePath, BasicFile::Mode::kTruncate); - Output.Write(ConfigStringBuilder.Data(), ConfigStringBuilder.Size(), 0); + ParsePluginsConfigFile(m_ServerOptions.PluginsConfigFile); } } void -ParsePluginsConfigFile(const std::filesystem::path& Path, ZenStorageServerOptions& ServerOptions, int BasePort) +ZenStorageServerConfigurator::AddCliOptions(cxxopts::Options& options) +{ + m_StorageOptions.AddCliOptions(options, m_ServerOptions); +} + +void +ZenStorageServerConfigurator::ApplyOptions(cxxopts::Options& options) +{ + m_StorageOptions.ApplyOptions(options, m_ServerOptions); +} + +void +ZenStorageServerConfigurator::ParsePluginsConfigFile(const std::filesystem::path& Path) { using namespace std::literals; @@ -590,19 +599,16 @@ ParsePluginsConfigFile(const std::filesystem::path& Path, ZenStorageServerOption // add a default base port in case if json config didn't provide one if (bNeedsPort) { - Config.PluginOptions.push_back({"port", std::to_string(BasePort)}); + Config.PluginOptions.push_back({"port", std::to_string(m_ServerOptions.BasePort)}); } - ServerOptions.HttpServerConfig.PluginConfigs.push_back(Config); + m_ServerOptions.HttpServerConfig.PluginConfigs.push_back(Config); } } void -ZenStorageServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { - options.add_options()("snapshot-dir", - "Specify a snapshot of server state to mirror into the persistence root at startup", - cxxopts::value<std::string>(BaseSnapshotDir)); options.add_options()("plugins-config", "Path to plugins config file", cxxopts::value<std::string>(PluginsConfigFile)); options.add_options()("scrub", "Validate state at startup", @@ -618,7 +624,7 @@ ZenStorageServerCmdLineOptions::AddCliOptions(cxxopts::Options& options, ZenStor } void -ZenStorageServerCmdLineOptions::AddSecurityOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddSecurityOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("security", "", @@ -646,7 +652,7 @@ ZenStorageServerCmdLineOptions::AddSecurityOptions(cxxopts::Options& options, Ze } void -ZenStorageServerCmdLineOptions::AddCacheOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddCacheOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("cache", "", @@ -831,7 +837,7 @@ ZenStorageServerCmdLineOptions::AddCacheOptions(cxxopts::Options& options, ZenSt } void -ZenStorageServerCmdLineOptions::AddGcOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddGcOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("gc", "", @@ -970,7 +976,7 @@ ZenStorageServerCmdLineOptions::AddGcOptions(cxxopts::Options& options, ZenStora } void -ZenStorageServerCmdLineOptions::AddObjectStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddObjectStoreOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("objectstore", "", @@ -988,7 +994,7 @@ ZenStorageServerCmdLineOptions::AddObjectStoreOptions(cxxopts::Options& options, } void -ZenStorageServerCmdLineOptions::AddBuildStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddBuildStoreOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("buildstore", "", @@ -1005,7 +1011,7 @@ ZenStorageServerCmdLineOptions::AddBuildStoreOptions(cxxopts::Options& options, } void -ZenStorageServerCmdLineOptions::AddWorkspacesOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::AddWorkspacesOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { options.add_option("workspaces", "", @@ -1023,21 +1029,11 @@ ZenStorageServerCmdLineOptions::AddWorkspacesOptions(cxxopts::Options& options, } void -ZenStorageServerCmdLineOptions::ApplyOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions) +ZenStorageServerCmdLineOptions::ApplyOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions) { - ServerOptions.BaseSnapshotDir = MakeSafeAbsolutePath(BaseSnapshotDir); ServerOptions.PluginsConfigFile = MakeSafeAbsolutePath(PluginsConfigFile); ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions); - if (!BaseSnapshotDir.empty()) - { - if (ServerOptions.DataDir.empty()) - throw OptionParseException("'--snapshot-dir' requires '--data-dir'", options.help()); - - if (!IsDir(ServerOptions.BaseSnapshotDir)) - throw std::runtime_error(fmt::format("'--snapshot-dir' ('{}') must be a directory", ServerOptions.BaseSnapshotDir)); - } - if (OpenIdProviderUrl.empty() == false) { if (OpenIdClientId.empty()) diff --git a/src/zenserver/storage/storageconfig.h b/src/zenserver/storage/storageconfig.h index ca0cf4135..acdaa099b 100644 --- a/src/zenserver/storage/storageconfig.h +++ b/src/zenserver/storage/storageconfig.h @@ -144,7 +144,7 @@ struct ZenWorkspacesConfig bool AllowConfigurationChanges = false; }; -struct ZenStorageServerOptions : public ZenServerOptions +struct ZenStorageServerConfig : public ZenServerConfig { ZenUpstreamCacheConfig UpstreamCacheConfig; ZenGcConfig GcConfig; @@ -155,19 +155,10 @@ struct ZenStorageServerOptions : public ZenServerOptions ZenBuildStoreConfig BuildStoreConfig; ZenWorkspacesConfig WorksSpacesConfig; std::filesystem::path PluginsConfigFile; // Path to plugins config file - std::filesystem::path BaseSnapshotDir; // Path to server state snapshot (will be copied into data dir on start) bool ObjectStoreEnabled = false; std::string ScrubOptions; }; -void ParseConfigFile(const std::filesystem::path& Path, - ZenStorageServerOptions& ServerOptions, - const cxxopts::ParseResult& CmdLineResult, - std::string_view OutputConfigFile); - -void ParsePluginsConfigFile(const std::filesystem::path& Path, ZenStorageServerOptions& ServerOptions, int BasePort); -void ValidateOptions(ZenStorageServerOptions& ServerOptions); - struct ZenStorageServerCmdLineOptions { // Note to those adding future options; std::filesystem::path-type options @@ -176,28 +167,49 @@ struct ZenStorageServerCmdLineOptions // expects paths in streams to be quoted but argv paths are unquoted. By // going into a std::string first, paths with whitespace parse correctly. std::string PluginsConfigFile; - std::string BaseSnapshotDir; - void AddCliOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); - void ApplyOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); + void AddCliOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); + void ApplyOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); std::string OpenIdProviderName; std::string OpenIdProviderUrl; std::string OpenIdClientId; - void AddSecurityOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); + void AddSecurityOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); std::string UpstreamCachePolicyOptions; - void AddCacheOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); + void AddCacheOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); - void AddGcOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); + void AddGcOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); std::vector<std::string> BucketConfigs; - void AddObjectStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); - void AddBuildStoreOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); - void AddWorkspacesOptions(cxxopts::Options& options, ZenStorageServerOptions& ServerOptions); + void AddObjectStoreOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); + void AddBuildStoreOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); + void AddWorkspacesOptions(cxxopts::Options& options, ZenStorageServerConfig& ServerOptions); +}; + +struct ZenStorageServerConfigurator : public ZenServerConfiguratorBase +{ + ZenStorageServerConfigurator(ZenStorageServerConfig& ServerOptions) + : ZenServerConfiguratorBase(ServerOptions) + , m_ServerOptions(ServerOptions) + { + } + ~ZenStorageServerConfigurator() = default; + +private: + virtual void AddCliOptions(cxxopts::Options& options) override; + virtual void AddConfigOptions(LuaConfig::Options& Options) override; + virtual void ApplyOptions(cxxopts::Options& options) override; + virtual void OnConfigFileParsed(LuaConfig::Options& LuaOptions) override; + virtual void ValidateOptions() override; + + void ParsePluginsConfigFile(const std::filesystem::path& Path); + + ZenStorageServerConfig& m_ServerOptions; + ZenStorageServerCmdLineOptions m_StorageOptions; }; } // namespace zen diff --git a/src/zenserver/storage/zenstorageserver.cpp b/src/zenserver/storage/zenstorageserver.cpp index 73896512d..65de3eca2 100644 --- a/src/zenserver/storage/zenstorageserver.cpp +++ b/src/zenserver/storage/zenstorageserver.cpp @@ -100,10 +100,11 @@ ZenStorageServer::ZenStorageServer() ZenStorageServer::~ZenStorageServer() { + Cleanup(); } int -ZenStorageServer::Initialize(const ZenStorageServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) +ZenStorageServer::Initialize(const ZenStorageServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) { ZEN_TRACE_CPU("ZenStorageServer::Initialize"); ZEN_MEMSCOPE(GetZenserverTag()); @@ -182,7 +183,7 @@ ZenStorageServer::RegisterServices() } void -ZenStorageServer::InitializeServices(const ZenStorageServerOptions& ServerOptions) +ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions) { InitializeAuthentication(ServerOptions); @@ -300,7 +301,7 @@ ZenStorageServer::InitializeServices(const ZenStorageServerOptions& ServerOption } void -ZenStorageServer::InitializeAuthentication(const ZenStorageServerOptions& ServerOptions) +ZenStorageServer::InitializeAuthentication(const ZenStorageServerConfig& ServerOptions) { // Setup authentication manager { @@ -343,7 +344,7 @@ ZenStorageServer::InitializeAuthentication(const ZenStorageServerOptions& Server } void -ZenStorageServer::InitializeState(const ZenStorageServerOptions& ServerOptions) +ZenStorageServer::InitializeState(const ZenStorageServerConfig& ServerOptions) { ZEN_TRACE_CPU("ZenStorageServer::InitializeState"); @@ -507,7 +508,7 @@ ZenStorageServer::InitializeState(const ZenStorageServerOptions& ServerOptions) } void -ZenStorageServer::InitializeStructuredCache(const ZenStorageServerOptions& ServerOptions) +ZenStorageServer::InitializeStructuredCache(const ZenStorageServerConfig& ServerOptions) { ZEN_TRACE_CPU("ZenStorageServer::InitializeStructuredCache"); @@ -876,7 +877,7 @@ ZenStorageServer::Flush() ////////////////////////////////////////////////////////////////////////// -ZenStorageServerMain::ZenStorageServerMain(ZenStorageServerOptions& ServerOptions) +ZenStorageServerMain::ZenStorageServerMain(ZenStorageServerConfig& ServerOptions) : ZenServerMain(ServerOptions) , m_ServerOptions(ServerOptions) { @@ -891,8 +892,6 @@ ZenStorageServerMain::DoRun(ZenServerState::ZenServerEntry* Entry) Server.SetTestMode(m_ServerOptions.IsTest); Server.SetDedicatedMode(m_ServerOptions.IsDedicated); - auto ServerCleanup = MakeGuard([&Server] { Server.Cleanup(); }); - int EffectiveBasePort = Server.Initialize(m_ServerOptions, Entry); if (EffectiveBasePort == -1) { @@ -917,7 +916,7 @@ ZenStorageServerMain::DoRun(ZenServerState::ZenServerEntry* Entry) // Monitor shutdown signals ShutdownThread.reset(new std::thread{[&] { - SetCurrentThreadName("shutdown_monitor"); + SetCurrentThreadName("shutdown_mon"); ZEN_INFO("shutdown monitor thread waiting for shutdown signal '{}' for process {}", ShutdownEventName, zen::GetCurrentProcessId()); diff --git a/src/zenserver/storage/zenstorageserver.h b/src/zenserver/storage/zenstorageserver.h index e4c31399d..f79c55bc8 100644 --- a/src/zenserver/storage/zenstorageserver.h +++ b/src/zenserver/storage/zenstorageserver.h @@ -39,13 +39,13 @@ public: void SetDataRoot(std::filesystem::path Root) { m_DataRoot = Root; } void SetContentRoot(std::filesystem::path Root) { m_ContentRoot = Root; } - int Initialize(const ZenStorageServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry); + int Initialize(const ZenStorageServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry); void Run(); void Cleanup(); private: - void InitializeState(const ZenStorageServerOptions& ServerOptions); - void InitializeStructuredCache(const ZenStorageServerOptions& ServerOptions); + void InitializeState(const ZenStorageServerConfig& ServerOptions); + void InitializeStructuredCache(const ZenStorageServerConfig& ServerOptions); void Flush(); bool m_IsDedicatedMode = false; @@ -62,9 +62,9 @@ private: std::unique_ptr<AuthMgr> m_AuthMgr; std::unique_ptr<HttpAuthService> m_AuthService; - void InitializeAuthentication(const ZenStorageServerOptions& ServerOptions); + void InitializeAuthentication(const ZenStorageServerConfig& ServerOptions); - void InitializeServices(const ZenStorageServerOptions& ServerOptions); + void InitializeServices(const ZenStorageServerConfig& ServerOptions); void RegisterServices(); HttpStatsService m_StatsService; @@ -97,17 +97,22 @@ private: std::unique_ptr<HttpAdminService> m_AdminService; }; +struct ZenStorageServerConfigurator; + class ZenStorageServerMain : public ZenServerMain { public: - ZenStorageServerMain(ZenStorageServerOptions& ServerOptions); + ZenStorageServerMain(ZenStorageServerConfig& ServerOptions); virtual void DoRun(ZenServerState::ZenServerEntry* Entry) override; ZenStorageServerMain(const ZenStorageServerMain&) = delete; ZenStorageServerMain& operator=(const ZenStorageServerMain&) = delete; + typedef ZenStorageServerConfig Config; + typedef ZenStorageServerConfigurator Configurator; + private: - ZenStorageServerOptions& m_ServerOptions; + ZenStorageServerConfig& m_ServerOptions; }; } // namespace zen diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index 11afb682c..2dd51d243 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -74,7 +74,7 @@ ZenServerBase::~ZenServerBase() } int -ZenServerBase::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) +ZenServerBase::Initialize(const ZenServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) { ZEN_TRACE_CPU("ZenServerBase::Initialize"); ZEN_MEMSCOPE(GetZenserverTag()); @@ -349,7 +349,7 @@ ZenServerBase::HandleStatusRequest(HttpServerRequest& Request) ////////////////////////////////////////////////////////////////////////// -ZenServerMain::ZenServerMain(ZenServerOptions& ServerOptions) : m_ServerOptions(ServerOptions) +ZenServerMain::ZenServerMain(ZenServerConfig& ServerOptions) : m_ServerOptions(ServerOptions) { } diff --git a/src/zenserver/zenserver.h b/src/zenserver/zenserver.h index e8ada97ae..09a994428 100644 --- a/src/zenserver/zenserver.h +++ b/src/zenserver/zenserver.h @@ -27,7 +27,7 @@ namespace zen { struct FLLMTag; extern const FLLMTag& GetZenserverTag(); -struct ZenStorageServerOptions; +struct ZenStorageServerConfig; class ZenServerBase : public IHttpStatusProvider { @@ -43,7 +43,7 @@ public: void SetIsReadyFunc(std::function<void()>&& IsReadyFunc) { m_IsReadyFunc = std::move(IsReadyFunc); } protected: - int Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry); + int Initialize(const ZenServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry); void Finalize(); protected: @@ -109,7 +109,7 @@ protected: class ZenServerMain { public: - ZenServerMain(ZenServerOptions& ServerOptions); + ZenServerMain(ZenServerConfig& ServerOptions); ~ZenServerMain(); int Run(); @@ -118,8 +118,8 @@ public: ZenServerMain& operator=(const ZenServerMain&) = delete; protected: - ZenServerOptions& m_ServerOptions; - LockFile m_LockFile; + ZenServerConfig& m_ServerOptions; + LockFile m_LockFile; virtual void DoRun(ZenServerState::ZenServerEntry* Entry) = 0; |