diff options
Diffstat (limited to 'zenutil/include/zenutil/zenserverprocess.h')
| -rw-r--r-- | zenutil/include/zenutil/zenserverprocess.h | 134 |
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; +}; + +} |