aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/hub/storageserverinstance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenserver/hub/storageserverinstance.cpp')
-rw-r--r--src/zenserver/hub/storageserverinstance.cpp293
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