diff options
| author | Dan Engelbrecht <[email protected]> | 2023-10-18 21:53:59 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-18 21:53:59 +0200 |
| commit | 6db4b4d1e023f4c17f12cb0915e0552f21d705f7 (patch) | |
| tree | a380f15a653be4dc273eefaca1599467a7866b6e /src/zenstore/gc.cpp | |
| parent | 0.2.28 (diff) | |
| download | zen-6db4b4d1e023f4c17f12cb0915e0552f21d705f7.tar.xz zen-6db4b4d1e023f4c17f12cb0915e0552f21d705f7.zip | |
add `flush` command and more gc status info (#483)
- Feature: New endpoint `/admin/flush ` to flush all storage - CAS, Cache and ProjectStore
- Feature: New command `zen flush` to flush all storage - CAS, Cache and ProjectStore
- Improved: Command `zen gc-status` now gives details about storage, when last GC occured, how long until next GC etc
- Changed: Cache access and write log are disabled by default
Diffstat (limited to 'src/zenstore/gc.cpp')
| -rw-r--r-- | src/zenstore/gc.cpp | 112 |
1 files changed, 89 insertions, 23 deletions
diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp index 0f3f178d6..0e4c49f65 100644 --- a/src/zenstore/gc.cpp +++ b/src/zenstore/gc.cpp @@ -39,19 +39,6 @@ # include <random> #endif -template<> -struct fmt::formatter<zen::GcClock::TimePoint> : formatter<string_view> -{ - template<typename FormatContext> - auto format(const zen::GcClock::TimePoint& TimePoint, FormatContext& ctx) - { - std::time_t Time = std::chrono::system_clock::to_time_t(TimePoint); - char TimeString[std::size("yyyy-mm-ddThh:mm:ss")]; - std::strftime(std::data(TimeString), std::size(TimeString), "%FT%T", std::localtime(&Time)); - return fmt::format_to(ctx.out(), "{}", TimeString); - } -}; - namespace zen { using namespace std::literals; @@ -403,11 +390,13 @@ GcManager::ScrubStorage(ScrubContext& GcCtx) } } -void +GcStorageSize GcManager::CollectGarbage(GcContext& GcCtx) { ZEN_TRACE_CPU("Gc::CollectGarbage"); + GcStorageSize GCTotalSizeDiff; + RwLock::SharedLockScope _(m_Lock); // First gather reference set @@ -425,14 +414,13 @@ GcManager::CollectGarbage(GcContext& GcCtx) { ZEN_TRACE_CPU("Gc::CollectGarbage::CollectGarbage"); - GcStorageSize GCTotalSizeDiff; - Stopwatch Timer; - const auto Guard = MakeGuard([&] { - ZEN_INFO("collected garbage in {}. Removed {} disk space, {} memory", - NiceTimeSpanMs(Timer.GetElapsedTimeMs()), - NiceBytes(GCTotalSizeDiff.DiskSize), - NiceBytes(GCTotalSizeDiff.MemorySize)); - }); + Stopwatch Timer; + const auto Guard = MakeGuard([&] { + ZEN_INFO("collected garbage in {}. Removed {} disk space, {} memory", + NiceTimeSpanMs(Timer.GetElapsedTimeMs()), + NiceBytes(GCTotalSizeDiff.DiskSize), + NiceBytes(GCTotalSizeDiff.MemorySize)); + }); for (GcStorage* Storage : m_GcStorage) { const auto PreSize = Storage->StorageSize(); @@ -442,6 +430,7 @@ GcManager::CollectGarbage(GcContext& GcCtx) GCTotalSizeDiff.MemorySize += PreSize.MemorySize > PostSize.MemorySize ? PreSize.MemorySize - PostSize.MemorySize : 0; } } + return GCTotalSizeDiff; } GcStorageSize @@ -753,6 +742,70 @@ GcScheduler::CheckDiskSpace() return Space; } +GcSchedulerState +GcScheduler::GetState() const +{ + GcClock::TimePoint Now = GcClock::Now(); + + const GcStorageSize TotalSize = m_GcManager.TotalStorageSize(); + + GcSchedulerState Result{.Status = Status(), .Config = m_Config, .AreDiskWritesBlocked = m_AreDiskWritesBlocked.load()}; + + { + std::unique_lock Lock(m_GcMutex); + Result.LastFullGcTime = m_LastGcTime; + Result.LastFullGCDiff = m_LastFullGCDiff; + Result.LastLightweightGcTime = m_LastLightweightGcTime; + Result.LastLightweightGCDiff = m_LastLightweightGCDiff; + } + std::error_code Ec; + DiskSpace Space = DiskSpaceInfo(Result.Config.RootDirectory, Ec); + if (!Ec) + { + Result.DiskSize = Space.Total; + Result.DiskUsed = Space.Total - Space.Free; + Result.DiskFree = Space.Free; + if (Result.Config.DiskSizeSoftLimit != 0) + { + Result.RemainingSpaceUntilFullGC = + Result.Config.DiskSizeSoftLimit > TotalSize.DiskSize ? (Result.Config.DiskSizeSoftLimit - TotalSize.DiskSize) : 0; + } + } + if (Result.Config.DiskReserveSize != 0) + { + Ec.clear(); + Result.HasDiskReserve = std::filesystem::is_regular_file(Result.Config.RootDirectory / "reserve.gc", Ec) && !Ec; + } + + GcClock::TimePoint CacheExpireTime = + Result.Config.MaxCacheDuration == GcClock::Duration::max() ? GcClock::TimePoint::min() : Now - Result.Config.MaxCacheDuration; + GcClock::TimePoint ProjectStoreExpireTime = Result.Config.MaxProjectStoreDuration == GcClock::Duration::max() + ? GcClock::TimePoint::min() + : Now - Result.Config.MaxProjectStoreDuration; + + Result.RemainingTimeUntilFullGc = + Result.Config.Interval.count() == 0 + ? std::chrono::seconds::max() + : std::chrono::duration_cast<std::chrono::seconds>(Result.LastFullGcTime + Result.Config.Interval - Now); + + if (Result.RemainingTimeUntilFullGc < std::chrono::seconds::zero()) + { + Result.RemainingTimeUntilFullGc = std::chrono::seconds::zero(); + } + + Result.RemainingTimeUntilLightweightGc = + Result.Config.LightweightInterval.count() == 0 + ? std::chrono::seconds::max() + : std::chrono::duration_cast<std::chrono::seconds>(Result.LastLightweightGcTime + Result.Config.LightweightInterval - Now); + + if (Result.RemainingTimeUntilLightweightGc < std::chrono::seconds::zero()) + { + Result.RemainingTimeUntilLightweightGc = std::chrono::seconds::zero(); + } + + return Result; +} + void GcScheduler::SchedulerThread() { @@ -1159,11 +1212,24 @@ GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime, Stopwatch Timer; const auto __ = MakeGuard([&] { ZEN_INFO("garbage collection DONE in {}", NiceTimeSpanMs(Timer.GetElapsedTimeMs())); }); - m_GcManager.CollectGarbage(GcCtx); + GcStorageSize Diff = m_GcManager.CollectGarbage(GcCtx); if (SkipCid) { m_LastLightweightGcTime = GcClock::Now(); + + std::chrono::seconds ElapsedSeconds = + std::chrono::duration_cast<std::chrono::seconds>(std::chrono::milliseconds(Timer.GetElapsedTimeMs())); + if (SkipCid) + { + m_LastLightweightGcDuration = ElapsedSeconds; + m_LastLightweightGCDiff = Diff; + } + else + { + m_LastFullGcDuration = ElapsedSeconds; + m_LastFullGCDiff = Diff; + } } else { |