aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcachestore.cpp
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-12-07 16:22:56 +0100
committerPer Larsson <[email protected]>2021-12-07 16:22:56 +0100
commit431c3f739b44f84470b54c57a00f89485caed901 (patch)
tree997d9a154790786ffa5d24d4aec46972c8fb099f /zenserver/cache/structuredcachestore.cpp
parentAdded support for time based eviction policy in structured cache. (diff)
downloadzen-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.cpp98
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));