From 289d66d7b54f0560253a2a4eb27bf697ad62fa83 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Wed, 8 Apr 2026 13:51:46 +0200 Subject: hydration data obliteration (#923) - Feature: Hub obliterate operation deletes all local and backend hydration data for a module - Improvement: Hub dashboard adds obliterate button for individual, bulk, and by-name module deletion --- src/zenserver/hub/storageserverinstance.cpp | 71 ++++++++++++++++++----------- 1 file changed, 45 insertions(+), 26 deletions(-) (limited to 'src/zenserver/hub/storageserverinstance.cpp') diff --git a/src/zenserver/hub/storageserverinstance.cpp b/src/zenserver/hub/storageserverinstance.cpp index 6185a7f19..b31a64e56 100644 --- a/src/zenserver/hub/storageserverinstance.cpp +++ b/src/zenserver/hub/storageserverinstance.cpp @@ -16,8 +16,6 @@ StorageServerInstance::StorageServerInstance(ZenServerEnvironment& RunEnvironmen , m_ModuleId(ModuleId) , m_ServerInstance(RunEnvironment, ZenServerInstance::ServerMode::kStorageServer) { - m_BaseDir = RunEnvironment.CreateChildDir(ModuleId); - m_TempDir = Config.HydrationTempPath / ModuleId; } StorageServerInstance::~StorageServerInstance() @@ -31,7 +29,7 @@ StorageServerInstance::SpawnServerProcess() m_ServerInstance.ResetDeadProcess(); m_ServerInstance.SetServerExecutablePath(GetRunningExecutablePath()); - m_ServerInstance.SetDataDir(m_BaseDir); + m_ServerInstance.SetDataDir(m_Config.StateDir); #if ZEN_PLATFORM_WINDOWS m_ServerInstance.SetJobObject(m_JobObject); #endif @@ -77,7 +75,7 @@ StorageServerInstance::ProvisionLocked() return; } - ZEN_INFO("Provisioning storage server instance for module '{}', at '{}'", m_ModuleId, m_BaseDir); + ZEN_INFO("Provisioning storage server instance for module '{}', at '{}'", m_ModuleId, m_Config.StateDir); try { Hydrate(); @@ -87,7 +85,7 @@ StorageServerInstance::ProvisionLocked() { ZEN_WARN("Failed spawning server instance for module '{}', at '{}' during provisioning. Reason: {}", m_ModuleId, - m_BaseDir, + m_Config.StateDir, Ex.what()); throw; } @@ -116,6 +114,22 @@ StorageServerInstance::DeprovisionLocked() } } +void +StorageServerInstance::ObliterateLocked() +{ + if (m_ServerInstance.IsRunning()) + { + // m_ServerInstance.Shutdown() never throws. + m_ServerInstance.Shutdown(); + } + + std::atomic AbortFlag{false}; + std::atomic PauseFlag{false}; + HydrationConfig Config = MakeHydrationConfig(AbortFlag, PauseFlag); + std::unique_ptr Hydrator = CreateHydrator(Config); + Hydrator->Obliterate(); +} + void StorageServerInstance::HibernateLocked() { @@ -146,7 +160,10 @@ StorageServerInstance::WakeLocked() } catch (const std::exception& Ex) { - ZEN_WARN("Failed spawning server instance for module '{}', at '{}' during waking. Reason: {}", m_ModuleId, m_BaseDir, Ex.what()); + ZEN_WARN("Failed spawning server instance for module '{}', at '{}' during waking. Reason: {}", + m_ModuleId, + m_Config.StateDir, + Ex.what()); throw; } } @@ -154,20 +171,9 @@ StorageServerInstance::WakeLocked() void StorageServerInstance::Hydrate() { - std::atomic AbortFlag{false}; - std::atomic PauseFlag{false}; - - HydrationConfig Config{.ServerStateDir = m_BaseDir, - .TempDir = m_TempDir, - .ModuleId = m_ModuleId, - .TargetSpecification = m_Config.HydrationTargetSpecification, - .Options = m_Config.HydrationOptions}; - if (m_Config.OptionalWorkerPool) - { - Config.Threading.emplace( - HydrationConfig::ThreadingOptions{.WorkerPool = m_Config.OptionalWorkerPool, .AbortFlag = &AbortFlag, .PauseFlag = &PauseFlag}); - } - + std::atomic AbortFlag{false}; + std::atomic PauseFlag{false}; + HydrationConfig Config = MakeHydrationConfig(AbortFlag, PauseFlag); std::unique_ptr Hydrator = CreateHydrator(Config); m_HydrationState = Hydrator->Hydrate(); } @@ -175,11 +181,18 @@ StorageServerInstance::Hydrate() void StorageServerInstance::Dehydrate() { - std::atomic AbortFlag{false}; - std::atomic PauseFlag{false}; + std::atomic AbortFlag{false}; + std::atomic PauseFlag{false}; + HydrationConfig Config = MakeHydrationConfig(AbortFlag, PauseFlag); + std::unique_ptr Hydrator = CreateHydrator(Config); + Hydrator->Dehydrate(m_HydrationState); +} - HydrationConfig Config{.ServerStateDir = m_BaseDir, - .TempDir = m_TempDir, +HydrationConfig +StorageServerInstance::MakeHydrationConfig(std::atomic& AbortFlag, std::atomic& PauseFlag) +{ + HydrationConfig Config{.ServerStateDir = m_Config.StateDir, + .TempDir = m_Config.TempDir, .ModuleId = m_ModuleId, .TargetSpecification = m_Config.HydrationTargetSpecification, .Options = m_Config.HydrationOptions}; @@ -189,8 +202,7 @@ StorageServerInstance::Dehydrate() HydrationConfig::ThreadingOptions{.WorkerPool = m_Config.OptionalWorkerPool, .AbortFlag = &AbortFlag, .PauseFlag = &PauseFlag}); } - std::unique_ptr Hydrator = CreateHydrator(Config); - Hydrator->Dehydrate(m_HydrationState); + return Config; } StorageServerInstance::SharedLockedPtr::SharedLockedPtr() : m_Lock(nullptr), m_Instance(nullptr) @@ -358,6 +370,13 @@ StorageServerInstance::ExclusiveLockedPtr::Deprovision() m_Instance->DeprovisionLocked(); } +void +StorageServerInstance::ExclusiveLockedPtr::Obliterate() +{ + ZEN_ASSERT(m_Instance != nullptr); + m_Instance->ObliterateLocked(); +} + void StorageServerInstance::ExclusiveLockedPtr::Hibernate() { -- cgit v1.2.3