diff options
| author | Martin Ridgers <[email protected]> | 2021-12-15 10:48:11 +0100 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-12-15 10:48:11 +0100 |
| commit | ad8a56168969a2d0154ae67c383d874c686d1f92 (patch) | |
| tree | fae5283e02a4191858a24ee81fc04516ed09651b /zenserver/cache/structuredcachestore.h | |
| parent | Deleted unused statically-linked function (diff) | |
| download | zen-ad8a56168969a2d0154ae67c383d874c686d1f92.tar.xz zen-ad8a56168969a2d0154ae67c383d874c686d1f92.zip | |
Fixed "incomplete type" error.
GCC throws this error when using forward-declared type as a value type
for an std::pair (implicitly via a std::map).
Diffstat (limited to 'zenserver/cache/structuredcachestore.h')
| -rw-r--r-- | zenserver/cache/structuredcachestore.h | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/zenserver/cache/structuredcachestore.h b/zenserver/cache/structuredcachestore.h index 41b47b409..b39aa405e 100644 --- a/zenserver/cache/structuredcachestore.h +++ b/zenserver/cache/structuredcachestore.h @@ -7,7 +7,9 @@ #include <zencore/iohash.h> #include <zencore/thread.h> #include <zencore/uid.h> +#include <zenstore/basicfile.h> #include <zenstore/cas.h> +#include <zenstore/caslog.h> #include <zenstore/gc.h> ZEN_THIRD_PARTY_INCLUDES_START @@ -65,6 +67,62 @@ struct ZenCacheValue CbObject IndexData; }; +////////////////////////////////////////////////////////////////////////// + +#pragma pack(push) +#pragma pack(1) + +struct DiskLocation +{ + inline DiskLocation() = default; + + inline DiskLocation(uint64_t Offset, uint64_t ValueSize, uint32_t IndexSize, uint64_t Flags) + : OffsetAndFlags(CombineOffsetAndFlags(Offset, Flags)) + , LowerSize(ValueSize & 0xFFFFffff) + , IndexDataSize(IndexSize) + { + } + + static const uint64_t kOffsetMask = 0x0000'ffFF'ffFF'ffFFull; + static const uint64_t kSizeMask = 0x00FF'0000'0000'0000ull; + static const uint64_t kFlagsMask = 0xff00'0000'0000'0000ull; + static const uint64_t kStandaloneFile = 0x8000'0000'0000'0000ull; + static const uint64_t kStructured = 0x4000'0000'0000'0000ull; + static const uint64_t kTombStone = 0x2000'0000'0000'0000ull; + + static uint64_t CombineOffsetAndFlags(uint64_t Offset, uint64_t Flags) { return Offset | Flags; } + + inline uint64_t Offset() const { return OffsetAndFlags & kOffsetMask; } + inline uint64_t Size() const { return LowerSize; } + inline uint64_t IsFlagSet(uint64_t Flag) const { return OffsetAndFlags & Flag; } + inline ZenContentType GetContentType() const + { + ZenContentType ContentType = ZenContentType::kBinary; + + if (IsFlagSet(DiskLocation::kStructured)) + { + ContentType = ZenContentType::kCbObject; + } + + return ContentType; + } + +private: + uint64_t OffsetAndFlags = 0; + uint32_t LowerSize = 0; + uint32_t IndexDataSize = 0; +}; + +struct DiskIndexEntry +{ + IoHash Key; + DiskLocation Location; +}; + +#pragma pack(pop) + +static_assert(sizeof(DiskIndexEntry) == 36); + /** In-memory cache storage Intended for small values which are frequently accessed @@ -146,7 +204,68 @@ private: /** A cache bucket manages a single directory containing metadata and data for that bucket */ - struct CacheBucket; + struct CacheBucket + { + CacheBucket(std::string BucketName); + ~CacheBucket(); + + void OpenOrCreate(std::filesystem::path BucketDir, bool AllowCreate = true); + static bool Delete(std::filesystem::path BucketDir); + bool Get(const IoHash& HashKey, ZenCacheValue& OutValue); + void Put(const IoHash& HashKey, const ZenCacheValue& Value); + void Drop(); + void Flush(); + void SaveManifest(); + void Scrub(ScrubContext& Ctx); + void GatherReferences(GcContext& GcCtx); + void CollectGarbage(GcContext& GcCtx); + void UpdateAccessTimes(const std::vector<zen::access_tracking::KeyAccessTime>& AccessTimes); + + inline bool IsOk() const { return m_IsOk; } + inline uint64_t TotalSize() const { return m_TotalSize.load(std::memory_order::relaxed); } + + private: + std::string m_BucketName; + std::filesystem::path m_BucketDir; + Oid m_BucketId; + bool m_IsOk = false; + uint64_t m_LargeObjectThreshold = 64 * 1024; + + // These files are used to manage storage of small objects for this bucket + + BasicFile m_SobsFile; + TCasLogFile<DiskIndexEntry> m_SlogFile; + + struct IndexEntry + { + DiskLocation Location; + GcClock::Tick LastAccess{}; + }; + + using IndexMap = tsl::robin_map<IoHash, IndexEntry, IoHash::Hasher>; + + RwLock m_IndexLock; + IndexMap m_Index; + uint64_t m_SobsCursor = 0; + std::atomic_uint64_t m_TotalSize{}; + + void BuildPath(PathBuilderBase& 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 std::filesystem::path& Path, std::error_code& Ec); + bool GetInlineCacheValue(const DiskLocation& Loc, ZenCacheValue& OutValue); + void OpenLog(const std::filesystem::path& BucketDir, const bool IsNew); + + // These locks are here to avoid contention on file creation, therefore it's sufficient + // that we take the same lock for the same hash + // + // These locks are small and should really be spaced out so they don't share cache lines, + // but we don't currently access them at particularly high frequency so it should not be + // an issue in practice + + RwLock m_ShardedLocks[256]; + inline RwLock& LockForHash(const IoHash& Hash) { return m_ShardedLocks[Hash.Hash[19]]; } + }; std::filesystem::path m_RootDir; mutable RwLock m_Lock; |