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 /src/zenserver/main.cpp | |
| 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
Diffstat (limited to 'src/zenserver/main.cpp')
| -rw-r--r-- | src/zenserver/main.cpp | 241 |
1 files changed, 139 insertions, 102 deletions
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 } |