aboutsummaryrefslogtreecommitdiff
path: root/zenserver/upstream/jupiter.h
blob: 61d1bd99cf034b56a4dc16df61e143a6c1c02336 (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
// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <zencore/httpserver.h>
#include <zencore/refcount.h>
#include <zencore/thread.h>

#include <spdlog/spdlog.h>

#include <atomic>
#include <list>
#include <memory>
#include <vector>

struct ZenCacheValue;

namespace zen {
namespace detail {
	struct CloudCacheSessionState;
}

class IoBuffer;
class CloudCacheClient;
struct IoHash;
class CbObjectView;

/**
 * Cached access token, for use with `Authorization:` header
 */
struct CloudCacheAccessToken
{
	std::string GetAuthorizationHeaderValue();
	void		SetToken(std::string_view Token);

	inline uint32_t GetSerial() const { return m_Serial.load(std::memory_order::memory_order_relaxed); }

private:
	RwLock				  m_Lock;
	std::string			  m_Token;
	std::atomic<uint32_t> m_Serial;
};

struct CloudCacheResult
{
	IoBuffer Value;
	bool	 Success = false;
};

/**
 * Context for performing Jupiter operations
 *
 * Maintains an HTTP connection so that subsequent operations don't need to go
 * through the whole connection setup process
 *
 */
class CloudCacheSession
{
public:
	CloudCacheSession(CloudCacheClient* OuterClient);
	~CloudCacheSession();

	CloudCacheResult GetDerivedData(std::string_view BucketId, std::string_view Key);
	CloudCacheResult GetDerivedData(std::string_view BucketId, const IoHash& Key);
	CloudCacheResult GetRef(std::string_view BucketId, const IoHash& Key);
	CloudCacheResult GetCompressedBlob(const IoHash& Key);

	CloudCacheResult PutDerivedData(std::string_view BucketId, std::string_view Key, IoBuffer DerivedData);
	CloudCacheResult PutDerivedData(std::string_view BucketId, const IoHash& Key, IoBuffer DerivedData);
	CloudCacheResult PutRef(std::string_view BucketId, const IoHash& Key, IoBuffer Ref);
	CloudCacheResult PutCompressedBlob(const IoHash& Key, IoBuffer Blob);

	std::vector<IoHash> Filter(std::string_view BucketId, const std::vector<IoHash>& ChunkHashes);

private:
	spdlog::logger&					m_Log;
	RefPtr<CloudCacheClient>		m_CacheClient;
	detail::CloudCacheSessionState* m_SessionState;
};

/**
 * Jupiter upstream cache client
 */
class CloudCacheClient : public RefCounted
{
public:
	CloudCacheClient(std::string_view ServiceUrl,
					 std::string_view DdcNamespace,
					 std::string_view BlobStoreNamespace,
					 std::string_view OAuthProvider,
					 std::string_view OAuthClientId,
					 std::string_view OAuthSecret);
	~CloudCacheClient();

	bool			 AcquireAccessToken(std::string& AuthorizationHeaderValue);
	std::string_view DdcNamespace() const { return m_DdcNamespace; }
	std::string_view BlobStoreNamespace() const { return m_BlobStoreNamespace; }
	std::string_view DefaultBucket() const { return m_DefaultBucket; }
	std::string_view ServiceUrl() const { return m_ServiceUrl; }
	bool			 IsValid() const { return m_IsValid; }

	spdlog::logger& Logger() { return m_Log; }

private:
	spdlog::logger&		  m_Log;
	std::string			  m_ServiceUrl;
	std::string			  m_OAuthDomain;
	std::string			  m_OAuthUriPath;
	std::string			  m_OAuthFullUri;
	std::string			  m_DdcNamespace;
	std::string			  m_BlobStoreNamespace;
	std::string			  m_DefaultBucket;
	std::string			  m_OAuthClientId;
	std::string			  m_OAuthSecret;
	CloudCacheAccessToken m_AccessToken;
	bool				  m_IsValid = false;

	RwLock									   m_SessionStateLock;
	std::list<detail::CloudCacheSessionState*> m_SessionStateCache;

	detail::CloudCacheSessionState* AllocSessionState();
	void							FreeSessionState(detail::CloudCacheSessionState*);

	friend class CloudCacheSession;
};

}  // namespace zen