diff options
| author | Dan Engelbrecht <[email protected]> | 2022-05-04 15:25:35 +0200 |
|---|---|---|
| committer | Dan Engelbrecht <[email protected]> | 2022-05-04 15:25:35 +0200 |
| commit | 5b95a4fba97aa66cec935ef3e0d969893223f9d6 (patch) | |
| tree | 32316f82b9c9d0e846141ddb4244cefebe036697 /zenserver/cache/namespacecachestore.cpp | |
| parent | Initialize upstream apply in background thread (#88) (diff) | |
| download | zen-5b95a4fba97aa66cec935ef3e0d969893223f9d6.tar.xz zen-5b95a4fba97aa66cec935ef3e0d969893223f9d6.zip | |
Add namespacecachestore layer to allow multiple structured cache namespaces
Diffstat (limited to 'zenserver/cache/namespacecachestore.cpp')
| -rw-r--r-- | zenserver/cache/namespacecachestore.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/zenserver/cache/namespacecachestore.cpp b/zenserver/cache/namespacecachestore.cpp new file mode 100644 index 000000000..82ac40c62 --- /dev/null +++ b/zenserver/cache/namespacecachestore.cpp @@ -0,0 +1,207 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "namespacecachestore.h" +#include "structuredcachestore.h" + +namespace zen { + +const char* NamespaceDirPrefix = "ns_"; + +NamespaceCacheStore::NamespaceCacheStore(std::filesystem::path BasePath, CasGc& Gc) +: GcStorage(Gc) +, GcContributor(Gc) +, m_Log(logging::Get("namespacecachestore")) +, m_BasePath(BasePath) +{ + CreateDirectories(m_BasePath); + std::vector<std::string> ExistingFolders = FindExistingFolders(); + + std::vector<std::string> LegacyBuckets; + std::vector<std::string> Namespaces; + for (const std::string& DirName : ExistingFolders) + { + if (DirName.starts_with(NamespaceDirPrefix)) + { + Namespaces.push_back(DirName.substr(3)); + continue; + } + LegacyBuckets.push_back(DirName); + } + if (Namespaces.empty() && !LegacyBuckets.empty()) + { + // If we find no namespaces, but any unknown folders we assume we have a legacy folder + // and move any existing folders into a default namespace + std::filesystem::path DefaultfNamespaceFolder = m_BasePath / NamespaceDirPrefix; + CreateDirectories(DefaultfNamespaceFolder); + for (const std::string& DirName : LegacyBuckets) + { + std::filesystem::path LegacyFolder = m_BasePath / DirName; + std::filesystem::path NewPath = DefaultfNamespaceFolder / DirName; + std::filesystem::rename(LegacyFolder, NewPath); + } + Namespaces.push_back(""); + } + + for (const std::string& NamespaceName : Namespaces) + { + ZenCacheStore* Store = new ZenCacheStore(Gc, m_BasePath / (NamespaceDirPrefix + NamespaceName)); + m_Namespaces[NamespaceName] = Store; + } +} + +NamespaceCacheStore::~NamespaceCacheStore() +{ + for (const auto& Entry : m_Namespaces) + { + delete Entry.second; + } + m_Namespaces.clear(); +} + +std::vector<std::string> +NamespaceCacheStore::FindExistingFolders() const +{ + FileSystemTraversal Traversal; + struct Visitor : public FileSystemTraversal::TreeVisitor + { + virtual void VisitFile([[maybe_unused]] const std::filesystem::path& Parent, + [[maybe_unused]] const path_view& File, + [[maybe_unused]] uint64_t FileSize) override + { + } + + virtual bool VisitDirectory([[maybe_unused]] const std::filesystem::path& Parent, const path_view& DirectoryName) override + { + std::string DirName8 = WideToUtf8(DirectoryName); + Dirs.push_back(DirName8); + return false; + } + + std::vector<std::string> Dirs; + } Visit; + + Traversal.TraverseFileSystem(m_BasePath, Visit); + return Visit.Dirs; +} + +bool +NamespaceCacheStore::Get(const std::string& Namespace, std::string_view Bucket, const IoHash& HashKey, ZenCacheValue& OutValue) +{ + ZenCacheStore* Store = GetStore(Namespace); + if (!Store) + { + return false; + } + return Store->Get(Bucket, HashKey, OutValue); +} + +void +NamespaceCacheStore::Put(const std::string& Namespace, std::string_view Bucket, const IoHash& HashKey, const ZenCacheValue& Value) +{ + ZenCacheStore* Store = GetStore(Namespace); + if (!Store) + { + return; + } + Store->Put(Bucket, HashKey, Value); +} + +bool +NamespaceCacheStore::DropBucket(const std::string& Namespace, std::string_view Bucket) +{ + ZenCacheStore* Store = GetStore(Namespace); + if (!Store) + { + return false; + } + return Store->DropBucket(Bucket); +} + +void +NamespaceCacheStore::Flush() +{ + std::vector<ZenCacheStore*> Stores; + RwLock::SharedLockScope _(m_NamespacesLock); + Stores.reserve(m_Namespaces.size()); + for (const auto& Entry : m_Namespaces) + { + Stores.push_back(Entry.second); + } + _.ReleaseNow(); + for (ZenCacheStore* Store : Stores) + { + Store->Flush(); + } +} + +void +NamespaceCacheStore::Scrub(ScrubContext& Ctx) +{ + std::vector<ZenCacheStore*> Stores = GetAllStores(); + for (ZenCacheStore* Store : Stores) + { + Store->Scrub(Ctx); + } +} + +ZenCacheStore* +NamespaceCacheStore::GetStore(const std::string& Namespace) +{ + RwLock::SharedLockScope _(m_NamespacesLock); + if (auto It = m_Namespaces.find(Namespace); It != m_Namespaces.end()) + { + return It->second; + } + return nullptr; +} + +std::vector<ZenCacheStore*> +NamespaceCacheStore::GetAllStores() const +{ + std::vector<ZenCacheStore*> Stores; + RwLock::SharedLockScope _(m_NamespacesLock); + Stores.reserve(m_Namespaces.size()); + for (const auto& Entry : m_Namespaces) + { + Stores.push_back(Entry.second); + } + return Stores; +} + +void +NamespaceCacheStore::GatherReferences(GcContext& GcCtx) +{ + std::vector<ZenCacheStore*> Stores = GetAllStores(); + for (ZenCacheStore* Store : Stores) + { + Store->GatherReferences(GcCtx); + } +} + +void +NamespaceCacheStore::CollectGarbage(GcContext& GcCtx) +{ + std::vector<ZenCacheStore*> Stores = GetAllStores(); + for (ZenCacheStore* Store : Stores) + { + Store->CollectGarbage(GcCtx); + } +} + +GcStorageSize +NamespaceCacheStore::StorageSize() const +{ + std::vector<ZenCacheStore*> Stores = GetAllStores(); + GcStorageSize Size; + for (ZenCacheStore* Store : Stores) + { + GcStorageSize StoreSize = Store->StorageSize(); + Size.MemorySize += StoreSize.MemorySize; + Size.DiskSize += StoreSize.DiskSize; + } + return Size; +} + +} // namespace zen |