aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/gc.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-10-18 21:53:59 +0200
committerGitHub <[email protected]>2023-10-18 21:53:59 +0200
commit6db4b4d1e023f4c17f12cb0915e0552f21d705f7 (patch)
treea380f15a653be4dc273eefaca1599467a7866b6e /src/zenstore/gc.cpp
parent0.2.28 (diff)
downloadzen-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.cpp112
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
{