aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcachestore.h
blob: 48c3cfde994c8ec8fd2faa8f745df6569339c143 (plain) (blame)
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:
};