// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include #include #include #include namespace zen { /** * Storage Server Instance * * This class manages the lifecycle of a storage server instance, and * provides functions to query its state. There should be one instance * per module ID. */ class StorageServerInstance { public: struct Configuration { uint16_t BasePort; std::filesystem::path HydrationTempPath; std::string HydrationTargetSpecification; CbObject HydrationOptions; uint32_t HttpThreadCount = 0; // Automatic int CoreLimit = 0; // Automatic std::filesystem::path ConfigPath; }; StorageServerInstance(ZenServerEnvironment& RunEnvironment, const Configuration& Config, std::string_view ModuleId); ~StorageServerInstance(); inline std::string_view GetModuleId() const { return m_ModuleId; } inline uint16_t GetBasePort() const { return m_Config.BasePort; } ProcessMetrics GetProcessMetrics() const; #if ZEN_PLATFORM_WINDOWS void SetJobObject(JobObject* InJobObject) { m_JobObject = InJobObject; } #endif class SharedLockedPtr { public: SharedLockedPtr(const SharedLockedPtr&) = delete; SharedLockedPtr(); SharedLockedPtr(RwLock& Lock, StorageServerInstance* Instance, bool Wait); SharedLockedPtr(SharedLockedPtr&& Rhs); ~SharedLockedPtr(); SharedLockedPtr& operator=(const SharedLockedPtr&) = delete; SharedLockedPtr& operator =(SharedLockedPtr&& Rhs); operator bool() const { return m_Instance != nullptr; } std::string_view GetModuleId() const; uint16_t GetBasePort() const { ZEN_ASSERT(m_Instance); return m_Instance->GetBasePort(); } bool IsRunning() const; ProcessMetrics GetProcessMetrics() const { ZEN_ASSERT(m_Instance); return m_Instance->GetProcessMetrics(); } #if ZEN_WITH_TESTS void TerminateForTesting() const; // kills the child process to simulate a crash #endif private: RwLock* m_Lock = nullptr; StorageServerInstance* m_Instance = nullptr; }; [[nodiscard]] SharedLockedPtr LockShared(bool Wait) { return SharedLockedPtr(m_Lock, this, Wait); } class ExclusiveLockedPtr { public: ExclusiveLockedPtr(const ExclusiveLockedPtr&) = delete; ExclusiveLockedPtr(); ExclusiveLockedPtr(RwLock& Lock, StorageServerInstance* Instance, bool Wait); ExclusiveLockedPtr(ExclusiveLockedPtr&& Rhs); ~ExclusiveLockedPtr(); ExclusiveLockedPtr& operator=(const ExclusiveLockedPtr&) = delete; ExclusiveLockedPtr& operator =(ExclusiveLockedPtr&& Rhs); operator bool() const { return m_Instance != nullptr; } std::string_view GetModuleId() const; uint16_t GetBasePort() const { ZEN_ASSERT(m_Instance); return m_Instance->GetBasePort(); } bool IsRunning() const; void Provision(); void Deprovision(); void Hibernate(); void Wake(); private: RwLock* m_Lock = nullptr; StorageServerInstance* m_Instance = nullptr; }; [[nodiscard]] ExclusiveLockedPtr LockExclusive(bool Wait) { return ExclusiveLockedPtr(m_Lock, this, Wait); } private: void ProvisionLocked(); void DeprovisionLocked(); void HibernateLocked(); void WakeLocked(); mutable RwLock m_Lock; const Configuration m_Config; std::string m_ModuleId; ZenServerInstance m_ServerInstance; std::filesystem::path m_BaseDir; std::filesystem::path m_TempDir; #if ZEN_PLATFORM_WINDOWS JobObject* m_JobObject = nullptr; #endif void SpawnServerProcess(); void Hydrate(); void Dehydrate(); friend class SharedLockedPtr; friend class ExclusiveLockedPtr; }; } // namespace zen