aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/main.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2025-10-13 12:01:55 +0200
committerGitHub Enterprise <[email protected]>2025-10-13 12:01:55 +0200
commitd86ca9ac1c76e2841c44ede6b39930b6f934ef93 (patch)
treeec2c6a936229d343c843ac5f1962cb2ba96c8db0 /src/zenserver/main.cpp
parenthide http.sys options when unavailable (#568) (diff)
downloadzen-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.cpp241
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
}