aboutsummaryrefslogtreecommitdiff
path: root/zenutil/include/zenutil/zenserverprocess.h
diff options
context:
space:
mode:
Diffstat (limited to 'zenutil/include/zenutil/zenserverprocess.h')
-rw-r--r--zenutil/include/zenutil/zenserverprocess.h134
1 files changed, 134 insertions, 0 deletions
diff --git a/zenutil/include/zenutil/zenserverprocess.h b/zenutil/include/zenutil/zenserverprocess.h
new file mode 100644
index 000000000..f0924f048
--- /dev/null
+++ b/zenutil/include/zenutil/zenserverprocess.h
@@ -0,0 +1,134 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/enumflags.h>
+#include <zencore/logging.h>
+#include <zencore/thread.h>
+#include <zencore/uid.h>
+
+#include <gsl/gsl-lite.hpp>
+
+#include <atomic>
+#include <filesystem>
+#include <optional>
+
+namespace zen {
+
+class ZenServerEnvironment
+{
+public:
+ ZenServerEnvironment();
+ ~ZenServerEnvironment();
+
+ void Initialize(std::filesystem::path ProgramBaseDir);
+ void InitializeForTest(std::filesystem::path ProgramBaseDir, std::filesystem::path TestBaseDir);
+
+ std::filesystem::path CreateNewTestDir();
+ std::filesystem::path ProgramBaseDir() const { return m_ProgramBaseDir; }
+ std::filesystem::path GetTestRootDir(std::string_view Path);
+ inline bool IsInitialized() const { return m_IsInitialized; }
+ inline bool IsTestEnvironment() const { return m_IsTestInstance; }
+
+private:
+ std::filesystem::path m_ProgramBaseDir;
+ std::filesystem::path m_TestBaseDir;
+ bool m_IsInitialized = false;
+ bool m_IsTestInstance = false;
+};
+
+struct ZenServerInstance
+{
+ ZenServerInstance(ZenServerEnvironment& TestEnvironment);
+ ~ZenServerInstance();
+
+ void Shutdown();
+ void SignalShutdown();
+ void WaitUntilReady();
+ [[nodiscard]] bool WaitUntilReady(int Timeout);
+ void EnableTermination() { m_Terminate = true; }
+ void EnableMesh() { m_MeshEnabled = true; }
+ void Detach();
+ inline int GetPid() { return m_Process.Pid(); }
+ inline void SetOwnerPid(int Pid) { m_OwnerPid = Pid; }
+
+ void SetTestDir(std::filesystem::path TestDir)
+ {
+ ZEN_ASSERT(!m_Process.IsValid());
+ m_TestDir = TestDir;
+ }
+
+ void SpawnServer(int BasePort = 0, std::string_view AdditionalServerArgs = std::string_view());
+
+ void AttachToRunningServer(int BasePort = 0);
+
+ std::string GetBaseUri() const;
+
+private:
+ ZenServerEnvironment& m_Env;
+ zen::ProcessHandle m_Process;
+ zen::Event m_ReadyEvent;
+ zen::Event m_ShutdownEvent;
+ bool m_Terminate = false;
+ std::filesystem::path m_TestDir;
+ bool m_MeshEnabled = false;
+ int m_BasePort = 0;
+ std::optional<int> m_OwnerPid;
+
+ void CreateShutdownEvent(int BasePort);
+};
+
+/** Shared system state
+ *
+ * Used as a scratchpad to identify running instances etc
+ *
+ * The state lives in a memory-mapped file backed by the swapfile
+ *
+ */
+
+class ZenServerState
+{
+public:
+ ZenServerState();
+ ~ZenServerState();
+
+ struct ZenServerEntry
+ {
+ std::atomic<uint32_t> Pid;
+ std::atomic<uint16_t> ListenPort;
+ std::atomic<uint16_t> Flags;
+ uint8_t SessionId[12];
+ std::atomic<uint32_t> SponsorPids[32];
+ uint8_t Padding[12];
+ uint8_t Padding2[96];
+
+ enum class FlagsEnum : uint16_t
+ {
+ kShutdownPlease = 1 << 0
+ };
+
+ FRIEND_ENUM_CLASS_FLAGS(FlagsEnum);
+
+ zen::Oid GetSessionId() const { return zen::Oid::FromMemory(SessionId); }
+ void Reset();
+ void SignalShutdownRequest();
+ bool AddSponsorProcess(uint32_t Pid);
+ };
+
+ static_assert(sizeof(ZenServerEntry) == 256);
+
+ void Initialize();
+ [[nodiscard]] bool InitializeReadOnly();
+ [[nodiscard]] ZenServerEntry* Lookup(int ListenPort);
+ ZenServerEntry* Register(int ListenPort);
+ void Sweep();
+ void Snapshot(std::function<void(const ZenServerEntry&)>&& Callback);
+
+private:
+ void* m_hMapFile = nullptr;
+ ZenServerEntry* m_Data = nullptr;
+ int m_MaxEntryCount = 131072 / sizeof(ZenServerEntry);
+ ZenServerEntry* m_OurEntry = nullptr;
+};
+
+}