aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/zenserver.h
blob: 9af61acb96121c8ad385981c2b36dec0b16faa0c (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <zencore/basicfile.h>
#include <zencore/system.h>
#include <zenhttp/httpserver.h>
#include <zenhttp/httpstats.h>
#include <zenhttp/httpstatus.h>
#include <zenutil/zenserverprocess.h>

#include <atomic>
#include <memory>
#include <string_view>
#include "config/config.h"

ZEN_THIRD_PARTY_INCLUDES_START
#include <asio.hpp>
ZEN_THIRD_PARTY_INCLUDES_END

#include "diag/diagsvcs.h"
#include "stats/statsreporter.h"

#ifndef ZEN_APP_NAME
#	define ZEN_APP_NAME "Unreal Zen Storage Server"
#endif

namespace zen {

struct FLLMTag;
extern const FLLMTag& GetZenserverTag();

struct ZenStorageServerConfig;

class ZenServerBase : public IHttpStatusProvider
{
	ZenServerBase& operator=(ZenServerBase&&) = delete;
	ZenServerBase(ZenServerBase&&)			  = delete;

public:
	ZenServerBase();
	~ZenServerBase();

	void RequestExit(int ExitCode);

	void SetIsReadyFunc(std::function<void()>&& IsReadyFunc) { m_IsReadyFunc = std::move(IsReadyFunc); }

	void			   SetDataRoot(std::filesystem::path Root) { m_DataRoot = Root; }
	void			   SetContentRoot(std::filesystem::path Root) { m_ContentRoot = Root; }
	void			   SetDedicatedMode(bool State) { m_IsDedicatedMode = State; }
	void			   SetServerMode(std::string_view Mode) { m_ServerMode = Mode; }
	const std::string& GetServerMode() const { return m_ServerMode; }
	void			   SetTestMode(bool State) { m_TestMode = State; }

protected:
	int	 Initialize(const ZenServerConfig& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry);
	void Finalize();
	void ShutdownServices();
	void GetBuildOptions(StringBuilderBase& OutOptions, char Separator = ',') const;
	static std::vector<std::pair<std::string_view, std::string>> BuildSettingsList(const ZenServerConfig& ServerConfig);
	void														 LogSettingsSummary(const ZenServerConfig& ServerConfig);

protected:
	NamedMutex						m_ServerMutex;
	ZenServerState::ZenServerEntry* m_ServerEntry  = nullptr;
	bool							m_UseSentry	   = false;
	bool							m_IsPowerCycle = false;

	bool		m_IsDedicatedMode		 = false;
	bool		m_TestMode				 = false;
	bool		m_NoNetwork				 = false;
	bool		m_DebugOptionForcedCrash = false;
	std::string m_ServerMode			 = "Server";

	std::thread		 m_IoRunner;
	asio::io_context m_IoContext;
	void			 EnsureIoRunner();

	enum ServerState
	{
		kInitializing,
		kRunning,
		kShuttingDown
	};
	std::atomic<ServerState> m_CurrentState = kInitializing;

	inline void				SetNewState(ServerState NewState) { m_CurrentState.store(NewState, std::memory_order_relaxed); }
	static std::string_view ToString(ServerState Value);

	std::function<void()> m_IsReadyFunc;
	void				  OnReady();

	std::filesystem::path m_DataRoot;	  // Root directory for server state
	std::filesystem::path m_ContentRoot;  // Root directory for frontend content

	Ref<HttpServer> m_Http;

	std::unique_ptr<IHttpRequestFilter> m_HttpRequestFilter;

	HttpHealthService	 m_HealthService;
	HttpStatsService	 m_StatsService{m_IoContext};
	HttpStatusService	 m_StatusService;
	SystemMetricsTracker m_MetricsTracker;

	// Stats reporting

	StatsReporter	   m_StatsReporter;
	asio::steady_timer m_StatsReportingTimer{m_IoContext};
	void			   EnqueueStatsReportingTimer();

	// Process Monitoring

	void CheckOwnerPid();
	bool UpdateProcessMonitor();
	void EnqueueProcessMonitorTimer();

	ProcessMonitor	   m_ProcessMonitor;
	asio::steady_timer m_PidCheckTimer{m_IoContext};
	bool			   m_FoundNoActiveSponsors = false;

	// Server state exit signaling

	asio::steady_timer m_StateExitFlagTimer{m_IoContext};

	void EnqueueStateExitFlagTimer();
	void CheckStateExitFlag();

	// SIGINT handling

	void			   EnqueueSigIntTimer();
	void			   CheckSigInt();
	asio::steady_timer m_SigIntTimer{m_IoContext};

	// IHttpStatusProvider
	virtual void HandleStatusRequest(HttpServerRequest& Request) override;

private:
	void InitializeSecuritySettings(const ZenServerConfig& ServerOptions);
};
class ZenServerMain
{
public:
	ZenServerMain(ZenServerConfig& ServerOptions);
	~ZenServerMain();

	int Run();

	ZenServerMain(const ZenServerMain&) = delete;
	ZenServerMain& operator=(const ZenServerMain&) = delete;

protected:
	ZenServerConfig&	  m_ServerOptions;
	LockFile			  m_LockFile;
	ZenServerInstanceInfo m_InstanceInfo;

	virtual void InitializeLogging();
	virtual void DoRun(ZenServerState::ZenServerEntry* Entry) = 0;

	void	 NotifyReady();
	CbObject MakeLockData(bool IsReady);
};

}  // namespace zen