diff options
| author | Per Larsson <[email protected]> | 2021-12-07 16:22:56 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2021-12-07 16:22:56 +0100 |
| commit | 431c3f739b44f84470b54c57a00f89485caed901 (patch) | |
| tree | 997d9a154790786ffa5d24d4aec46972c8fb099f /zenserver/cache/structuredcachestore.cpp | |
| parent | Added support for time based eviction policy in structured cache. (diff) | |
| download | zen-431c3f739b44f84470b54c57a00f89485caed901.tar.xz zen-431c3f739b44f84470b54c57a00f89485caed901.zip | |
First pass of z$ garbage collection.
Diffstat (limited to 'zenserver/cache/structuredcachestore.cpp')
| -rw-r--r-- | zenserver/cache/structuredcachestore.cpp | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/zenserver/cache/structuredcachestore.cpp b/zenserver/cache/structuredcachestore.cpp index 2b213b9b0..740023098 100644 --- a/zenserver/cache/structuredcachestore.cpp +++ b/zenserver/cache/structuredcachestore.cpp @@ -36,10 +36,11 @@ ZEN_THIRD_PARTY_INCLUDES_END namespace zen { +namespace fs = std::filesystem; using namespace fmt::literals; static CbObject -LoadCompactBinaryObject(const std::filesystem::path& Path) +LoadCompactBinaryObject(const fs::path& Path) { FileContents Result = ReadFile(Path); @@ -56,12 +57,12 @@ LoadCompactBinaryObject(const std::filesystem::path& Path) } static void -SaveCompactBinaryObject(const std::filesystem::path& Path, const CbObject& Object) +SaveCompactBinaryObject(const fs::path& Path, const CbObject& Object) { WriteFile(Path, Object.GetBuffer().AsIoBuffer()); } -ZenCacheStore::ZenCacheStore(CasGc& Gc, const std::filesystem::path& RootDir) : GcContributor(Gc), m_DiskLayer(RootDir) +ZenCacheStore::ZenCacheStore(CasGc& Gc, const std::filesystem::path& RootDir) : GcStorage(Gc), GcContributor(Gc), m_DiskLayer(RootDir) { ZEN_INFO("initializing structured cache at '{}'", RootDir); CreateDirectories(RootDir); @@ -186,6 +187,13 @@ ZenCacheStore::GatherReferences(GcContext& GcCtx) m_DiskLayer.GatherReferences(GcCtx); } +void +ZenCacheStore::CollectGarbage(GcContext& GcCtx) +{ + m_MemLayer.CollectGarbage(GcCtx); + m_DiskLayer.CollectGarbage(GcCtx); +} + ZenCacheSize ZenCacheStore::TotalSize() const { @@ -285,6 +293,16 @@ ZenCacheMemoryLayer::GatherReferences(GcContext& GcCtx) } } +void +ZenCacheMemoryLayer::CollectGarbage(GcContext& GcCtx) +{ + ZEN_UNUSED(GcCtx); + + // Just drop everything for now + RwLock::ExclusiveLockScope _(m_Lock); + m_Buckets.clear(); +} + uint64_t ZenCacheMemoryLayer::TotalSize() const { @@ -444,6 +462,7 @@ struct ZenCacheDiskLayer::CacheBucket void Flush(); void Scrub(ScrubContext& Ctx); void GatherReferences(GcContext& GcCtx); + void CollectGarbage(GcContext& GcCtx); inline bool IsOk() const { return m_IsOk; } inline uint64_t TotalSize() const { return m_TotalSize; } @@ -473,6 +492,7 @@ private: void BuildPath(WideStringBuilderBase& Path, const IoHash& HashKey); void PutStandaloneCacheValue(const IoHash& HashKey, const ZenCacheValue& Value); bool GetStandaloneCacheValue(const DiskLocation& Loc, const IoHash& HashKey, ZenCacheValue& OutValue); + void DeleteStandaloneCacheValue(const DiskLocation& Loc, const IoHash& HashKey, const fs::path& Path, std::error_code& Ec); bool GetInlineCacheValue(const DiskLocation& Loc, ZenCacheValue& OutValue); // These locks are here to avoid contention on file creation, therefore it's sufficient @@ -644,6 +664,22 @@ ZenCacheDiskLayer::CacheBucket::GetStandaloneCacheValue(const DiskLocation& Loc, return false; } +void +ZenCacheDiskLayer::CacheBucket::DeleteStandaloneCacheValue(const DiskLocation& Loc, + const IoHash& HashKey, + const fs::path& Path, + std::error_code& Ec) +{ + ZEN_DEBUG("deleting standalone cache file '{}'", Path); + fs::remove(Path, Ec); + + if (!Ec) + { + m_SlogFile.Append(DiskIndexEntry{.Key = HashKey, .Location = {0, Loc.Size(), 0, DiskLocation::kTombStone}}); + m_Index.erase(HashKey); + } +} + bool ZenCacheDiskLayer::CacheBucket::Get(const IoHash& HashKey, ZenCacheValue& OutValue) { @@ -658,6 +694,8 @@ ZenCacheDiskLayer::CacheBucket::Get(const IoHash& HashKey, ZenCacheValue& OutVal { IndexEntry& Entry = It.value(); Entry.LastAccess = GcClock::TickCount(); + { + } if (GetInlineCacheValue(Entry.Location, OutValue)) { @@ -853,6 +891,60 @@ ZenCacheDiskLayer::CacheBucket::GatherReferences(GcContext& GcCtx) } void +ZenCacheDiskLayer::CacheBucket::CollectGarbage(GcContext& GcCtx) +{ + RwLock::ExclusiveLockScope _(m_IndexLock); + + const auto Reserved = size_t(m_Index.size() * 0.5); + + std::vector<std::pair<IoHash, DiskLocation>> Expired; + Expired.reserve(Reserved); + + for (auto& Kv : m_Index) + { + const IoHash& HashKey = Kv.first; + const IndexEntry& Entry = Kv.second; + const bool Standalone = Entry.Location.IsFlagSet(DiskLocation::kStandaloneFile); + + if (Standalone && GcCtx.Expired(Entry.LastAccess)) + { + Expired.push_back(std::make_pair(HashKey, Entry.Location)); + } + } + + { + std::error_code Ec; + WideStringBuilder<128> Path; + for (const auto& E : Expired) + { + const IoHash& HashKey = E.first; + const DiskLocation& Loc = E.second; + + Ec.clear(); + Path.Reset(); + BuildPath(Path, HashKey); + DeleteStandaloneCacheValue(Loc, HashKey, Path.c_str(), Ec); + + if (Ec) + { + ZEN_ERROR("delete standalone cache file '{}' FAILED, reason '{}'", WideToUtf8(Path.ToString()), Ec.message()); + } + } + } +} + +void +ZenCacheDiskLayer::CollectGarbage(GcContext& GcCtx) +{ + RwLock::SharedLockScope _(m_Lock); + + for (auto& Kv : m_Buckets) + { + Kv.second.CollectGarbage(GcCtx); + } +} + +void ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, const ZenCacheValue& Value) { RwLock::ExclusiveLockScope ValueLock(LockForHash(HashKey)); |