diff options
Diffstat (limited to 'zenstore/gc.cpp')
| -rw-r--r-- | zenstore/gc.cpp | 183 |
1 files changed, 181 insertions, 2 deletions
diff --git a/zenstore/gc.cpp b/zenstore/gc.cpp index bfb8f015e..278f09b0b 100644 --- a/zenstore/gc.cpp +++ b/zenstore/gc.cpp @@ -2,9 +2,97 @@ #include <zenstore/gc.h> +#include <zenstore/CAS.h> +#include <zenstore/cidstore.h> +#include <zencore/logging.h> + namespace zen { -CasGc::CasGc(CasStore& Store) : m_CasStore(Store) +////////////////////////////////////////////////////////////////////////// + +struct GcContext::GcState +{ + CasChunkSet m_CasChunks; + CasChunkSet m_CidChunks; + bool m_DeletionMode = true; +}; + +GcContext::GcContext() : m_State(std::make_unique<GcState>()) +{ +} + +GcContext::~GcContext() +{ +} + +void +GcContext::ContributeCids(std::span<const IoHash> Cids) +{ + m_State->m_CidChunks.AddChunksToSet(Cids); +} + +void +GcContext::ContributeCas(std::span<const IoHash> Cas) +{ + m_State->m_CasChunks.AddChunksToSet(Cas); +} + +void +GcContext::IterateCids(std::function<void(const IoHash&)> Callback) +{ + m_State->m_CidChunks.IterateChunks([&](const IoHash& Hash) { Callback(Hash); }); +} + +void +GcContext::FilterCids(std::span<const IoHash> Cid, std::function<void(const IoHash&)> KeepFunc) +{ + m_State->m_CidChunks.FilterChunks(Cid, [&](const IoHash& Hash) { KeepFunc(Hash); }); +} + +void +GcContext::FilterCas(std::span<const IoHash> Cas, std::function<void(const IoHash&)> KeepFunc) +{ + m_State->m_CasChunks.FilterChunks(Cas, [&](const IoHash& Hash) { KeepFunc(Hash); }); +} + +bool +GcContext::IsDeletionMode() const +{ + return m_State->m_DeletionMode; +} +void +GcContext::SetDeletionMode(bool NewState) +{ + m_State->m_DeletionMode = NewState; +} + +////////////////////////////////////////////////////////////////////////// + +GcContributor::GcContributor(CasGc& Gc) : m_Gc(Gc) +{ + m_Gc.AddGcContributor(this); +} + +GcContributor::~GcContributor() +{ + m_Gc.RemoveGcContributor(this); +} + +////////////////////////////////////////////////////////////////////////// + +GcStorage::GcStorage(CasGc& Gc) : m_Gc(Gc) +{ + m_Gc.AddGcStorage(this); +} + +GcStorage::~GcStorage() +{ + m_Gc.AddGcStorage(this); +} + +////////////////////////////////////////////////////////////////////////// + +CasGc::CasGc() { } @@ -13,12 +101,103 @@ CasGc::~CasGc() } void +CasGc::AddGcContributor(GcContributor* Contributor) +{ + RwLock::ExclusiveLockScope _(m_Lock); + m_GcContribs.push_back(Contributor); +} + +void +CasGc::RemoveGcContributor(GcContributor* Contributor) +{ + RwLock::ExclusiveLockScope _(m_Lock); + std::erase_if(m_GcContribs, [&](GcContributor* $) { return $ == 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() { + RwLock::SharedLockScope _(m_Lock); + + // First gather reference set + + GcContext GcCtx; + GcCtx.SetDeletionMode(false); + + for (GcContributor* Contributor : m_GcContribs) + { + Contributor->GatherReferences(GcCtx); + } + + if (CidStore* CidStore = m_CidStore) + { + std::vector<IoHash> CasHashes; + + int UnknownChunks = 0; + + GcCtx.IterateCids([&](const IoHash& Hash) { + IoHash Cas = CidStore->RemapCid(Hash); + + if (Cas == IoHash::Zero) + { + ++UnknownChunks; + } + else + { + CasHashes.push_back(Cas); + } + }); + + if (UnknownChunks) + { + ZEN_WARN("found {} unknown CIDs", UnknownChunks); + } + + GcCtx.ContributeCas(CasHashes); + } + + // Then trim storage + + for (GcStorage* Storage : m_GcStorage) + { + Storage->CollectGarbage(GcCtx); + } +} + +void +CasGc::SetCidStore(CidStore* Cids) +{ + m_CidStore = Cids; +} + +void +CasGc::OnNewCidReferences(std::span<IoHash> Hashes) +{ + ZEN_UNUSED(Hashes); +} + +void +CasGc::OnCommittedCidReferences(std::span<IoHash> Hashes) +{ + ZEN_UNUSED(Hashes); } void -CasGc::OnNewReferences(std::span<IoHash> Hashes) +CasGc::OnDroppedCidReferences(std::span<IoHash> Hashes) { ZEN_UNUSED(Hashes); } |