diff options
| author | Stefan Boberg <[email protected]> | 2021-10-21 18:03:41 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-10-21 18:03:41 +0200 |
| commit | 3e824897aed32282ec9ee297e1cfc3efc5a8d251 (patch) | |
| tree | 199d71e7314ecf7df577b4466f0d599b86c4dd08 | |
| parent | Added IsReady flag to ZenServerEntry (diff) | |
| download | zen-3e824897aed32282ec9ee297e1cfc3efc5a8d251.tar.xz zen-3e824897aed32282ec9ee297e1cfc3efc5a8d251.zip | |
gc: Added GcStorage base class and hooked it up to CasGc
| -rw-r--r-- | zen/chunk/chunk.cpp | 5 | ||||
| -rw-r--r-- | zenserver/cache/structuredcachestore.cpp | 18 | ||||
| -rw-r--r-- | zenserver/cache/structuredcachestore.h | 8 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 4 | ||||
| -rw-r--r-- | zenstore/CAS.cpp | 15 | ||||
| -rw-r--r-- | zenstore/filecas.cpp | 16 | ||||
| -rw-r--r-- | zenstore/filecas.h | 7 | ||||
| -rw-r--r-- | zenstore/gc.cpp | 28 | ||||
| -rw-r--r-- | zenstore/include/zenstore/CAS.h | 3 | ||||
| -rw-r--r-- | zenstore/include/zenstore/gc.h | 27 |
10 files changed, 93 insertions, 38 deletions
diff --git a/zen/chunk/chunk.cpp b/zen/chunk/chunk.cpp index 3283a8b66..043832dd3 100644 --- a/zen/chunk/chunk.cpp +++ b/zen/chunk/chunk.cpp @@ -15,6 +15,7 @@ #include <zencore/thread.h> #include <zencore/timer.h> #include <zenstore/cas.h> +#include <zenstore/gc.h> #include "../internalfile.h" @@ -942,12 +943,14 @@ ChunkCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) std::unique_ptr<zen::CasStore> CasStore; + zen::CasGc Gc; + if (!m_RootDirectory.empty()) { zen::CasStoreConfiguration Config; Config.RootDirectory = m_RootDirectory; - CasStore.reset(zen::CreateCasStore()); + CasStore.reset(zen::CreateCasStore(Gc)); CasStore->Initialize(Config); } diff --git a/zenserver/cache/structuredcachestore.cpp b/zenserver/cache/structuredcachestore.cpp index e28b2b2d8..f964c3102 100644 --- a/zenserver/cache/structuredcachestore.cpp +++ b/zenserver/cache/structuredcachestore.cpp @@ -145,10 +145,10 @@ ZenCacheStore::Scrub(ScrubContext& Ctx) } void -ZenCacheStore::GarbageCollect(GcContext& GcCtx) +ZenCacheStore::GatherReferences(GcContext& GcCtx) { - m_MemLayer.GarbageCollect(GcCtx); - m_DiskLayer.GarbageCollect(GcCtx); + m_MemLayer.GatherReferences(GcCtx); + m_DiskLayer.GatherReferences(GcCtx); } ////////////////////////////////////////////////////////////////////////// @@ -234,7 +234,7 @@ ZenCacheMemoryLayer::Scrub(ScrubContext& Ctx) } void -ZenCacheMemoryLayer::GarbageCollect(GcContext& GcCtx) +ZenCacheMemoryLayer::GatherReferences(GcContext& GcCtx) { ZEN_UNUSED(GcCtx); } @@ -261,7 +261,7 @@ ZenCacheMemoryLayer::CacheBucket::Scrub(ScrubContext& Ctx) } void -ZenCacheMemoryLayer::CacheBucket::GarbageCollect(GcContext& GcCtx) +ZenCacheMemoryLayer::CacheBucket::GatherReferences(GcContext& GcCtx) { // Is it even meaningful to do this? The memory layer shouldn't // contain anything which is not already in the disk layer @@ -391,7 +391,7 @@ struct ZenCacheDiskLayer::CacheBucket void Drop(); void Flush(); void Scrub(ScrubContext& Ctx); - void GarbageCollect(GcContext& GcCtx); + void GatherReferences(GcContext& GcCtx); inline bool IsOk() const { return m_IsOk; } @@ -723,7 +723,7 @@ ZenCacheDiskLayer::CacheBucket::Scrub(ScrubContext& Ctx) } void -ZenCacheDiskLayer::CacheBucket::GarbageCollect(GcContext& GcCtx) +ZenCacheDiskLayer::CacheBucket::GatherReferences(GcContext& GcCtx) { RwLock::SharedLockScope _(m_IndexLock); @@ -1069,13 +1069,13 @@ ZenCacheDiskLayer::Scrub(ScrubContext& Ctx) } void -ZenCacheDiskLayer::GarbageCollect(GcContext& GcCtx) +ZenCacheDiskLayer::GatherReferences(GcContext& GcCtx) { RwLock::SharedLockScope _(m_Lock); for (auto& Kv : m_Buckets) { - Kv.second.GarbageCollect(GcCtx); + Kv.second.GatherReferences(GcCtx); } } diff --git a/zenserver/cache/structuredcachestore.h b/zenserver/cache/structuredcachestore.h index 042d2ab3d..cf22b8be2 100644 --- a/zenserver/cache/structuredcachestore.h +++ b/zenserver/cache/structuredcachestore.h @@ -66,7 +66,7 @@ public: void Put(std::string_view Bucket, const IoHash& HashKey, const ZenCacheValue& Value); bool DropBucket(std::string_view Bucket); void Scrub(ScrubContext& Ctx); - void GarbageCollect(GcContext& GcCtx); + void GatherReferences(GcContext& GcCtx); struct Configuration { @@ -92,7 +92,7 @@ private: bool Get(const IoHash& HashKey, ZenCacheValue& OutValue); void Put(const IoHash& HashKey, const ZenCacheValue& Value); void Scrub(ScrubContext& Ctx); - void GarbageCollect(GcContext& GcCtx); + void GatherReferences(GcContext& GcCtx); private: uint64_t GetCurrentTimeStamp(); @@ -114,7 +114,7 @@ public: bool DropBucket(std::string_view Bucket); void Flush(); void Scrub(ScrubContext& Ctx); - void GarbageCollect(GcContext& GcCtx); + void GatherReferences(GcContext& GcCtx); void DiscoverBuckets(); @@ -140,7 +140,7 @@ public: bool DropBucket(std::string_view Bucket); void Flush(); void Scrub(ScrubContext& Ctx); - virtual void GarbageCollect(GcContext& GcCtx) override; + virtual void GatherReferences(GcContext& GcCtx) override; private: std::filesystem::path m_RootDir; diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index c96fec986..4e9d2f644 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -472,8 +472,8 @@ private: zen::Ref<zen::HttpServer> m_Http; zen::HttpStatusService m_StatusService; zen::HttpStatsService m_StatsService; - std::unique_ptr<zen::CasStore> m_CasStore{zen::CreateCasStore()}; - zen::CasGc m_Gc{*m_CasStore}; + zen::CasGc m_Gc; + std::unique_ptr<zen::CasStore> m_CasStore{zen::CreateCasStore(m_Gc)}; std::unique_ptr<zen::CidStore> m_CidStore; std::unique_ptr<zen::ZenCacheStore> m_CacheStore; zen::CasScrubber m_Scrubber{*m_CasStore}; diff --git a/zenstore/CAS.cpp b/zenstore/CAS.cpp index 20ad20971..09e13a702 100644 --- a/zenstore/CAS.cpp +++ b/zenstore/CAS.cpp @@ -17,6 +17,7 @@ #include <zencore/testutils.h> #include <zencore/thread.h> #include <zencore/uid.h> +#include <zenstore/gc.h> #include <gsl/gsl-lite.hpp> @@ -94,7 +95,7 @@ ScrubContext::ReportScrubbed(uint64_t ChunkCount, uint64_t ChunkBytes) class CasImpl : public CasStore { public: - CasImpl(); + CasImpl(CasGc& Gc); virtual ~CasImpl(); virtual void Initialize(const CasStoreConfiguration& InConfig) override; @@ -123,7 +124,7 @@ private: void UpdateManifest(bool IsNewStore); }; -CasImpl::CasImpl() : m_TinyStrategy(m_Config), m_SmallStrategy(m_Config), m_LargeStrategy(m_Config) +CasImpl::CasImpl(CasGc& Gc) : m_TinyStrategy(m_Config), m_SmallStrategy(m_Config), m_LargeStrategy(m_Config, Gc) { } @@ -313,15 +314,15 @@ CasImpl::Scrub(ScrubContext& Ctx) void CasImpl::GarbageCollect(GcContext& GcCtx) { - m_LargeStrategy.GarbageCollect(GcCtx); + m_LargeStrategy.CollectGarbage(GcCtx); } ////////////////////////////////////////////////////////////////////////// CasStore* -CreateCasStore() +CreateCasStore(CasGc& Gc) { - return new CasImpl(); + return new CasImpl(Gc); } ////////////////////////////////////////////////////////////////////////// @@ -338,7 +339,9 @@ TEST_CASE("CasStore") CasStoreConfiguration config; config.RootDirectory = TempDir.Path(); - std::unique_ptr<CasStore> Store{CreateCasStore()}; + CasGc Gc; + + std::unique_ptr<CasStore> Store{CreateCasStore(Gc)}; Store->Initialize(config); ScrubContext Ctx; diff --git a/zenstore/filecas.cpp b/zenstore/filecas.cpp index d8811de00..9cb6e5c79 100644 --- a/zenstore/filecas.cpp +++ b/zenstore/filecas.cpp @@ -14,10 +14,10 @@ #include <zencore/thread.h> #include <zencore/uid.h> #include <zenstore/basicfile.h> +#include <zenstore/gc.h> #if ZEN_WITH_TESTS # include <zencore/compactbinarybuilder.h> -# include <zenstore/gc.h> #endif #include <gsl/gsl-lite.hpp> @@ -70,7 +70,7 @@ FileCasStrategy::ShardingHelper::ShardingHelper(const std::filesystem::path& Roo ////////////////////////////////////////////////////////////////////////// -FileCasStrategy::FileCasStrategy(const CasStoreConfiguration& Config) : m_Config(Config), m_Log(logging::Get("filecas")) +FileCasStrategy::FileCasStrategy(const CasStoreConfiguration& Config, CasGc& Gc) : GcStorage(Gc), m_Config(Config), m_Log(logging::Get("filecas")) { } @@ -481,7 +481,7 @@ FileCasStrategy::Scrub(ScrubContext& Ctx) } void -FileCasStrategy::GarbageCollect(GcContext& GcCtx) +FileCasStrategy::CollectGarbage(GcContext& GcCtx) { ZEN_UNUSED(GcCtx); } @@ -497,10 +497,12 @@ TEST_CASE("cas.file.move") // specifying an absolute path here can be helpful when using procmon to dig into things ScopedTemporaryDirectory TempDir; // {"d:\\filecas_testdir"}; + CasGc Gc; + CasStoreConfiguration CasConfig; CasConfig.RootDirectory = TempDir.Path() / "cas"; - FileCasStrategy FileCas(CasConfig); + FileCasStrategy FileCas(CasConfig, Gc); { std::filesystem::path Payload1Path{TempDir.Path() / "payload_1"}; @@ -575,10 +577,12 @@ TEST_CASE("cas.file.gc") // specifying an absolute path here can be helpful when using procmon to dig into things ScopedTemporaryDirectory TempDir; // {"d:\\filecas_testdir"}; + CasGc Gc; + CasStoreConfiguration CasConfig; CasConfig.RootDirectory = TempDir.Path() / "cas"; - FileCasStrategy FileCas(CasConfig); + FileCasStrategy FileCas(CasConfig, Gc); for (int i = 0; i < 1000; ++i) { @@ -595,7 +599,7 @@ TEST_CASE("cas.file.gc") GcContext Ctx; - FileCas.GarbageCollect(Ctx); + FileCas.CollectGarbage(Ctx); } #endif diff --git a/zenstore/filecas.h b/zenstore/filecas.h index 14314ce52..bbba9733e 100644 --- a/zenstore/filecas.h +++ b/zenstore/filecas.h @@ -9,6 +9,7 @@ #include <zencore/string.h> #include <zencore/thread.h> #include <zenstore/cas.h> +#include <zenstore/gc.h> #include <functional> @@ -23,9 +24,9 @@ class BasicFile; /** CAS storage strategy using a file-per-chunk storage strategy */ -struct FileCasStrategy +struct FileCasStrategy : public GcStorage { - FileCasStrategy(const CasStoreConfiguration& Config); + FileCasStrategy(const CasStoreConfiguration& Config, CasGc& Gc); ~FileCasStrategy(); CasStore::InsertResult InsertChunk(const void* ChunkData, size_t ChunkSize, const IoHash& ChunkHash); @@ -34,7 +35,7 @@ struct FileCasStrategy bool HaveChunk(const IoHash& ChunkHash); void FilterChunks(CasChunkSet& InOutChunks); void Flush(); - void GarbageCollect(GcContext& GcCtx); + virtual void CollectGarbage(GcContext& GcCtx) override; void Scrub(ScrubContext& Ctx); private: diff --git a/zenstore/gc.cpp b/zenstore/gc.cpp index 612cceed9..79c646db2 100644 --- a/zenstore/gc.cpp +++ b/zenstore/gc.cpp @@ -47,7 +47,19 @@ GcContributor::~GcContributor() ////////////////////////////////////////////////////////////////////////// -CasGc::CasGc(CasStore& Store) : m_CasStore(Store) +GcStorage::GcStorage(CasGc& Gc) : m_Gc(Gc) +{ + m_Gc.AddGcStorage(this); +} + +GcStorage::~GcStorage() +{ + m_Gc.AddGcStorage(this); +} + +////////////////////////////////////////////////////////////////////////// + +CasGc::CasGc() { } @@ -70,6 +82,20 @@ CasGc::RemoveGcContributor(GcContributor* Contributor) } void +CasGc::AddGcStorage(GcStorage* Storage) +{ + RwLock::ExclusiveLockScope _(m_Lock); + m_GcStorage.push_back(Storage); +} + +void +CasGc::RemoveGcStorage(GcStorage* Storage) +{ + RwLock::ExclusiveLockScope _(m_Lock); + std::erase_if(m_GcStorage, [&](GcStorage* $) { return $ == Storage; }); +} + +void CasGc::CollectGarbage() { } diff --git a/zenstore/include/zenstore/CAS.h b/zenstore/include/zenstore/CAS.h index 738103f73..a387b905e 100644 --- a/zenstore/include/zenstore/CAS.h +++ b/zenstore/include/zenstore/CAS.h @@ -20,6 +20,7 @@ namespace zen { class GcContext; +class CasGc; struct CasStoreConfiguration { @@ -107,7 +108,7 @@ protected: uint64_t m_LastScrubTime = 0; }; -ZENCORE_API CasStore* CreateCasStore(); +ZENCORE_API CasStore* CreateCasStore(CasGc& Gc); void CAS_forcelink(); diff --git a/zenstore/include/zenstore/gc.h b/zenstore/include/zenstore/gc.h index 942355293..d51925a0c 100644 --- a/zenstore/include/zenstore/gc.h +++ b/zenstore/include/zenstore/gc.h @@ -33,10 +33,9 @@ private: std::unique_ptr<GcState> m_State; }; - /** GC root contributor - Higher level data structures provide roots for the garbage collector, + Higher level data structures provide roots for the garbage collector, which ultimately determine what is garbage and what data we need to retain. @@ -48,24 +47,42 @@ public: GcContributor(CasGc& Gc); ~GcContributor(); - virtual void GarbageCollect(GcContext& GcCtx) = 0; + virtual void GatherReferences(GcContext& GcCtx) = 0; protected: CasGc& m_Gc; }; +/** GC storage provider + */ + +class GcStorage +{ +public: + GcStorage(CasGc& Gc); + ~GcStorage(); + + virtual void CollectGarbage(GcContext& GcCtrx) = 0; + +private: + CasGc& m_Gc; +}; + /** GC orchestrator */ class CasGc { public: - CasGc(CasStore& Store); + CasGc(); ~CasGc(); void AddGcContributor(GcContributor* Contributor); void RemoveGcContributor(GcContributor* Contributor); + void AddGcStorage(GcStorage* Contributor); + void RemoveGcStorage(GcStorage* Contributor); + void CollectGarbage(); void OnNewCidReferences(std::span<IoHash> Hashes); @@ -73,9 +90,9 @@ public: void OnDroppedCidReferences(std::span<IoHash> Hashes); private: - CasStore& m_CasStore; RwLock m_Lock; std::vector<GcContributor*> m_GcContribs; + std::vector<GcStorage*> m_GcStorage; }; } // namespace zen |