diff options
| author | Dan Engelbrecht <[email protected]> | 2023-10-02 10:58:47 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-02 10:58:47 +0200 |
| commit | 3259b5a7f90f374ea75af469f07a29020d6c9c2d (patch) | |
| tree | 3437f75b24c531905cf4b4ce5957d685ce3c2e08 /src | |
| parent | Sentry username fix (#435) (diff) | |
| download | zen-3259b5a7f90f374ea75af469f07a29020d6c9c2d.tar.xz zen-3259b5a7f90f374ea75af469f07a29020d6c9c2d.zip | |
lightweight gc (#431)
- Feature: Add lightweight GC that only removes items from cache/project store without cleaning up data referenced in Cid store
- Add `skipcid` parameter to http endpoint `admin/gc`, defaults to "false"
- Add `--skipcid` option to `zen gc` command, defaults to false
- Add `--gc-lightweight-interval-seconds` option to zenserver
Diffstat (limited to 'src')
| -rw-r--r-- | src/zen/cmds/admin_cmd.cpp | 5 | ||||
| -rw-r--r-- | src/zen/cmds/admin_cmd.h | 1 | ||||
| -rw-r--r-- | src/zenserver/admin/admin.cpp | 5 | ||||
| -rw-r--r-- | src/zenserver/cache/cachedisklayer.cpp | 5 | ||||
| -rw-r--r-- | src/zenserver/config.cpp | 10 | ||||
| -rw-r--r-- | src/zenserver/config.h | 1 | ||||
| -rw-r--r-- | src/zenserver/projectstore/projectstore.cpp | 4 | ||||
| -rw-r--r-- | src/zenserver/zenserver.cpp | 8 | ||||
| -rw-r--r-- | src/zenstore/compactcas.cpp | 5 | ||||
| -rw-r--r-- | src/zenstore/filecas.cpp | 5 | ||||
| -rw-r--r-- | src/zenstore/gc.cpp | 188 | ||||
| -rw-r--r-- | src/zenstore/include/zenstore/gc.h | 27 |
12 files changed, 204 insertions, 60 deletions
diff --git a/src/zen/cmds/admin_cmd.cpp b/src/zen/cmds/admin_cmd.cpp index b48207bec..9d8348b43 100644 --- a/src/zen/cmds/admin_cmd.cpp +++ b/src/zen/cmds/admin_cmd.cpp @@ -74,6 +74,7 @@ GcCommand::GcCommand() "Collect small objects", cxxopts::value(m_SmallObjects)->default_value("false"), "<smallobjects>"); + m_Options.add_option("", "", "skipcid", "Skip collection of CAS data", cxxopts::value(m_SkipCid)->default_value("false"), "<skipcid>"); m_Options.add_option("", "m", "maxcacheduration", @@ -122,6 +123,10 @@ GcCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { Params.Add({"disksizesoftlimit", fmt::format("{}", m_DiskSizeSoftLimit)}); } + if (m_SkipCid) + { + Params.Add({"skipcid", "true"}); + } cpr::Session Session; Session.SetHeader(cpr::Header{{"Accept", "application/json"}}); diff --git a/src/zen/cmds/admin_cmd.h b/src/zen/cmds/admin_cmd.h index 873c230d9..af375e91b 100644 --- a/src/zen/cmds/admin_cmd.h +++ b/src/zen/cmds/admin_cmd.h @@ -37,6 +37,7 @@ private: cxxopts::Options m_Options{"gc", "Garbage collect zen storage"}; std::string m_HostName; bool m_SmallObjects{false}; + bool m_SkipCid{false}; uint64_t m_MaxCacheDuration{0}; uint64_t m_DiskSizeSoftLimit{0}; }; diff --git a/src/zenserver/admin/admin.cpp b/src/zenserver/admin/admin.cpp index 083086f50..89dae25af 100644 --- a/src/zenserver/admin/admin.cpp +++ b/src/zenserver/admin/admin.cpp @@ -228,6 +228,11 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler, } } + if (auto Param = Params.GetValue("skipcid"); Param.empty() == false) + { + GcParams.SkipCid = Param == "true"sv; + } + const bool Started = m_GcScheduler.TriggerGc(GcParams); CbObjectWriter Response; diff --git a/src/zenserver/cache/cachedisklayer.cpp b/src/zenserver/cache/cachedisklayer.cpp index 3cee3197b..d53d3f3f4 100644 --- a/src/zenserver/cache/cachedisklayer.cpp +++ b/src/zenserver/cache/cachedisklayer.cpp @@ -1197,6 +1197,11 @@ ZenCacheDiskLayer::CacheBucket::GatherReferences(GcContext& GcCtx) continue; } + if (GcCtx.SkipCid()) + { + continue; + } + const DiskLocation& Loc = Payloads[Entry.second].Location; if (Loc.IsFlagSet(DiskLocation::kStructured)) diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index 64acdfe73..6daf7fe1c 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -920,6 +920,9 @@ ParseConfigFile(const std::filesystem::path& Path, LuaOptions.AddOption("gc.lowdiskspacethreshold"sv, ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites, "gc-low-diskspace-threshold"sv); + LuaOptions.AddOption("gc.lightweightntervalseconds"sv, + ServerOptions.GcConfig.LightweightIntervalSeconds, + "gc-lightweight-interval-seconds"sv); ////// gc LuaOptions.AddOption("gc.cache.maxdurationseconds"sv, ServerOptions.GcConfig.Cache.MaxDurationSeconds, "gc-cache-duration-seconds"sv); @@ -1358,6 +1361,13 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) options.add_option("gc", "", + "gc-lightweight-interval-seconds", + "Lightweight garbage collection interval in seconds. Default set to 900 (30 min).", + cxxopts::value<int32_t>(ServerOptions.GcConfig.LightweightIntervalSeconds)->default_value("900"), + ""); + + options.add_option("gc", + "", "gc-cache-duration-seconds", "Max duration in seconds before Z$ entries get evicted. Default set to 1209600 (2 weeks)", cxxopts::value<int32_t>(ServerOptions.GcConfig.Cache.MaxDurationSeconds)->default_value("1209600"), diff --git a/src/zenserver/config.h b/src/zenserver/config.h index f5438489d..bb6e20bb6 100644 --- a/src/zenserver/config.h +++ b/src/zenserver/config.h @@ -89,6 +89,7 @@ struct ZenGcConfig bool Enabled = true; uint64_t DiskReserveSize = 1ul << 28; uint64_t DiskSizeSoftLimit = 0; + int32_t LightweightIntervalSeconds = 0; uint64_t MinimumFreeDiskSpaceToAllowWrites = 1ul << 28; }; diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index 70dc678a9..4ddbdded7 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -502,6 +502,10 @@ void ProjectStore::Oplog::GatherReferences(GcContext& GcCtx) { ZEN_TRACE_CPU("Store::Oplog::GatherReferences"); + if (GcCtx.SkipCid()) + { + return; + } tsl::robin_set<IoHash> AttachmentHashes; IterateOplog([&](CbObject Op) { diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index fa7694573..e4143dc01 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -449,7 +449,10 @@ public: m_VfsService->AddService(Ref<ZenCacheStore>(m_CacheStore)); m_Http->RegisterService(*m_VfsService); - ZEN_INFO("initializing GC, enabled '{}', interval {}s", ServerOptions.GcConfig.Enabled, ServerOptions.GcConfig.IntervalSeconds); + ZEN_INFO("initializing GC, enabled '{}', interval {}s, lightweight interval {}s", + ServerOptions.GcConfig.Enabled, + ServerOptions.GcConfig.IntervalSeconds, + ServerOptions.GcConfig.LightweightIntervalSeconds); zen::GcSchedulerConfig GcConfig{ .RootDirectory = m_DataRoot / "gc", .MonitorInterval = std::chrono::seconds(ServerOptions.GcConfig.MonitorIntervalSeconds), @@ -460,7 +463,8 @@ public: .Enabled = ServerOptions.GcConfig.Enabled, .DiskReserveSize = ServerOptions.GcConfig.DiskReserveSize, .DiskSizeSoftLimit = ServerOptions.GcConfig.DiskSizeSoftLimit, - .MinimumFreeDiskSpaceToAllowWrites = ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites}; + .MinimumFreeDiskSpaceToAllowWrites = ServerOptions.GcConfig.MinimumFreeDiskSpaceToAllowWrites, + .LightweightInterval = std::chrono::seconds(ServerOptions.GcConfig.LightweightIntervalSeconds)}; m_GcScheduler.Initialize(GcConfig); // Create and register admin interface last to make sure all is properly initialized diff --git a/src/zenstore/compactcas.cpp b/src/zenstore/compactcas.cpp index 63158f6de..a138e43e9 100644 --- a/src/zenstore/compactcas.cpp +++ b/src/zenstore/compactcas.cpp @@ -388,6 +388,11 @@ CasContainerStrategy::CollectGarbage(GcContext& GcCtx) { ZEN_TRACE_CPU("CasContainer::CollectGarbage"); + if (GcCtx.SkipCid()) + { + return; + } + // It collects all the blocks that we want to delete chunks from. For each such // block we keep a list of chunks to retain and a list of chunks to delete. // diff --git a/src/zenstore/filecas.cpp b/src/zenstore/filecas.cpp index ce0dd7ce6..c3dce2b7b 100644 --- a/src/zenstore/filecas.cpp +++ b/src/zenstore/filecas.cpp @@ -897,6 +897,11 @@ FileCasStrategy::CollectGarbage(GcContext& GcCtx) ZEN_ASSERT(m_IsInitialized); + if (GcCtx.SkipCid()) + { + return; + } + ZEN_DEBUG("collecting garbage from {}", m_RootDirectory); std::vector<IoHash> ChunksToDelete; diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp index a3282dde6..f8ef5de82 100644 --- a/src/zenstore/gc.cpp +++ b/src/zenstore/gc.cpp @@ -196,6 +196,7 @@ struct GcContext::GcState GcClock::TimePoint m_ProjectStoreExpireTime; bool m_DeletionMode = true; bool m_CollectSmallObjects = false; + bool m_SkipCid = false; std::filesystem::path DiskReservePath; }; @@ -260,6 +261,18 @@ GcContext::ExpiredCacheKeys(const std::string& CacheKeyContext) const } bool +GcContext::SkipCid() const +{ + return m_State->m_SkipCid; +} + +void +GcContext::SetSkipCid(bool NewState) +{ + m_State->m_SkipCid = NewState; +} + +bool GcContext::IsDeletionMode() const { return m_State->m_DeletionMode; @@ -591,6 +604,11 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config) m_Config.Interval = m_Config.MonitorInterval; } + if (m_Config.LightweightInterval.count() && m_Config.LightweightInterval < m_Config.MonitorInterval) + { + m_Config.LightweightInterval = m_Config.MonitorInterval; + } + std::filesystem::create_directories(Config.RootDirectory); std::error_code Ec = CreateGCReserve(m_Config.RootDirectory / "reserve.gc", m_Config.DiskReserveSize); @@ -604,8 +622,9 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config) CheckDiskSpace(); - m_LastGcTime = GcClock::Now(); - m_LastGcExpireTime = GcClock::TimePoint::min(); + m_LastGcTime = GcClock::Now(); + m_LastLightweightGcTime = m_LastGcTime; + m_LastGcExpireTime = GcClock::TimePoint::min(); if (CbObject SchedulerState = LoadCompactBinaryObject(Config.RootDirectory / "gc_state")) { @@ -615,7 +634,8 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config) if (m_LastGcTime + m_Config.Interval < GcClock::Now()) { // TODO: Trigger GC? - m_LastGcTime = GcClock::Now(); + m_LastGcTime = GcClock::Now(); + m_LastLightweightGcTime = m_LastGcTime; } } @@ -631,8 +651,7 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config) }, 0); - m_NextGcTime = NextGcTime(m_LastGcTime); - m_GcThread = std::thread(&GcScheduler::SchedulerThread, this); + m_GcThread = std::thread(&GcScheduler::SchedulerThread, this); } void @@ -773,10 +792,17 @@ GcScheduler::SchedulerThread() std::chrono::seconds ScrubTimeslice = std::chrono::seconds::max(); bool DoDelete = true; bool CollectSmallObjects = m_Config.CollectSmallObjects; + std::chrono::seconds GcInterval = m_Config.Interval; + std::chrono::seconds LightwightGcInterval = m_Config.LightweightInterval; std::chrono::seconds MaxCacheDuration = m_Config.MaxCacheDuration; std::chrono::seconds MaxProjectStoreDuration = m_Config.MaxProjectStoreDuration; uint64_t DiskSizeSoftLimit = m_Config.DiskSizeSoftLimit; - GcClock::TimePoint Now = GcClock::Now(); + bool SkipCid = false; + + bool DiskSpaceGCTriggered = false; + bool TimeBasedGCTriggered = false; + + GcClock::TimePoint Now = GcClock::Now(); if (m_TriggerGcParams) { @@ -797,6 +823,10 @@ GcScheduler::SchedulerThread() { DiskSizeSoftLimit = TriggerParams.DiskSizeSoftLimit; } + if (TriggerParams.SkipCid) + { + SkipCid = true; + } } if (m_TriggerScrubParams) @@ -859,7 +889,7 @@ GcScheduler::SchedulerThread() LoadGraph.resize(DiskDeltas.size(), '0'); if (DiskDeltas.size() > 0 && MaxLoad > 0) { - char LoadIndicator[11] = "0123456789"; + static const char LoadIndicator[11] = "0123456789"; for (size_t Index = 0; Index < DiskDeltas.size(); ++Index) { size_t LoadIndex = (9 * DiskDeltas[Index] + MaxLoad - 1) / MaxLoad; @@ -884,48 +914,114 @@ GcScheduler::SchedulerThread() } } - const bool DiskSpaceGCTriggered = GcDiskSpaceGoal > 0; + std::chrono::seconds RemaingTimeUntilGc = + GcInterval.count() == 0 ? std::chrono::seconds::max() + : std::chrono::duration_cast<std::chrono::seconds>(m_LastGcTime + GcInterval - GcClock::Now()); + if (RemaingTimeUntilGc < std::chrono::seconds::zero()) + { + RemaingTimeUntilGc = std::chrono::seconds::zero(); + } + std::chrono::seconds RemaingTimeUntilLightweightGc = + LightwightGcInterval.count() == 0 + ? std::chrono::seconds::max() + : std::chrono::duration_cast<std::chrono::seconds>(m_LastLightweightGcTime + LightwightGcInterval - GcClock::Now()); + if (RemaingTimeUntilLightweightGc < std::chrono::seconds::zero()) + { + RemaingTimeUntilLightweightGc = std::chrono::seconds::zero(); + } - std::chrono::seconds RemaingTime = std::chrono::duration_cast<std::chrono::seconds>(m_NextGcTime - GcClock::Now()); + if (GcDiskSpaceGoal > 0) + { + DiskSpaceGCTriggered = true; + } + else if (RemaingTimeUntilGc.count() == 0) + { + TimeBasedGCTriggered = true; + } + else if (RemaingTimeUntilLightweightGc.count() == 0) + { + TimeBasedGCTriggered = true; + SkipCid = true; + } - if (RemaingTime < std::chrono::seconds::zero()) + std::string NextTriggerStatus; + if (GcInterval.count() != 0 || LightwightGcInterval.count() != 0 || DiskSizeSoftLimit != 0) { - RemaingTime = std::chrono::seconds::zero(); + ExtendableStringBuilder<256> Sb; + if (DiskSpaceGCTriggered) + { + Sb.Append(fmt::format(" Disk space exceeds {}, trying to reclaim {}.", + NiceBytes(DiskSizeSoftLimit), + NiceBytes(GcDiskSpaceGoal))); + } + else if (TimeBasedGCTriggered) + { + if (SkipCid) + { + Sb.Append(fmt::format(" Lightweight GC schedule triggered.")); + } + else + { + Sb.Append(fmt::format(" GC schedule triggered.")); + } + } + else + { + if (GcInterval.count() != 0) + { + Sb.Append(fmt::format(" Full GC in {}.", + NiceTimeSpanMs(uint64_t(std::chrono::milliseconds(RemaingTimeUntilGc).count())))); + } + if (LightwightGcInterval.count() != 0) + { + Sb.Append( + fmt::format(" Lightweight GC in {}.", + NiceTimeSpanMs(uint64_t(std::chrono::milliseconds(RemaingTimeUntilLightweightGc).count())))); + } + if (DiskSizeSoftLimit != 0 && DiskSizeSoftLimit > TotalSize.DiskSize) + { + Sb.Append(fmt::format(" Disk usagage GC in {}.", NiceBytes(DiskSizeSoftLimit - TotalSize.DiskSize))); + } + } + NextTriggerStatus = Sb; } - bool TimeBasedGCTriggered = !DiskSpaceGCTriggered && RemaingTime.count() == 0; ZEN_INFO( - "{} in use,{} {} of total {} free disk space, disk writes last {} per {} [{}], peak {}/s. {}", + "{} used{}. '{}': {} in use, {} free. Disk writes last {} per {} [{}], peak {}/s.{}", NiceBytes(TotalSize.DiskSize), - DiskSizeSoftLimit == 0 ? "" : fmt::format(" {} soft limit,", NiceBytes(DiskSizeSoftLimit)), + DiskSizeSoftLimit == 0 ? "" : fmt::format(", {} soft limit", NiceBytes(DiskSizeSoftLimit)), + m_Config.RootDirectory, NiceBytes(Space.Free), NiceBytes(Space.Total), NiceTimeSpanMs(uint64_t(std::chrono::milliseconds(LoadGraphTime).count())), NiceTimeSpanMs(uint64_t(std::chrono::milliseconds(LoadGraphTime).count() / PressureGraphLength)), LoadGraph, NiceBytes(MaxLoad * uint64_t(std::chrono::seconds(1).count()) / uint64_t(std::chrono::seconds(LoadGraphTime).count())), - DiskSpaceGCTriggered ? fmt::format("Disk use threshold triggered, trying to reclaim {}. ", NiceBytes(GcDiskSpaceGoal)) - : TimeBasedGCTriggered ? "GC schedule triggered." - : m_NextGcTime == GcClock::TimePoint::max() - ? "" - : fmt::format("{} until next scheduled GC.", - NiceTimeSpanMs(uint64_t(std::chrono::milliseconds(RemaingTime).count())))); + NextTriggerStatus); if (!DiskSpaceGCTriggered && !TimeBasedGCTriggered) { - WaitTime = m_Config.MonitorInterval < RemaingTime ? m_Config.MonitorInterval : RemaingTime; + WaitTime = m_Config.MonitorInterval; + if (RemaingTimeUntilGc < WaitTime) + { + WaitTime = RemaingTimeUntilGc; + } + if (RemaingTimeUntilLightweightGc < WaitTime) + { + WaitTime = RemaingTimeUntilLightweightGc; + } continue; } - WaitTime = m_Config.MonitorInterval; uint32_t IdleState = static_cast<uint32_t>(GcSchedulerStatus::kIdle); if (!m_Status.compare_exchange_strong(IdleState, static_cast<uint32_t>(GcSchedulerStatus::kRunning))) { + WaitTime = m_Config.MonitorInterval; continue; } } - CollectGarbage(CacheExpireTime, ProjectStoreExpireTime, DoDelete, CollectSmallObjects); + CollectGarbage(CacheExpireTime, ProjectStoreExpireTime, DoDelete, CollectSmallObjects, SkipCid); uint32_t RunningState = static_cast<uint32_t>(GcSchedulerStatus::kRunning); if (!m_Status.compare_exchange_strong(RunningState, static_cast<uint32_t>(GcSchedulerStatus::kIdle))) @@ -933,26 +1029,14 @@ GcScheduler::SchedulerThread() ZEN_ASSERT(m_Status == static_cast<uint32_t>(GcSchedulerStatus::kStopped)); break; } + + WaitTime = std::chrono::seconds(0); } catch (std::exception& Ex) { ZEN_ERROR("scheduling garbage collection failed with: '{}'", Ex.what()); + WaitTime = m_Config.MonitorInterval; } - - WaitTime = m_Config.MonitorInterval; - } -} - -GcClock::TimePoint -GcScheduler::NextGcTime(GcClock::TimePoint CurrentTime) -{ - if (m_Config.Interval.count()) - { - return CurrentTime + m_Config.Interval; - } - else - { - return GcClock::TimePoint::max(); } } @@ -990,12 +1074,14 @@ void GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime, const GcClock::TimePoint& ProjectStoreExpireTime, bool Delete, - bool CollectSmallObjects) + bool CollectSmallObjects, + bool SkipCid) { ZEN_TRACE_CPU("GcScheduler::CollectGarbage"); GcContext GcCtx(CacheExpireTime, ProjectStoreExpireTime); GcCtx.SetDeletionMode(Delete); + GcCtx.SetSkipCid(SkipCid); GcCtx.CollectSmallObjects(CollectSmallObjects); GcCtx.DiskReservePath(m_Config.RootDirectory / "reserve.gc"); @@ -1027,8 +1113,9 @@ GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime, } } - ZEN_INFO("garbage collection STARTING, small objects gc {}, cache cutoff time {}, project store cutoff time {}", + ZEN_INFO("garbage collection STARTING, small objects gc {}, CAS. Cache cutoff time {}, project store cutoff time {}", GcCtx.CollectSmallObjects() ? "ENABLED"sv : "DISABLED"sv, + SkipCid ? "skip"sv : "include"sv, CacheExpireTime, ProjectStoreExpireTime); { @@ -1037,16 +1124,23 @@ GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime, m_GcManager.CollectGarbage(GcCtx); - if (Delete) + if (SkipCid) { - GcClock::TimePoint KeepRangeStart = Min(CacheExpireTime, ProjectStoreExpireTime); - m_LastGcExpireTime = KeepRangeStart; - std::unique_lock Lock(m_GcMutex); - m_DiskUsageWindow.KeepRange(KeepRangeStart.time_since_epoch().count(), GcClock::Duration::max().count()); + m_LastLightweightGcTime = GcClock::Now(); } + else + { + if (Delete) + { + GcClock::TimePoint KeepRangeStart = Min(CacheExpireTime, ProjectStoreExpireTime); + m_LastGcExpireTime = KeepRangeStart; + std::unique_lock Lock(m_GcMutex); + m_DiskUsageWindow.KeepRange(KeepRangeStart.time_since_epoch().count(), GcClock::Duration::max().count()); + } - m_LastGcTime = GcClock::Now(); - m_NextGcTime = NextGcTime(m_LastGcTime); + m_LastGcTime = GcClock::Now(); + m_LastLightweightGcTime = m_LastGcTime; + } try { diff --git a/src/zenstore/include/zenstore/gc.h b/src/zenstore/include/zenstore/gc.h index 28e5c2ec2..2e52218f8 100644 --- a/src/zenstore/include/zenstore/gc.h +++ b/src/zenstore/include/zenstore/gc.h @@ -65,6 +65,9 @@ public: std::span<const IoHash> ExpiredCacheKeys(const std::string& CacheKeyContext) const; + bool SkipCid() const; + void SetSkipCid(bool NewState); + bool IsDeletionMode() const; void SetDeletionMode(bool NewState); @@ -183,6 +186,7 @@ struct GcSchedulerConfig uint64_t DiskReserveSize = 1ul << 28; uint64_t DiskSizeSoftLimit = 0; uint64_t MinimumFreeDiskSpaceToAllowWrites = 1ul << 28; + std::chrono::seconds LightweightInterval{}; }; class DiskUsageWindow @@ -224,6 +228,7 @@ public: std::chrono::seconds MaxCacheDuration = std::chrono::seconds::max(); std::chrono::seconds MaxProjectStoreDuration = std::chrono::seconds::max(); uint64_t DiskSizeSoftLimit = 0; + bool SkipCid = false; }; bool TriggerGc(const TriggerGcParams& Params); @@ -237,23 +242,23 @@ public: bool TriggerScrub(const TriggerScrubParams& Params); private: - void SchedulerThread(); - void CollectGarbage(const GcClock::TimePoint& CacheExpireTime, - const GcClock::TimePoint& ProjectStoreExpireTime, - bool Delete, - bool CollectSmallObjects); - void ScrubStorage(bool DoDelete, std::chrono::seconds TimeSlice); - GcClock::TimePoint NextGcTime(GcClock::TimePoint CurrentTime); - spdlog::logger& Log() { return m_Log; } - virtual bool AreDiskWritesAllowed() const override { return !m_AreDiskWritesBlocked.load(); } - DiskSpace CheckDiskSpace(); + void SchedulerThread(); + void CollectGarbage(const GcClock::TimePoint& CacheExpireTime, + const GcClock::TimePoint& ProjectStoreExpireTime, + bool Delete, + bool CollectSmallObjects, + bool SkipCid); + void ScrubStorage(bool DoDelete, std::chrono::seconds TimeSlice); + spdlog::logger& Log() { return m_Log; } + virtual bool AreDiskWritesAllowed() const override { return !m_AreDiskWritesBlocked.load(); } + DiskSpace CheckDiskSpace(); spdlog::logger& m_Log; GcManager& m_GcManager; GcSchedulerConfig m_Config; GcClock::TimePoint m_LastGcTime{}; + GcClock::TimePoint m_LastLightweightGcTime{}; GcClock::TimePoint m_LastGcExpireTime{}; - GcClock::TimePoint m_NextGcTime{}; std::atomic_uint32_t m_Status{}; std::thread m_GcThread; std::mutex m_GcMutex; |