1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include <zencore/compactbinary.h>
#include <zencore/iobuffer.h>
#include <zencore/iohash.h>
#include <zencore/thread.h>
#include <zencore/uid.h>
#include <zenstore/cas.h>
#pragma warning(push)
#pragma warning(disable : 4127)
#include <tsl/robin_map.h>
#pragma warning(pop)
#include <compare>
#include <filesystem>
#include <unordered_map>
namespace zen {
class WideStringBuilderBase;
class CasStore;
} // namespace zen
/******************************************************************************
/$$$$$$$$ /$$$$$$ /$$
|_____ $$ /$$__ $$ | $$
/$$/ /$$$$$$ /$$$$$$$ | $$ \__/ /$$$$$$ /$$$$$$| $$$$$$$ /$$$$$$
/$$/ /$$__ $| $$__ $$ | $$ |____ $$/$$_____| $$__ $$/$$__ $$
/$$/ | $$$$$$$| $$ \ $$ | $$ /$$$$$$| $$ | $$ \ $| $$$$$$$$
/$$/ | $$_____| $$ | $$ | $$ $$/$$__ $| $$ | $$ | $| $$_____/
/$$$$$$$| $$$$$$| $$ | $$ | $$$$$$| $$$$$$| $$$$$$| $$ | $| $$$$$$$
|________/\_______|__/ |__/ \______/ \_______/\_______|__/ |__/\_______/
Cache store for UE5. Restricts keys to "{bucket}/{hash}" pairs where the hash
is 40 (hex) chars in size. Values may be opaque blobs or structured objects
which can in turn contain references to other objects (or blobs).
******************************************************************************/
struct ZenCacheValue
{
zen::IoBuffer Value;
zen::CbObject IndexData;
};
class ZenCacheMemoryLayer
{
public:
ZenCacheMemoryLayer();
~ZenCacheMemoryLayer();
bool Get(std::string_view Bucket, const zen::IoHash& HashKey, ZenCacheValue& OutValue);
void Put(std::string_view Bucket, const zen::IoHash& HashKey, const ZenCacheValue& Value);
bool DropBucket(std::string_view Bucket);
private:
struct CacheBucket
{
zen::RwLock m_bucketLock;
tsl::robin_map<zen::IoHash, zen::IoBuffer> m_cacheMap;
bool Get(const zen::IoHash& HashKey, ZenCacheValue& OutValue);
void Put(const zen::IoHash& HashKey, const ZenCacheValue& Value);
};
zen::RwLock m_Lock;
std::unordered_map<std::string, CacheBucket> m_Buckets;
};
class ZenCacheDiskLayer
{
public:
ZenCacheDiskLayer(zen::CasStore& Cas, const std::filesystem::path& RootDir);
~ZenCacheDiskLayer();
bool Get(std::string_view Bucket, const zen::IoHash& HashKey, ZenCacheValue& OutValue);
void Put(std::string_view Bucket, const zen::IoHash& HashKey, const ZenCacheValue& Value);
bool DropBucket(std::string_view Bucket);
void Flush();
private:
/** A cache bucket manages a single directory containing
metadata and data for that bucket
*/
struct CacheBucket;
zen::CasStore& m_CasStore;
std::filesystem::path m_RootDir;
zen::RwLock m_Lock;
std::unordered_map<std::string, CacheBucket> m_Buckets; // TODO: make this case insensitive
};
class ZenCacheStore
{
public:
ZenCacheStore(zen::CasStore& Cas, const std::filesystem::path& RootDir);
~ZenCacheStore();
bool Get(std::string_view Bucket, const zen::IoHash& HashKey, ZenCacheValue& OutValue);
void Put(std::string_view Bucket, const zen::IoHash& HashKey, const ZenCacheValue& Value);
bool DropBucket(std::string_view Bucket);
void Flush();
private:
std::filesystem::path m_RootDir;
ZenCacheMemoryLayer m_MemLayer;
ZenCacheDiskLayer m_DiskLayer;
uint64_t m_DiskLayerSizeThreshold = 4 * 1024;
};
/** Tracks cache entry access, stats and orchestrates cleanup activities
*/
class ZenCacheTracker
{
public:
ZenCacheTracker(ZenCacheStore& CacheStore);
~ZenCacheTracker();
void TrackAccess(std::string_view Bucket, const zen::IoHash& HashKey);
void Flush();
private:
};
|