diff options
| author | Stefan Boberg <[email protected]> | 2025-10-13 12:01:55 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-10-13 12:01:55 +0200 |
| commit | d86ca9ac1c76e2841c44ede6b39930b6f934ef93 (patch) | |
| tree | ec2c6a936229d343c843ac5f1962cb2ba96c8db0 | |
| parent | hide http.sys options when unavailable (#568) (diff) | |
| download | zen-d86ca9ac1c76e2841c44ede6b39930b6f934ef93.tar.xz zen-d86ca9ac1c76e2841c44ede6b39930b6f934ef93.zip | |
move service common code into base class (#567)
Separates storage server code and generic server code into two classes.
This is a change to prepare for different services to be implemented using the same framework, into the same executable
| -rw-r--r-- | src/zenserver/config.cpp | 10 | ||||
| -rw-r--r-- | src/zenserver/config.h | 69 | ||||
| -rw-r--r-- | src/zenserver/main.cpp | 241 | ||||
| -rw-r--r-- | src/zenserver/zenserver.cpp | 642 | ||||
| -rw-r--r-- | src/zenserver/zenserver.h | 163 |
5 files changed, 626 insertions, 499 deletions
diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index a355f0ed5..ce3a70184 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -95,7 +95,7 @@ ReadAllCentralManifests(const std::filesystem::path& SystemRoot) } void -ValidateOptions(ZenServerOptions& ServerOptions) +ValidateOptions(ZenStorageServerOptions& ServerOptions) { if (ServerOptions.EncryptionKey.empty() == false) { @@ -440,7 +440,7 @@ MakeOption(std::vector<std::pair<std::string, ZenStructuredCacheBucketConfig>>& }; void -ParseEnvVariables(ZenServerOptions& ServerOptions, const cxxopts::ParseResult& CmdLineResult) +ParseEnvVariables(ZenStorageServerOptions& ServerOptions, const cxxopts::ParseResult& CmdLineResult) { using namespace std::literals; @@ -464,7 +464,7 @@ ParseEnvVariables(ZenServerOptions& ServerOptions, const cxxopts::ParseResult& C void ParseConfigFile(const std::filesystem::path& Path, - ZenServerOptions& ServerOptions, + ZenStorageServerOptions& ServerOptions, const cxxopts::ParseResult& CmdLineResult, std::string_view OutputConfigFile) { @@ -679,7 +679,7 @@ ParseConfigFile(const std::filesystem::path& Path, } void -ParsePluginsConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions, int BasePort) +ParsePluginsConfigFile(const std::filesystem::path& Path, ZenStorageServerOptions& ServerOptions, int BasePort) { using namespace std::literals; @@ -741,7 +741,7 @@ ParsePluginsConfigFile(const std::filesystem::path& Path, ZenServerOptions& Serv } void -ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) +ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions) { const char* DefaultHttp = "asio"; diff --git a/src/zenserver/config.h b/src/zenserver/config.h index 3f7cb149a..d2311396e 100644 --- a/src/zenserver/config.h +++ b/src/zenserver/config.h @@ -170,55 +170,60 @@ struct ZenSentryConfig struct ZenServerOptions { + HttpServerConfig HttpServerConfig; + ZenSentryConfig SentryConfig; + int BasePort = 8558; // Service listen port (used for both UDP and TCP) + int OwnerPid = 0; // Parent process id (zero for standalone) + bool IsDebug = false; + bool IsCleanStart = false; // Indicates whether all state should be wiped on startup or not + bool IsPowerCycle = false; // When true, the process shuts down immediately after initialization + bool IsTest = false; + bool Detach = true; // Whether zenserver should detach from existing process group (Mac/Linux) + bool NoConsoleOutput = false; // Control default use of stdout for diagnostics + bool QuietConsole = false; // Configure console logger output to level WARN + int CoreLimit = 0; // If set, hardware concurrency queries are capped at this number + 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 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::string Loggers[zen::logging::level::LogLevelCount]; +#if ZEN_WITH_TRACE + bool HasTraceCommandlineOptions = false; + TraceOptions TraceOptions; +#endif + std::string MemoryOptions; // Memory allocation options + std::string CommandLine; + std::string EncryptionKey; // 256 bit AES encryption key + std::string EncryptionIV; // 128 bit AES initialization vector + + ZenStatsConfig StatsConfig; +}; + +struct ZenStorageServerOptions : public ZenServerOptions +{ ZenUpstreamCacheConfig UpstreamCacheConfig; ZenGcConfig GcConfig; ZenAuthConfig AuthConfig; ZenObjectStoreConfig ObjectStoreConfig; - zen::HttpServerConfig HttpServerConfig; ZenStructuredCacheConfig StructuredCacheConfig; ZenProjectStoreConfig ProjectStoreConfig; ZenBuildStoreConfig BuildStoreConfig; - ZenStatsConfig StatsConfig; ZenWorkspacesConfig WorksSpacesConfig; - ZenSentryConfig SentryConfig; - std::filesystem::path SystemRootDir; // System root directory (used for machine level config) - std::filesystem::path DataDir; // Root directory for state (used for testing) - std::filesystem::path ContentDir; // Root directory for serving frontend content (experimental) - std::filesystem::path AbsLogFile; // Absolute path to main log file std::filesystem::path ConfigFile; // Path to Lua config file 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) - std::string ChildId; // Id assigned by parent process (used for lifetime management) - std::string LogId; // Id for tagging log output - std::string EncryptionKey; // 256 bit AES encryption key - std::string EncryptionIV; // 128 bit AES initialization vector - int BasePort = 8558; // Service listen port (used for both UDP and TCP) - int OwnerPid = 0; // Parent process id (zero for standalone) bool InstallService = false; // Flag used to initiate service install (temporary) bool UninstallService = false; // Flag used to initiate service uninstall (temporary) - bool IsDebug = false; - bool IsCleanStart = false; // Indicates whether all state should be wiped on startup or not - bool IsPowerCycle = false; // When true, the process shuts down immediately after initialization - bool IsTest = false; - bool IsDedicated = false; // Indicates a dedicated/shared instance, with larger resource requirements - bool ShouldCrash = false; // Option for testing crash handling - bool IsFirstRun = false; - bool Detach = true; // Whether zenserver should detach from existing process group (Mac/Linux) bool ObjectStoreEnabled = false; - bool NoConsoleOutput = false; // Control default use of stdout for diagnostics - bool QuietConsole = false; // Configure console logger output to level WARN - int CoreLimit = 0; // If set, hardware concurrency queries are capped at this number - std::string Loggers[zen::logging::level::LogLevelCount]; std::string ScrubOptions; -#if ZEN_WITH_TRACE - bool HasTraceCommandlineOptions = false; - TraceOptions TraceOptions; -#endif - std::string MemoryOptions; // Memory allocation options - std::string CommandLine; }; -void ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions); +void ParseCliOptions(int argc, char* argv[], ZenStorageServerOptions& ServerOptions); void EmitCentralManifest(const std::filesystem::path& SystemRoot, Oid Identifier, CbObject Manifest, std::filesystem::path ManifestPath); std::vector<CbObject> ReadAllCentralManifests(const std::filesystem::path& SystemRoot); diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index b4d53ec5f..0dc390797 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -14,9 +14,7 @@ #include <zencore/session.h> #include <zencore/string.h> #include <zencore/thread.h> -#include <zencore/timer.h> #include <zencore/trace.h> -#include <zenhttp/httpserver.h> #include <zencore/memory/fmalloc.h> #include <zencore/memory/llm.h> @@ -73,25 +71,53 @@ using namespace std::literals; //////////////////////////////////////////////////////////////////////////////// -class ZenEntryPoint +class ZenServerMain { public: - ZenEntryPoint(ZenServerOptions& ServerOptions); - ZenEntryPoint(const ZenEntryPoint&) = delete; - ZenEntryPoint& operator=(const ZenEntryPoint&) = delete; - int Run(); + ZenServerMain(ZenServerOptions& ServerOptions); + ~ZenServerMain(); -private: + int Run(); + + ZenServerMain(const ZenServerMain&) = delete; + ZenServerMain& operator=(const ZenServerMain&) = delete; + +protected: ZenServerOptions& m_ServerOptions; LockFile m_LockFile; + + virtual void DoRun(ZenServerState::ZenServerEntry* Entry) = 0; + + void NotifyReady() + { + if (!m_ServerOptions.ChildId.empty()) + { + NamedEvent ParentEvent{m_ServerOptions.ChildId}; + ParentEvent.Set(); + } + } + + CbObject MakeLockData(bool IsReady) + { + return MakeLockFilePayload({.Pid = GetCurrentProcessId(), + .SessionId = GetSessionId(), + .EffectiveListenPort = gsl::narrow<uint16_t>(m_ServerOptions.BasePort), + .Ready = IsReady, + .DataDir = m_ServerOptions.DataDir, + .ExecutablePath = GetRunningExecutablePath()}); + }; }; -ZenEntryPoint::ZenEntryPoint(ZenServerOptions& ServerOptions) : m_ServerOptions(ServerOptions) +ZenServerMain::ZenServerMain(ZenServerOptions& ServerOptions) : m_ServerOptions(ServerOptions) +{ +} + +ZenServerMain::~ZenServerMain() { } int -ZenEntryPoint::Run() +ZenServerMain::Run() { // On Linux this has the unfortunate side effect of making `top` and other tools display // `main` as the program name since threads and processes have a closer relationship @@ -118,6 +144,7 @@ ZenEntryPoint::Run() m_ServerOptions.CommandLine); } #endif + try { // Mutual exclusion and synchronization @@ -125,14 +152,6 @@ ZenEntryPoint::Run() ServerState.Initialize(); ServerState.Sweep(); - auto NotifyReady = [&] { - if (!m_ServerOptions.ChildId.empty()) - { - NamedEvent ParentEvent{m_ServerOptions.ChildId}; - ParentEvent.Set(); - } - }; - uint32_t AttachSponsorProcessRetriesLeft = 3; ZenServerState::ZenServerEntry* Entry = ServerState.Lookup(m_ServerOptions.BasePort); while (Entry) @@ -202,15 +221,6 @@ ZenEntryPoint::Run() std::filesystem::path LockFilePath = m_ServerOptions.DataDir / ".lock"; - auto MakeLockData = [&](bool IsReady) { - return MakeLockFilePayload({.Pid = GetCurrentProcessId(), - .SessionId = GetSessionId(), - .EffectiveListenPort = gsl::narrow<uint16_t>(m_ServerOptions.BasePort), - .Ready = IsReady, - .DataDir = m_ServerOptions.DataDir, - .ExecutablePath = GetRunningExecutablePath()}); - }; - m_LockFile.Create(LockFilePath, MakeLockData(false), Ec); if (Ec) @@ -253,78 +263,9 @@ ZenEntryPoint::Run() Entry->AddSponsorProcess(m_ServerOptions.OwnerPid, 0); } - ZenServer Server; - Server.SetDataRoot(m_ServerOptions.DataDir); - Server.SetContentRoot(m_ServerOptions.ContentDir); - 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) - { - // Server.Initialize has already logged what the issue is - just exit with failure code here. - std::exit(1); - } - - Entry->EffectiveListenPort = uint16_t(EffectiveBasePort); - if (EffectiveBasePort != m_ServerOptions.BasePort) - { - ZEN_INFO(ZEN_APP_NAME " - relocated to base port {}", EffectiveBasePort); - m_ServerOptions.BasePort = EffectiveBasePort; - } - - std::unique_ptr<std::thread> ShutdownThread; - std::unique_ptr<NamedEvent> ShutdownEvent; - - ExtendableStringBuilder<64> ShutdownEventName; - ShutdownEventName << "Zen_" << m_ServerOptions.BasePort << "_Shutdown"; - ShutdownEvent.reset(new NamedEvent{ShutdownEventName}); - - // Monitor shutdown signals - - ShutdownThread.reset(new std::thread{[&] { - SetCurrentThreadName("shutdown_monitor"); - - ZEN_INFO("shutdown monitor thread waiting for shutdown signal '{}' for process {}", - ShutdownEventName, - zen::GetCurrentProcessId()); - - if (ShutdownEvent->Wait()) - { - ZEN_INFO("shutdown signal for pid {} received", zen::GetCurrentProcessId()); - Server.RequestExit(0); - } - else - { - ZEN_INFO("shutdown signal wait() failed"); - } - }}); - - auto CleanupShutdown = MakeGuard([&ShutdownEvent, &ShutdownThread] { - ReportServiceStatus(ServiceStatus::Stopping); - - if (ShutdownEvent) - { - ShutdownEvent->Set(); - } - if (ShutdownThread && ShutdownThread->joinable()) - { - ShutdownThread->join(); - } - }); - - // If we have a parent process, establish the mechanisms we need - // to be able to communicate readiness with the parent - - Server.SetIsReadyFunc([&] { - m_LockFile.Update(MakeLockData(true), Ec); - ReportServiceStatus(ServiceStatus::Running); - NotifyReady(); - }); + // Run the actual application logic - Server.Run(); + DoRun(Entry); } catch (const AssertException& AssertEx) { @@ -355,13 +296,109 @@ ZenEntryPoint::Run() } ////////////////////////////////////////////////////////////////////////// +class ZenStorageServerMain : public ZenServerMain +{ +public: + ZenStorageServerMain(ZenStorageServerOptions& ServerOptions); + virtual void DoRun(ZenServerState::ZenServerEntry* Entry) override; + + ZenStorageServerMain(const ZenStorageServerMain&) = delete; + ZenStorageServerMain& operator=(const ZenStorageServerMain&) = delete; + +private: + ZenStorageServerOptions& m_ServerOptions; +}; + +ZenStorageServerMain::ZenStorageServerMain(ZenStorageServerOptions& ServerOptions) +: ZenServerMain(ServerOptions) +, m_ServerOptions(ServerOptions) +{ +} + +void +ZenStorageServerMain::DoRun(ZenServerState::ZenServerEntry* Entry) +{ + ZenStorageServer Server; + Server.SetDataRoot(m_ServerOptions.DataDir); + Server.SetContentRoot(m_ServerOptions.ContentDir); + 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) + { + // Server.Initialize has already logged what the issue is - just exit with failure code here. + std::exit(1); + } + + Entry->EffectiveListenPort = uint16_t(EffectiveBasePort); + if (EffectiveBasePort != m_ServerOptions.BasePort) + { + ZEN_INFO(ZEN_APP_NAME " - relocated to base port {}", EffectiveBasePort); + m_ServerOptions.BasePort = EffectiveBasePort; + } + + std::unique_ptr<std::thread> ShutdownThread; + std::unique_ptr<NamedEvent> ShutdownEvent; + + ExtendableStringBuilder<64> ShutdownEventName; + ShutdownEventName << "Zen_" << m_ServerOptions.BasePort << "_Shutdown"; + ShutdownEvent.reset(new NamedEvent{ShutdownEventName}); + + // Monitor shutdown signals + + ShutdownThread.reset(new std::thread{[&] { + SetCurrentThreadName("shutdown_monitor"); + + ZEN_INFO("shutdown monitor thread waiting for shutdown signal '{}' for process {}", ShutdownEventName, zen::GetCurrentProcessId()); + + if (ShutdownEvent->Wait()) + { + ZEN_INFO("shutdown signal for pid {} received", zen::GetCurrentProcessId()); + Server.RequestExit(0); + } + else + { + ZEN_INFO("shutdown signal wait() failed"); + } + }}); + + auto CleanupShutdown = MakeGuard([&ShutdownEvent, &ShutdownThread] { + ReportServiceStatus(ServiceStatus::Stopping); + + if (ShutdownEvent) + { + ShutdownEvent->Set(); + } + if (ShutdownThread && ShutdownThread->joinable()) + { + ShutdownThread->join(); + } + }); + + // If we have a parent process, establish the mechanisms we need + // to be able to communicate readiness with the parent + + Server.SetIsReadyFunc([&] { + std::error_code Ec; + m_LockFile.Update(MakeLockData(true), Ec); + ReportServiceStatus(ServiceStatus::Running); + NotifyReady(); + }); + + Server.Run(); +} + +////////////////////////////////////////////////////////////////////////// #if ZEN_PLATFORM_WINDOWS class ZenWindowsService : public WindowsService { public: - ZenWindowsService(ZenServerOptions& ServerOptions) : m_EntryPoint(ServerOptions) {} + ZenWindowsService(ZenStorageServerOptions& ServerOptions) : m_EntryPoint(ServerOptions) {} ZenWindowsService(const ZenWindowsService&) = delete; ZenWindowsService& operator=(const ZenWindowsService&) = delete; @@ -369,7 +406,7 @@ public: virtual int Run() override; private: - ZenEntryPoint m_EntryPoint; + ZenStorageServerMain m_EntryPoint; }; int @@ -426,7 +463,7 @@ main(int argc, char* argv[]) try { - ZenServerOptions ServerOptions; + ZenStorageServerOptions ServerOptions; { #if ZEN_WITH_TRACE @@ -508,7 +545,7 @@ main(int argc, char* argv[]) throw std::runtime_error("Service mode is not supported on this platform"); } - ZenEntryPoint App(ServerOptions); + ZenStorageServerMain App(ServerOptions); return App.Run(); #endif } diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index 82ebc1711..0f53e657f 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -107,31 +107,22 @@ namespace utils { ////////////////////////////////////////////////////////////////////////// -ZenServer::ZenServer() +ZenServerBase::ZenServerBase() { } -ZenServer::~ZenServer() +ZenServerBase::~ZenServerBase() { } -void -ZenServer::OnReady() -{ - m_ServerEntry->SignalReady(); - - if (m_IsReadyFunc) - { - m_IsReadyFunc(); - } -} - int -ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) +ZenServerBase::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) { - ZEN_TRACE_CPU("ZenServer::Initialize"); - + ZEN_TRACE_CPU("ZenServerBase::Initialize"); ZEN_MEMSCOPE(GetZenserverTag()); + + m_IsPowerCycle = ServerOptions.IsPowerCycle; + const std::string MutexName = fmt::format("zen_{}", ServerOptions.BasePort); if (NamedMutex::Exists(MutexName)) @@ -140,14 +131,12 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen return -1; } - m_UseSentry = ServerOptions.SentryConfig.Disable == false; - m_ServerEntry = ServerEntry; - m_DebugOptionForcedCrash = ServerOptions.ShouldCrash; - m_IsPowerCycle = ServerOptions.IsPowerCycle; - const int ParentPid = ServerOptions.OwnerPid; - m_StartupScrubOptions = ServerOptions.ScrubOptions; + m_UseSentry = ServerOptions.SentryConfig.Disable == false; + m_ServerEntry = ServerEntry; + + // Initialize parent (sponsor) process monitoring - if (ParentPid) + if (const int ParentPid = ServerOptions.OwnerPid) { std::error_code Ec; ProcessHandle OwnerProcess; @@ -175,16 +164,7 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen ThrowLastError(fmt::format("Failed to create mutex '{}'", MutexName).c_str()); } - InitializeState(ServerOptions); - - m_JobQueue = MakeJobQueue(8, "bgjobs"); - - m_HealthService.SetHealthInfo({.DataRoot = m_DataRoot, - .AbsLogPath = ServerOptions.AbsLogFile, - .HttpServerClass = std::string(ServerOptions.HttpServerConfig.ServerClass), - .BuildVersion = std::string(ZEN_CFG_VERSION_BUILD_STRING_FULL)}); - - // Ok so now we're configured, let's kick things off + EnqueueSigIntTimer(); m_Http = CreateHttpServer(ServerOptions.HttpServerConfig); int EffectiveBasePort = m_Http->Initialize(ServerOptions.BasePort, ServerOptions.DataDir); @@ -197,56 +177,311 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen return -1; } - // Setup authentication manager + ZEN_INFO("Effective concurrency: {} (hw: {})", GetHardwareConcurrency(), std::thread::hardware_concurrency()); + + m_StatusService.RegisterHandler("status", *this); + m_Http->RegisterService(m_StatusService); + + m_StatsReporter.Initialize(ServerOptions.StatsConfig); + if (ServerOptions.StatsConfig.Enabled) { - ZEN_TRACE_CPU("Zenserver::InitAuth"); - std::string EncryptionKey = ServerOptions.EncryptionKey; + EnqueueStatsReportingTimer(); + } - if (EncryptionKey.empty()) + return EffectiveBasePort; +} + +void +ZenServerBase::Finalize() +{ + // Register health service last so if we return "OK" for health it means all services have been properly initialized + + m_Http->RegisterService(m_HealthService); +} + +void +ZenServerBase::EnsureIoRunner() +{ + ZEN_MEMSCOPE(GetZenserverTag()); + if (!m_IoRunner.joinable()) + { + m_IoRunner = std::thread{[this] { + SetCurrentThreadName("timer_io"); + m_IoContext.run(); + }}; + } +} + +void +ZenServerBase::OnReady() +{ + if (m_ServerEntry) + { + m_ServerEntry->SignalReady(); + } + + if (m_IsReadyFunc) + { + m_IsReadyFunc(); + } +} + +void +ZenServerBase::RequestExit(int ExitCode) +{ + if (RequestApplicationExit(ExitCode)) + { + if (m_Http) { - EncryptionKey = "abcdefghijklmnopqrstuvxyz0123456"; + m_Http->RequestExit(); + } + } +} - if (ServerOptions.IsDedicated) - { - ZEN_WARN("Using default encryption key for authentication state"); - } +std::string_view +ZenServerBase::ToString(ServerState Value) +{ + switch (Value) + { + case kInitializing: + return "initializing"sv; + case kRunning: + return "running"sv; + case kShuttingDown: + return "shutdown"sv; + default: + return "unknown"sv; + } +} + +void +ZenServerBase::EnqueueStatsReportingTimer() +{ + ZEN_MEMSCOPE(GetZenserverTag()); + m_StatsReportingTimer.expires_after(std::chrono::milliseconds(500)); + m_StatsReportingTimer.async_wait([this](const asio::error_code& Ec) { + if (!Ec) + { + m_StatsReporter.ReportStats(); + EnqueueStatsReportingTimer(); } + }); + EnsureIoRunner(); +} - std::string EncryptionIV = ServerOptions.EncryptionIV; +void +ZenServerBase::EnqueueProcessMonitorTimer() +{ + ZEN_MEMSCOPE(GetZenserverTag()); + m_PidCheckTimer.expires_after(std::chrono::seconds(1)); + m_PidCheckTimer.async_wait([this](const asio::error_code&) { CheckOwnerPid(); }); - if (EncryptionIV.empty()) + EnsureIoRunner(); +} + +void +ZenServerBase::CheckOwnerPid() +{ + bool IsRunning = UpdateProcessMonitor(); + + if (IsRunning) + { + m_FoundNoActiveSponsors = false; + EnqueueProcessMonitorTimer(); + } + else + { + // Delay exit one iteration to avoid race conditions where one process detaches + // and another attaches + if (m_FoundNoActiveSponsors) { - EncryptionIV = "0123456789abcdef"; + ZEN_INFO(ZEN_APP_NAME " exiting since sponsor processes are all gone"); + RequestExit(0); + } + else + { + m_FoundNoActiveSponsors = true; + EnqueueProcessMonitorTimer(); + } + } +} - if (ServerOptions.IsDedicated) +bool +ZenServerBase::UpdateProcessMonitor() +{ + if (m_ServerEntry) + { + // Pick up any new "owner" processes + std::set<uint32_t> AddedPids; + + for (auto& PidEntry : m_ServerEntry->SponsorPids) + { + if (uint32_t ThisPid = PidEntry.load(std::memory_order_relaxed)) { - ZEN_WARN("Using default encryption initialization vector for authentication state"); + if (PidEntry.compare_exchange_strong(ThisPid, 0)) + { + if (AddedPids.insert(ThisPid).second) + { + m_ProcessMonitor.AddPid(ThisPid); + + ZEN_INFO("added process with pid {} as a sponsor process", ThisPid); + } + } } } + } + return m_ProcessMonitor.IsRunning(); +} - m_AuthMgr = AuthMgr::Create({.RootDirectory = m_DataRoot / "auth", - .EncryptionKey = AesKey256Bit::FromString(EncryptionKey), - .EncryptionIV = AesIV128Bit::FromString(EncryptionIV)}); +void +ZenServerBase::EnqueueStateExitFlagTimer() +{ + ZEN_MEMSCOPE(GetZenserverTag()); + m_StateExitFlagTimer.expires_after(std::chrono::milliseconds(500)); + m_StateExitFlagTimer.async_wait([this](const asio::error_code&) { CheckStateExitFlag(); }); + EnsureIoRunner(); +} - for (const ZenOpenIdProviderConfig& OpenIdProvider : ServerOptions.AuthConfig.OpenIdProviders) - { - m_AuthMgr->AddOpenIdProvider({.Name = OpenIdProvider.Name, .Url = OpenIdProvider.Url, .ClientId = OpenIdProvider.ClientId}); - } +void +ZenServerBase::CheckStateExitFlag() +{ + if (m_ServerEntry && m_ServerEntry->IsShutdownRequested()) + { + RequestExit(0); + return; } + EnqueueStateExitFlagTimer(); +} - m_AuthService = std::make_unique<HttpAuthService>(*m_AuthMgr); +void +ZenServerBase::EnqueueSigIntTimer() +{ + ZEN_MEMSCOPE(GetZenserverTag()); + m_SigIntTimer.expires_after(std::chrono::milliseconds(500)); + m_SigIntTimer.async_wait([this](const asio::error_code&) { CheckSigInt(); }); + EnsureIoRunner(); +} - m_StatsReporter.Initialize(ServerOptions.StatsConfig); - if (ServerOptions.StatsConfig.Enabled) +void +ZenServerBase::CheckSigInt() +{ + if (utils::SignalCounter[SIGINT] > 0) { - EnqueueStatsReportingTimer(); + ZEN_INFO("SIGINT triggered (Ctrl+C) for process {}, exiting", zen::GetCurrentProcessId()); + RequestExit(128 + SIGINT); + return; + } + if (utils::SignalCounter[SIGTERM] > 0) + { + ZEN_INFO("SIGTERM triggered for process {}, exiting", zen::GetCurrentProcessId()); + RequestExit(128 + SIGTERM); + return; } + EnqueueSigIntTimer(); +} - m_StatusService.RegisterHandler("status", *this); +void +ZenServerBase::HandleStatusRequest(HttpServerRequest& Request) +{ + CbObjectWriter Cbo; + Cbo << "ok" << true; + Cbo << "state" << ToString(m_CurrentState); + Request.WriteResponse(HttpResponseCode::OK, Cbo.Save()); +} - ZEN_INFO("Effective concurrency: {} (hw: {})", GetHardwareConcurrency(), std::thread::hardware_concurrency()); +////////////////////////////////////////////////////////////////////////// + +ZenStorageServer::ZenStorageServer() +{ +} + +ZenStorageServer::~ZenStorageServer() +{ +} + +int +ZenStorageServer::Initialize(const ZenStorageServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) +{ + ZEN_TRACE_CPU("ZenStorageServer::Initialize"); + ZEN_MEMSCOPE(GetZenserverTag()); + + const int EffectiveBasePort = ZenServerBase::Initialize(ServerOptions, ServerEntry); + if (EffectiveBasePort < 0) + { + return EffectiveBasePort; + } + + m_DebugOptionForcedCrash = ServerOptions.ShouldCrash; + m_StartupScrubOptions = ServerOptions.ScrubOptions; + + InitializeState(ServerOptions); + InitializeServices(ServerOptions); + RegisterServices(); + + ZenServerBase::Finalize(); + + return EffectiveBasePort; +} + +void +ZenStorageServer::RegisterServices() +{ + m_Http->RegisterService(*m_AuthService); + m_Http->RegisterService(m_StatsService); + m_Http->RegisterService(m_TestService); // NOTE: this is intentionally not limited to test mode as it's useful for diagnostics + +#if ZEN_WITH_TESTS + m_Http->RegisterService(m_TestingService); +#endif + + if (m_StructuredCacheService) + { + m_Http->RegisterService(*m_StructuredCacheService); + } + + if (m_UpstreamService) + { + m_Http->RegisterService(*m_UpstreamService); + } + + if (m_HttpProjectService) + { + m_Http->RegisterService(*m_HttpProjectService); + } + + if (m_HttpWorkspacesService) + { + m_Http->RegisterService(*m_HttpWorkspacesService); + } - // Initialize storage and services + m_FrontendService = std::make_unique<HttpFrontendService>(m_ContentRoot, m_StatusService); + + if (m_FrontendService) + { + m_Http->RegisterService(*m_FrontendService); + } + + if (m_ObjStoreService) + { + m_Http->RegisterService(*m_ObjStoreService); + } + + if (m_BuildStoreService) + { + m_Http->RegisterService(*m_BuildStoreService); + } + +#if ZEN_WITH_VFS + m_Http->RegisterService(*m_VfsService); +#endif // ZEN_WITH_VFS + + m_Http->RegisterService(*m_AdminService); +} + +void +ZenStorageServer::InitializeServices(const ZenStorageServerOptions& ServerOptions) +{ + InitializeAuthentication(ServerOptions); ZEN_INFO("initializing storage"); @@ -258,6 +493,8 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen ZEN_INFO("instantiating project service"); + m_JobQueue = MakeJobQueue(8, "bgjobs"); + m_ProjectStore = new ProjectStore(*m_CidStore, m_DataRoot / "projects", m_GcManager, ProjectStore::Configuration{}); m_HttpProjectService.reset( new HttpProjectService{*m_CidStore, m_ProjectStore, m_StatusService, m_StatsService, *m_AuthMgr, *m_OpenProcessCache, *m_JobQueue}); @@ -357,74 +594,55 @@ ZenServer::Initialize(const ZenServerOptions& ServerOptions, ZenServerState::Zen .HttpLogPath = ServerOptions.DataDir / "logs" / "http.log", .CacheLogPath = ServerOptions.DataDir / "logs" / "z$.log"}, ServerOptions); +} - // Register all services when all initialization for all services are done - - m_Http->RegisterService(*m_AuthService); - - m_Http->RegisterService(m_StatsService); - m_Http->RegisterService(m_StatusService); - m_Http->RegisterService(m_TestService); // NOTE: this is intentionally not limited to test mode as it's useful for diagnostics - -#if ZEN_WITH_TESTS - m_Http->RegisterService(m_TestingService); -#endif - - if (m_StructuredCacheService) +void +ZenStorageServer::InitializeAuthentication(const ZenStorageServerOptions& ServerOptions) +{ + // Setup authentication manager { - m_Http->RegisterService(*m_StructuredCacheService); - } + ZEN_TRACE_CPU("ZenStorageServer::InitAuth"); + std::string EncryptionKey = ServerOptions.EncryptionKey; - if (m_UpstreamService) - { - m_Http->RegisterService(*m_UpstreamService); - } + if (EncryptionKey.empty()) + { + EncryptionKey = "abcdefghijklmnopqrstuvxyz0123456"; - if (m_HttpProjectService) - { - m_Http->RegisterService(*m_HttpProjectService); - } + if (ServerOptions.IsDedicated) + { + ZEN_WARN("Using default encryption key for authentication state"); + } + } - if (m_HttpWorkspacesService) - { - m_Http->RegisterService(*m_HttpWorkspacesService); - } + std::string EncryptionIV = ServerOptions.EncryptionIV; - m_FrontendService = std::make_unique<HttpFrontendService>(m_ContentRoot, m_StatusService); + if (EncryptionIV.empty()) + { + EncryptionIV = "0123456789abcdef"; - if (m_FrontendService) - { - m_Http->RegisterService(*m_FrontendService); - } + if (ServerOptions.IsDedicated) + { + ZEN_WARN("Using default encryption initialization vector for authentication state"); + } + } - if (m_ObjStoreService) - { - m_Http->RegisterService(*m_ObjStoreService); - } + m_AuthMgr = AuthMgr::Create({.RootDirectory = m_DataRoot / "auth", + .EncryptionKey = AesKey256Bit::FromString(EncryptionKey), + .EncryptionIV = AesIV128Bit::FromString(EncryptionIV)}); - if (m_BuildStoreService) - { - m_Http->RegisterService(*m_BuildStoreService); + for (const ZenOpenIdProviderConfig& OpenIdProvider : ServerOptions.AuthConfig.OpenIdProviders) + { + m_AuthMgr->AddOpenIdProvider({.Name = OpenIdProvider.Name, .Url = OpenIdProvider.Url, .ClientId = OpenIdProvider.ClientId}); + } } -#if ZEN_WITH_VFS - m_Http->RegisterService(*m_VfsService); -#endif // ZEN_WITH_VFS - - m_Http->RegisterService(*m_AdminService); - - // Register health service last so if we return "OK" for health it means all services have been properly initialized - m_Http->RegisterService(m_HealthService); - - return EffectiveBasePort; + m_AuthService = std::make_unique<HttpAuthService>(*m_AuthMgr); } void -ZenServer::InitializeState(const ZenServerOptions& ServerOptions) +ZenStorageServer::InitializeState(const ZenStorageServerOptions& ServerOptions) { - ZEN_TRACE_CPU("ZenServer::InitializeState"); - - EnqueueSigIntTimer(); + ZEN_TRACE_CPU("ZenStorageServer::InitializeState"); // Check root manifest to deal with schema versioning @@ -586,9 +804,9 @@ ZenServer::InitializeState(const ZenServerOptions& ServerOptions) } void -ZenServer::InitializeStructuredCache(const ZenServerOptions& ServerOptions) +ZenStorageServer::InitializeStructuredCache(const ZenStorageServerOptions& ServerOptions) { - ZEN_TRACE_CPU("ZenServer::InitializeStructuredCache"); + ZEN_TRACE_CPU("ZenStorageServer::InitializeStructuredCache"); using namespace std::literals; @@ -718,7 +936,7 @@ ZenServer::InitializeStructuredCache(const ZenServerOptions& ServerOptions) } void -ZenServer::Run() +ZenStorageServer::Run() { if (m_ProcessMonitor.IsActive()) { @@ -841,21 +1059,9 @@ ZenServer::Run() } void -ZenServer::RequestExit(int ExitCode) +ZenStorageServer::Cleanup() { - if (RequestApplicationExit(ExitCode)) - { - if (m_Http) - { - m_Http->RequestExit(); - } - } -} - -void -ZenServer::Cleanup() -{ - ZEN_TRACE_CPU("ZenServer::Cleanup"); + ZEN_TRACE_CPU("ZenStorageServer::Cleanup"); ZEN_INFO(ZEN_APP_NAME " cleaning up"); try { @@ -869,6 +1075,7 @@ ZenServer::Cleanup() { m_Http->Close(); } + if (m_JobQueue) { m_JobQueue->Stop(); @@ -915,72 +1122,16 @@ ZenServer::Cleanup() } void -ZenServer::EnsureIoRunner() -{ - ZEN_MEMSCOPE(GetZenserverTag()); - if (!m_IoRunner.joinable()) - { - m_IoRunner = std::thread{[this] { - SetCurrentThreadName("timer_io"); - m_IoContext.run(); - }}; - } -} - -void -ZenServer::EnqueueProcessMonitorTimer() -{ - ZEN_MEMSCOPE(GetZenserverTag()); - m_PidCheckTimer.expires_after(std::chrono::seconds(1)); - m_PidCheckTimer.async_wait([this](const asio::error_code&) { CheckOwnerPid(); }); - - EnsureIoRunner(); -} - -void -ZenServer::EnqueueStateMarkerTimer() -{ - ZEN_MEMSCOPE(GetZenserverTag()); - m_StateMakerTimer.expires_after(std::chrono::seconds(5)); - m_StateMakerTimer.async_wait([this](const asio::error_code&) { CheckStateMarker(); }); - EnsureIoRunner(); -} - -void -ZenServer::EnqueueSigIntTimer() -{ - ZEN_MEMSCOPE(GetZenserverTag()); - m_SigIntTimer.expires_after(std::chrono::milliseconds(500)); - m_SigIntTimer.async_wait([this](const asio::error_code&) { CheckSigInt(); }); - EnsureIoRunner(); -} - -void -ZenServer::EnqueueStateExitFlagTimer() -{ - ZEN_MEMSCOPE(GetZenserverTag()); - m_StateExitFlagTimer.expires_after(std::chrono::milliseconds(500)); - m_StateExitFlagTimer.async_wait([this](const asio::error_code&) { CheckStateExitFlag(); }); - EnsureIoRunner(); -} - -void -ZenServer::EnqueueStatsReportingTimer() +ZenStorageServer::EnqueueStateMarkerTimer() { ZEN_MEMSCOPE(GetZenserverTag()); - m_StatsReportingTimer.expires_after(std::chrono::milliseconds(500)); - m_StatsReportingTimer.async_wait([this](const asio::error_code& Ec) { - if (!Ec) - { - m_StatsReporter.ReportStats(); - EnqueueStatsReportingTimer(); - } - }); + m_StateMarkerTimer.expires_after(std::chrono::seconds(5)); + m_StateMarkerTimer.async_wait([this](const asio::error_code&) { CheckStateMarker(); }); EnsureIoRunner(); } void -ZenServer::CheckStateMarker() +ZenStorageServer::CheckStateMarker() { ZEN_MEMSCOPE(GetZenserverTag()); std::filesystem::path StateMarkerPath = m_DataRoot / "state_marker"; @@ -1003,89 +1154,9 @@ ZenServer::CheckStateMarker() } void -ZenServer::CheckSigInt() -{ - if (utils::SignalCounter[SIGINT] > 0) - { - ZEN_INFO("SIGINT triggered (Ctrl+C) for process {}, exiting", zen::GetCurrentProcessId()); - RequestExit(128 + SIGINT); - return; - } - if (utils::SignalCounter[SIGTERM] > 0) - { - ZEN_INFO("SIGTERM triggered for process {}, exiting", zen::GetCurrentProcessId()); - RequestExit(128 + SIGTERM); - return; - } - EnqueueSigIntTimer(); -} - -void -ZenServer::CheckStateExitFlag() -{ - if (m_ServerEntry && m_ServerEntry->IsShutdownRequested()) - { - RequestExit(0); - return; - } - EnqueueStateExitFlagTimer(); -} - -bool -ZenServer::UpdateProcessMonitor() -{ - // Pick up any new "owner" processes - std::set<uint32_t> AddedPids; - - for (auto& PidEntry : m_ServerEntry->SponsorPids) - { - if (uint32_t ThisPid = PidEntry.load(std::memory_order_relaxed)) - { - if (PidEntry.compare_exchange_strong(ThisPid, 0)) - { - if (AddedPids.insert(ThisPid).second) - { - m_ProcessMonitor.AddPid(ThisPid); - - ZEN_INFO("added process with pid {} as a sponsor process", ThisPid); - } - } - } - } - return m_ProcessMonitor.IsRunning(); -} - -void -ZenServer::CheckOwnerPid() -{ - bool IsRunning = UpdateProcessMonitor(); - - if (IsRunning) - { - m_FoundNoActiveSponsors = false; - EnqueueProcessMonitorTimer(); - } - else - { - // Delay exit one iteration to avoid race conditions where one process detaches - // and another attaches - if (m_FoundNoActiveSponsors) - { - ZEN_INFO(ZEN_APP_NAME " exiting since sponsor processes are all gone"); - RequestExit(0); - } - else - { - m_FoundNoActiveSponsors = true; - EnqueueProcessMonitorTimer(); - } - } -} - -void -ZenServer::Flush() +ZenStorageServer::Flush() { - ZEN_TRACE_CPU("ZenServer::Flush"); + ZEN_TRACE_CPU("ZenStorageServer::Flush"); if (m_CidStore) m_CidStore->Flush(); @@ -1100,31 +1171,6 @@ ZenServer::Flush() m_BuildCidStore->Flush(); } -void -ZenServer::HandleStatusRequest(HttpServerRequest& Request) -{ - CbObjectWriter Cbo; - Cbo << "ok" << true; - Cbo << "state" << ToString(m_CurrentState); - Request.WriteResponse(HttpResponseCode::OK, Cbo.Save()); -} - -std::string_view -ZenServer::ToString(ServerState Value) -{ - switch (Value) - { - case kInitializing: - return "initializing"sv; - case kRunning: - return "running"sv; - case kShuttingDown: - return "shutdown"sv; - default: - return "unknown"sv; - } -} - #if ZEN_WITH_TESTS void diff --git a/src/zenserver/zenserver.h b/src/zenserver/zenserver.h index ba76c5fff..5447158ab 100644 --- a/src/zenserver/zenserver.h +++ b/src/zenserver/zenserver.h @@ -43,84 +43,129 @@ ZEN_THIRD_PARTY_INCLUDES_END namespace zen { -struct ZenServerOptions; +struct ZenStorageServerOptions; -class ZenServer : public IHttpStatusProvider +class ZenServerBase : public IHttpStatusProvider { - ZenServer& operator=(ZenServer&&) = delete; - ZenServer(ZenServer&&) = delete; + ZenServerBase& operator=(ZenServerBase&&) = delete; + ZenServerBase(ZenServerBase&&) = delete; public: - ZenServer(); - ~ZenServer(); + ZenServerBase(); + ~ZenServerBase(); + void RequestExit(int ExitCode); + + void SetIsReadyFunc(std::function<void()>&& IsReadyFunc) { m_IsReadyFunc = std::move(IsReadyFunc); } + +protected: int Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry); - void InitializeState(const ZenServerOptions& ServerOptions); - void InitializeStructuredCache(const ZenServerOptions& ServerOptions); + void Finalize(); - void Run(); - void RequestExit(int ExitCode); - void Cleanup(); +protected: + NamedMutex m_ServerMutex; + ZenServerState::ZenServerEntry* m_ServerEntry = nullptr; + bool m_UseSentry = false; + bool m_IsPowerCycle = false; - void SetDedicatedMode(bool State) { m_IsDedicatedMode = State; } - void SetTestMode(bool State) { m_TestMode = State; } - void SetDataRoot(std::filesystem::path Root) { m_DataRoot = Root; } - void SetContentRoot(std::filesystem::path Root) { m_ContentRoot = Root; } + std::thread m_IoRunner; + asio::io_context m_IoContext; + void EnsureIoRunner(); + + enum ServerState + { + kInitializing, + kRunning, + kShuttingDown + } m_CurrentState = kInitializing; + + inline void SetNewState(ServerState NewState) { m_CurrentState = NewState; } + static std::string_view ToString(ServerState Value); std::function<void()> m_IsReadyFunc; - void SetIsReadyFunc(std::function<void()>&& IsReadyFunc) { m_IsReadyFunc = std::move(IsReadyFunc); } void OnReady(); - void EnsureIoRunner(); + Ref<HttpServer> m_Http; + HttpHealthService m_HealthService; + HttpStatusService m_StatusService; + + // Stats reporting + + StatsReporter m_StatsReporter; + asio::steady_timer m_StatsReportingTimer{m_IoContext}; + void EnqueueStatsReportingTimer(); + + // Process Monitoring + + void CheckOwnerPid(); + bool UpdateProcessMonitor(); void EnqueueProcessMonitorTimer(); - void EnqueueStateMarkerTimer(); - void EnqueueSigIntTimer(); + + ProcessMonitor m_ProcessMonitor; + asio::steady_timer m_PidCheckTimer{m_IoContext}; + bool m_FoundNoActiveSponsors = false; + + // Server state exit signaling + + asio::steady_timer m_StateExitFlagTimer{m_IoContext}; + void EnqueueStateExitFlagTimer(); - void EnqueueStatsReportingTimer(); - void CheckStateMarker(); - void CheckSigInt(); void CheckStateExitFlag(); - void CheckOwnerPid(); - bool UpdateProcessMonitor(); - void Flush(); + // SIGINT handling + + void EnqueueSigIntTimer(); + void CheckSigInt(); + asio::steady_timer m_SigIntTimer{m_IoContext}; + + // IHttpStatusProvider virtual void HandleStatusRequest(HttpServerRequest& Request) override; +}; + +class ZenStorageServer : public ZenServerBase +{ + ZenStorageServer& operator=(ZenStorageServer&&) = delete; + ZenStorageServer(ZenStorageServer&&) = delete; + +public: + ZenStorageServer(); + ~ZenStorageServer(); + + void SetDedicatedMode(bool State) { m_IsDedicatedMode = State; } + void SetTestMode(bool State) { m_TestMode = State; } + 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); + void Run(); + void Cleanup(); private: - ZenServerState::ZenServerEntry* m_ServerEntry = nullptr; - bool m_IsDedicatedMode = false; - bool m_TestMode = false; - bool m_IsPowerCycle = false; - CbObject m_RootManifest; - std::filesystem::path m_DataRoot; - std::filesystem::path m_ContentRoot; - std::thread m_IoRunner; - asio::io_context m_IoContext; - asio::steady_timer m_PidCheckTimer{m_IoContext}; - asio::steady_timer m_StateMakerTimer{m_IoContext}; - asio::steady_timer m_StateExitFlagTimer{m_IoContext}; - asio::steady_timer m_SigIntTimer{m_IoContext}; - asio::steady_timer m_StatsReportingTimer{m_IoContext}; - ProcessMonitor m_ProcessMonitor; - NamedMutex m_ServerMutex; - bool m_FoundNoActiveSponsors = false; + void InitializeState(const ZenStorageServerOptions& ServerOptions); + void InitializeStructuredCache(const ZenStorageServerOptions& ServerOptions); + void Flush(); - enum ServerState - { - kInitializing, - kRunning, - kShuttingDown - } m_CurrentState = kInitializing; + bool m_IsDedicatedMode = false; + bool m_TestMode = false; + bool m_DebugOptionForcedCrash = false; + std::string m_StartupScrubOptions; + CbObject m_RootManifest; + std::filesystem::path m_DataRoot; + std::filesystem::path m_ContentRoot; + asio::steady_timer m_StateMarkerTimer{m_IoContext}; - inline void SetNewState(ServerState NewState) { m_CurrentState = NewState; } - static std::string_view ToString(ServerState Value); + void EnqueueStateMarkerTimer(); + void CheckStateMarker(); + + std::unique_ptr<AuthMgr> m_AuthMgr; + std::unique_ptr<HttpAuthService> m_AuthService; + void InitializeAuthentication(const ZenStorageServerOptions& ServerOptions); + + void InitializeServices(const ZenStorageServerOptions& ServerOptions); + void RegisterServices(); - StatsReporter m_StatsReporter; - Ref<HttpServer> m_Http; - std::unique_ptr<AuthMgr> m_AuthMgr; - std::unique_ptr<HttpAuthService> m_AuthService; - HttpStatusService m_StatusService; HttpStatsService m_StatsService; + std::unique_ptr<JobQueue> m_JobQueue; GcManager m_GcManager; GcScheduler m_GcScheduler{m_GcManager}; std::unique_ptr<CidStore> m_CidStore; @@ -133,6 +178,7 @@ private: #if ZEN_WITH_TESTS HttpTestingService m_TestingService; #endif + RefPtr<ProjectStore> m_ProjectStore; std::unique_ptr<VfsServiceImpl> m_VfsServiceImpl; std::unique_ptr<HttpProjectService> m_HttpProjectService; @@ -141,18 +187,11 @@ private: std::unique_ptr<UpstreamCache> m_UpstreamCache; std::unique_ptr<HttpUpstreamService> m_UpstreamService; std::unique_ptr<HttpStructuredCacheService> m_StructuredCacheService; - HttpHealthService m_HealthService; std::unique_ptr<HttpFrontendService> m_FrontendService; std::unique_ptr<HttpObjectStoreService> m_ObjStoreService; std::unique_ptr<HttpBuildStoreService> m_BuildStoreService; std::unique_ptr<VfsService> m_VfsService; - std::unique_ptr<JobQueue> m_JobQueue; std::unique_ptr<HttpAdminService> m_AdminService; - - bool m_DebugOptionForcedCrash = false; - bool m_UseSentry = false; - - std::string m_StartupScrubOptions; }; void zenserver_forcelinktests(); |