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
129
130
131
132
133
134
|
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "resourcemetrics.h"
#include <zencore/system.h>
#include <zenutil/zenserverprocess.h>
#include <filesystem>
#include <functional>
#include <memory>
#include <unordered_map>
#include <unordered_set>
namespace zen {
class StorageServerInstance;
/**
* Hub
*
* Core logic for managing storage server instances on behalf of external clients.
*/
struct HubProvisionedInstanceInfo
{
std::string BaseUri;
uint16_t Port;
};
class Hub
{
public:
struct Configuration
{
/** Enable or disable the use of a Windows Job Object for child process management.
* When enabled, all spawned child processes are assigned to a job object with
* JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, ensuring children are terminated if the hub
* crashes or is force-killed. Must be called before Initialize(). No-op on non-Windows.
*/
bool UseJobObject = true;
uint16_t BasePortNumber = 21000;
int InstanceLimit = 1000;
};
typedef std::function<void(std::string_view ModuleId, const HubProvisionedInstanceInfo& Info)> ProvisionModuleCallbackFunc;
Hub(const Configuration& Config,
ZenServerEnvironment&& RunEnvironment,
ProvisionModuleCallbackFunc&& ProvisionedModuleCallback = {},
ProvisionModuleCallbackFunc&& DeprovisionedModuleCallback = {});
~Hub();
Hub(const Hub&) = delete;
Hub& operator=(const Hub&) = delete;
/**
* Provision a storage server instance for the given module ID.
*
* @param ModuleId The ID of the module to provision.
* @param OutInfo If successful, information about the provisioned instance will be returned here.
* @param OutReason If unsuccessful, the reason will be returned here.
*/
bool Provision(std::string_view ModuleId, HubProvisionedInstanceInfo& OutInfo, std::string& OutReason);
/**
* Deprovision a storage server instance for the given module ID.
*
* @param ModuleId The ID of the module to deprovision.
* @param OutReason If unsuccessful, the reason will be returned here.
* @return true if the instance was found and deprovisioned, false otherwise.
*/
bool Deprovision(const std::string& ModuleId, std::string& OutReason);
/**
* Find a storage server instance for the given module ID.
*
* Beware that as this returns a raw pointer to the instance, the caller must ensure
* that the instance is not deprovisioned while in use.
*
* @param ModuleId The ID of the module to find.
* @param OutInstance If found, the instance will be returned here.
* @return true if the instance was found, false otherwise.
*/
bool Find(std::string_view ModuleId, StorageServerInstance** OutInstance = nullptr);
/**
* Enumerate all storage server instances.
*
* @param Callback The callback to invoke for each instance. Note that you should
* not do anything heavyweight in the callback as it is invoked while holding
* a shared lock.
*/
void EnumerateModules(std::function<void(StorageServerInstance&)> Callback);
int GetInstanceCount();
int GetMaxInstanceCount() const { return m_MaxInstanceCount; }
const Configuration& GetConfig() const { return m_Config; }
private:
const Configuration m_Config;
ZenServerEnvironment m_RunEnvironment;
ProvisionModuleCallbackFunc m_ProvisionedModuleCallback;
ProvisionModuleCallbackFunc m_DeprovisionedModuleCallback;
std::filesystem::path m_FileHydrationPath;
std::filesystem::path m_HydrationTempPath;
#if ZEN_PLATFORM_WINDOWS
JobObject m_JobObject;
#endif
RwLock m_Lock;
std::unordered_map<std::string, std::unique_ptr<StorageServerInstance>> m_Instances;
std::unordered_set<std::string> m_DeprovisioningModules;
std::unordered_set<std::string> m_ProvisioningModules;
ResourceMetrics m_ResourceLimits;
SystemMetrics m_HostMetrics;
int m_MaxInstanceCount = 0;
void UpdateStats();
void UpdateCapacityMetrics();
bool CanProvisionInstance(std::string_view ModuleId, std::string& OutReason);
};
#if ZEN_WITH_TESTS
void hub_forcelink();
#endif // ZEN_WITH_TESTS
} // namespace zen
|