diff options
Diffstat (limited to 'src/zenserver/hub/storageserverinstance.cpp')
| -rw-r--r-- | src/zenserver/hub/storageserverinstance.cpp | 293 |
1 files changed, 243 insertions, 50 deletions
diff --git a/src/zenserver/hub/storageserverinstance.cpp b/src/zenserver/hub/storageserverinstance.cpp index c54322683..bab501429 100644 --- a/src/zenserver/hub/storageserverinstance.cpp +++ b/src/zenserver/hub/storageserverinstance.cpp @@ -57,72 +57,82 @@ StorageServerInstance::SpawnServerProcess() } void -StorageServerInstance::Provision() +StorageServerInstance::GetProcessMetrics(ProcessMetrics& OutMetrics) const { - RwLock::ExclusiveLockScope _(m_Lock); + OutMetrics.MemoryBytes = m_MemoryBytes.load(); + OutMetrics.KernelTimeMs = m_KernelTimeMs.load(); + OutMetrics.UserTimeMs = m_UserTimeMs.load(); + OutMetrics.WorkingSetSize = m_WorkingSetSize.load(); + OutMetrics.PeakWorkingSetSize = m_PeakWorkingSetSize.load(); + OutMetrics.PagefileUsage = m_PagefileUsage.load(); + OutMetrics.PeakPagefileUsage = m_PeakPagefileUsage.load(); +} - if (m_IsProvisioned) +void +StorageServerInstance::ProvisionLocked() +{ + if (m_State.load() == HubInstanceState::Provisioned) { ZEN_WARN("Storage server instance for module '{}' is already provisioned", m_ModuleId); - return; } - if (m_IsHibernated) + if (m_State.load() == HubInstanceState::Hibernated) { - WakeLocked(); + if (WakeLocked()) + { + return; + } + // Wake failed; proceed with a fresh provision (discards hibernated data) + m_State = HubInstanceState::Unprovisioned; } - else + else if (m_State.load() != HubInstanceState::Unprovisioned) { - ZEN_INFO("Provisioning storage server instance for module '{}', at '{}'", m_ModuleId, m_BaseDir); - - Hydrate(); - - SpawnServerProcess(); + ZEN_WARN("Storage server instance for module '{}' is in unexpected state '{}', cannot provision", + m_ModuleId, + ToString(m_State.load())); + return; } - m_IsProvisioned = true; + ZEN_INFO("Provisioning storage server instance for module '{}', at '{}'", m_ModuleId, m_BaseDir); + + m_State = HubInstanceState::Provisioning; + Hydrate(); + SpawnServerProcess(); + m_State = HubInstanceState::Provisioned; } void -StorageServerInstance::Deprovision() +StorageServerInstance::DeprovisionLocked() { - RwLock::ExclusiveLockScope _(m_Lock); - - if (!m_IsProvisioned) + if (m_State.load() != HubInstanceState::Provisioned) { - ZEN_WARN("Attempted to deprovision storage server instance for module '{}' which is not provisioned", m_ModuleId); - + ZEN_WARN("Attempted to deprovision storage server instance for module '{}' which is not provisioned (state: '{}')", + m_ModuleId, + ToString(m_State.load())); return; } ZEN_INFO("Deprovisioning storage server instance for module '{}'", m_ModuleId); + m_State = HubInstanceState::Deprovisioning; m_ServerInstance.Shutdown(); Dehydrate(); - m_IsProvisioned = false; + m_State = HubInstanceState::Unprovisioned; } void -StorageServerInstance::Hibernate() +StorageServerInstance::HibernateLocked() { // Signal server to shut down, but keep data around for later wake - RwLock::ExclusiveLockScope _(m_Lock); - - if (!m_IsProvisioned) - { - ZEN_WARN("Attempted to hibernate storage server instance for module '{}' which is not provisioned", m_ModuleId); - - return; - } - - if (m_IsHibernated) + if (m_State.load() != HubInstanceState::Provisioned) { - ZEN_WARN("Storage server instance for module '{}' is already hibernated", m_ModuleId); - + ZEN_WARN("Attempted to hibernate storage server instance for module '{}' which is not provisioned (state: '{}')", + m_ModuleId, + ToString(m_State.load())); return; } @@ -135,52 +145,46 @@ StorageServerInstance::Hibernate() return; } + m_State = HubInstanceState::Hibernating; try { m_ServerInstance.Shutdown(); - - m_IsHibernated = true; - m_IsProvisioned = false; - + m_State = HubInstanceState::Hibernated; return; } catch (const std::exception& Ex) { ZEN_ERROR("Failed to hibernate storage server instance for module '{}': {}", m_ModuleId, Ex.what()); + m_State = HubInstanceState::Provisioned; // Shutdown failed; instance is still running } } -void -StorageServerInstance::Wake() -{ - RwLock::ExclusiveLockScope _(m_Lock); - WakeLocked(); -} - -void +bool StorageServerInstance::WakeLocked() { // Start server in-place using existing data - if (!m_IsHibernated) + if (m_State.load() != HubInstanceState::Hibernated) { ZEN_WARN("Attempted to wake storage server instance for module '{}' which is not hibernated", m_ModuleId); - return; + return true; // Instance is already usable (noop success) } ZEN_ASSERT_FORMAT(!m_ServerInstance.IsRunning(), "Storage server instance for module '{}' is already running", m_ModuleId); + m_State = HubInstanceState::Waking; try { SpawnServerProcess(); - m_IsHibernated = false; + m_State = HubInstanceState::Provisioned; + return true; } catch (const std::exception& Ex) { ZEN_ERROR("Failed to wake storage server instance for module '{}': {}", m_ModuleId, Ex.what()); - - // TODO: this instance should be marked as invalid + m_State = HubInstanceState::Hibernated; + return false; } } @@ -210,4 +214,193 @@ StorageServerInstance::Dehydrate() Hydrator->Dehydrate(); } +StorageServerInstance::SharedLockedPtr::SharedLockedPtr() : m_Lock(nullptr), m_Instance(nullptr) +{ +} + +StorageServerInstance::SharedLockedPtr::SharedLockedPtr(RwLock& Lock, StorageServerInstance* Instance, bool Wait) +: m_Lock(nullptr) +, m_Instance(nullptr) +{ + ZEN_ASSERT(Instance != nullptr); + if (Wait) + { + Lock.AcquireShared(); + m_Lock = &Lock; + m_Instance = Instance; + } + else + { + if (Lock.TryAcquireShared()) + { + m_Lock = &Lock; + m_Instance = Instance; + } + } +} + +StorageServerInstance::SharedLockedPtr::SharedLockedPtr(SharedLockedPtr&& Rhs) : m_Lock(Rhs.m_Lock), m_Instance(Rhs.m_Instance) +{ + Rhs.m_Lock = nullptr; + Rhs.m_Instance = nullptr; +} + +StorageServerInstance::SharedLockedPtr::~SharedLockedPtr() +{ + if (m_Lock != nullptr) + { + m_Lock->ReleaseShared(); + m_Lock = nullptr; + } + m_Instance = nullptr; +} + +StorageServerInstance::SharedLockedPtr& +StorageServerInstance::SharedLockedPtr::operator=(SharedLockedPtr&& Rhs) +{ + if (m_Lock) + { + m_Lock->ReleaseShared(); + m_Lock = nullptr; + m_Instance = nullptr; + } + m_Lock = Rhs.m_Lock; + m_Instance = Rhs.m_Instance; + Rhs.m_Lock = nullptr; + Rhs.m_Instance = nullptr; + return *this; +} + +std::string_view +StorageServerInstance::SharedLockedPtr::GetModuleId() const +{ + ZEN_ASSERT(m_Instance != nullptr); + return m_Instance->m_ModuleId; +} + +bool +StorageServerInstance::SharedLockedPtr::IsRunning() const +{ + ZEN_ASSERT(m_Instance != nullptr); + return m_Instance->m_State.load() == HubInstanceState::Provisioned && m_Instance->m_ServerInstance.IsRunning(); +} + +void +StorageServerInstance::UpdateMetricsLocked() +{ + if (m_State.load() == HubInstanceState::Provisioned) + { + ProcessMetrics Metrics; + zen::GetProcessMetrics(m_ServerInstance.GetProcessHandle(), Metrics); + + m_MemoryBytes.store(Metrics.MemoryBytes); + m_KernelTimeMs.store(Metrics.KernelTimeMs); + m_UserTimeMs.store(Metrics.UserTimeMs); + m_WorkingSetSize.store(Metrics.WorkingSetSize); + m_PeakWorkingSetSize.store(Metrics.PeakWorkingSetSize); + m_PagefileUsage.store(Metrics.PagefileUsage); + m_PeakPagefileUsage.store(Metrics.PeakPagefileUsage); + } + // TODO: Resource metrics... +} + +StorageServerInstance::ExclusiveLockedPtr::ExclusiveLockedPtr() : m_Lock(nullptr), m_Instance(nullptr) +{ +} + +StorageServerInstance::ExclusiveLockedPtr::ExclusiveLockedPtr(RwLock& Lock, StorageServerInstance* Instance, bool Wait) +: m_Lock(nullptr) +, m_Instance(nullptr) +{ + ZEN_ASSERT(Instance != nullptr); + if (Wait) + { + Lock.AcquireExclusive(); + m_Lock = &Lock; + m_Instance = Instance; + } + else + { + if (Lock.TryAcquireExclusive()) + { + m_Lock = &Lock; + m_Instance = Instance; + } + } +} + +StorageServerInstance::ExclusiveLockedPtr::ExclusiveLockedPtr(ExclusiveLockedPtr&& Rhs) : m_Lock(Rhs.m_Lock), m_Instance(Rhs.m_Instance) +{ + Rhs.m_Lock = nullptr; + Rhs.m_Instance = nullptr; +} + +StorageServerInstance::ExclusiveLockedPtr::~ExclusiveLockedPtr() +{ + if (m_Lock != nullptr) + { + m_Lock->ReleaseExclusive(); + m_Lock = nullptr; + } + m_Instance = nullptr; +} + +StorageServerInstance::ExclusiveLockedPtr& +StorageServerInstance::ExclusiveLockedPtr::operator=(ExclusiveLockedPtr&& Rhs) +{ + if (m_Lock) + { + m_Lock->ReleaseExclusive(); + m_Lock = nullptr; + m_Instance = nullptr; + } + m_Lock = Rhs.m_Lock; + m_Instance = Rhs.m_Instance; + Rhs.m_Lock = nullptr; + Rhs.m_Instance = nullptr; + return *this; +} + +std::string_view +StorageServerInstance::ExclusiveLockedPtr::GetModuleId() const +{ + ZEN_ASSERT(m_Instance != nullptr); + return m_Instance->m_ModuleId; +} + +bool +StorageServerInstance::ExclusiveLockedPtr::IsRunning() const +{ + ZEN_ASSERT(m_Instance != nullptr); + return m_Instance->m_State.load() == HubInstanceState::Provisioned && m_Instance->m_ServerInstance.IsRunning(); +} + +void +StorageServerInstance::ExclusiveLockedPtr::Provision() +{ + ZEN_ASSERT(m_Instance != nullptr); + m_Instance->ProvisionLocked(); +} + +void +StorageServerInstance::ExclusiveLockedPtr::Deprovision() +{ + ZEN_ASSERT(m_Instance != nullptr); + m_Instance->DeprovisionLocked(); +} + +void +StorageServerInstance::ExclusiveLockedPtr::Hibernate() +{ + ZEN_ASSERT(m_Instance != nullptr); + m_Instance->HibernateLocked(); +} + +bool +StorageServerInstance::ExclusiveLockedPtr::Wake() +{ + ZEN_ASSERT(m_Instance != nullptr); + return m_Instance->WakeLocked(); +} + } // namespace zen |