aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-11-25 14:07:24 +0100
committerPer Larsson <[email protected]>2021-11-25 14:07:24 +0100
commit522fbd01d25856c921bb1400b07ae900a0054627 (patch)
treebf649ab7efe41c22661d77196fc52428911cdb57
parentrpc: tactical checkin (diff)
parentAdded support for loading Lua config file from CLI option and merged server/s... (diff)
downloadzen-522fbd01d25856c921bb1400b07ae900a0054627.tar.xz
zen-522fbd01d25856c921bb1400b07ae900a0054627.zip
Merged main.
-rw-r--r--.gitignore1
-rw-r--r--scripts/deploybuild.py22
-rw-r--r--xmake.lua50
-rw-r--r--zenhttp/httpasio.cpp122
-rw-r--r--zenserver-test/zenserver-test.cpp2
-rw-r--r--zenserver/config.cpp180
-rw-r--r--zenserver/config.h44
-rw-r--r--zenserver/diag/diagsvcs.cpp3
-rw-r--r--zenserver/upstream/jupiter.cpp4
-rw-r--r--zenserver/upstream/upstreamapply.cpp14
-rw-r--r--zenserver/zenserver.cpp101
11 files changed, 317 insertions, 226 deletions
diff --git a/.gitignore b/.gitignore
index f84d4d94e..de0d3019b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
[Rr]eleases/
x64/
x86/
+build/
[Bb]in/
[Oo]bj/
[Ll]og/
diff --git a/scripts/deploybuild.py b/scripts/deploybuild.py
index c81235a8c..d137c3da1 100644
--- a/scripts/deploybuild.py
+++ b/scripts/deploybuild.py
@@ -50,20 +50,20 @@ while not os.path.exists(os.path.join(zenroot, "zen.sln")):
zenroot = os.path.dirname(zenroot)
jazz_print("Zen root:", zenroot)
-
# Build fresh binaries
-if use_xmake:
- build_cmd = ["xmake", "-b", "zenserver"]
- build_output_dir = r'build\windows\x64\release'
-else:
- vs_path = vswhere.get_latest_path() # can also specify prerelease=True
- jazz_print("BUILDING CODE", f"using VS root: {vs_path}")
- devenv_path = os.path.join(vs_path, "Common7\\IDE\\devenv.com")
- build_cmd = [devenv_path, "/build", "Release", "zen.sln"]
- build_output_dir = r'x64\Release'
-
try:
+ if use_xmake:
+ subprocess.run(["xmake.exe", "config", "-p", "windows", "-a", "x64", "-m", "release"], check=True)
+ build_cmd = ["xmake.exe", "build", "--rebuild", "zenserver"]
+ build_output_dir = r'build\windows\x64\release'
+ else:
+ vs_path = vswhere.get_latest_path() # can also specify prerelease=True
+ jazz_print("BUILDING CODE", f"using VS root: {vs_path}")
+ devenv_path = os.path.join(vs_path, "Common7\\IDE\\devenv.com")
+ build_cmd = [devenv_path, "/build", "Release", "zen.sln"]
+ build_output_dir = r'x64\Release'
+
subprocess.run(build_cmd, check=True)
except:
jazz_fail("Build failed!")
diff --git a/xmake.lua b/xmake.lua
index ced2b55ce..49989615c 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -73,3 +73,53 @@ includes("zenstore", "zenstore-test")
includes("zenutil")
includes("zenserver", "zenserver-test")
includes("zen")
+
+task("bundle")
+ on_run(function()
+ import("detect.tools.find_zip")
+ import("detect.tools.find_7z")
+
+ -- copy files
+ local dirs = {
+ binaries = "./build/windows/x64/release",
+ bundles = "./build/bundles",
+ bundle = "./build/bundles/zenzerver-win64"
+ }
+
+ local files = {
+ dirs.binaries .. "/zenserver.exe",
+ dirs.binaries .. "/zenserver.pdb",
+ "./vcpkg_installed/x64-windows-static/tools/sentry-native/crashpad_handler.exe"
+ }
+
+ os.mkdir(dirs.bundles)
+ os.mkdir(dirs.bundle)
+
+ for _,file in ipairs(files) do
+ printf("copy '%s' -> '%s'\n", file, dirs.bundle)
+ os.cp(file, dirs.bundle)
+ end
+
+ -- create archive
+ local bundle_name = "zenserver-win64.zip"
+
+ local zip_cmd = find_7z()
+ assert(zip_cmd)
+
+ local zip_args = {}
+ table.insert(zip_args, "a")
+ table.insert(zip_args, dirs.bundles .. "/" .. bundle_name)
+ table.insert(zip_args, dirs.bundle .. "/*.*")
+
+ printf("creating bundle '%s'...", dirs.bundles .. "/" .. bundle_name)
+ os.runv(zip_cmd, zip_args)
+ os.rm(dirs.bundle)
+
+ printf(" Ok!")
+ end)
+
+ set_menu {
+ usage = "xmake bundle",
+ description = "Create zip bundle from binaries",
+ options = {}
+ }
diff --git a/zenhttp/httpasio.cpp b/zenhttp/httpasio.cpp
index ea84e7e87..d5fe9adbb 100644
--- a/zenhttp/httpasio.cpp
+++ b/zenhttp/httpasio.cpp
@@ -6,6 +6,7 @@
#include <zenhttp/httpserver.h>
#include <deque>
+#include <memory>
#include <memory_resource>
ZEN_THIRD_PARTY_INCLUDES_START
@@ -169,7 +170,7 @@ private:
IoBuffer m_BodyBuffer;
uint64_t m_BodyPosition = 0;
http_parser m_Parser;
- char m_HeaderBuffer[512];
+ char m_HeaderBuffer[1024];
void AppendInputBytes(const char* Data, size_t Bytes);
void AppendCurrentHeader();
@@ -281,7 +282,7 @@ private:
//////////////////////////////////////////////////////////////////////////
-struct HttpServerConnection
+struct HttpServerConnection : std::enable_shared_from_this<HttpServerConnection>
{
HttpServerConnection(HttpAsioServerImpl& Server, std::unique_ptr<asio::ip::tcp::socket>&& Socket);
~HttpServerConnection();
@@ -290,6 +291,8 @@ struct HttpServerConnection
void TerminateConnection();
void HandleRequest();
+ std::shared_ptr<HttpServerConnection> AsSharedPtr() { return shared_from_this(); }
+
private:
enum class RequestState
{
@@ -369,50 +372,32 @@ HttpServerConnection::EnqueueRead()
asio::async_read(*m_Socket.get(),
m_RequestBuffer,
asio::transfer_at_least(16),
- [this](const asio::error_code& Ec, std::size_t ByteCount) {
- if (Ec)
- {
- if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kInitialRead)
- {
- // Expected, just silently handle the condition
- //
- // if we get an I/O error on the boundary between two messages
- // it should be fine to just not say anything
-
- ZEN_TRACE("(expected) socket read error: conn#{} '{}'", m_ConnectionId, Ec.message());
- }
- else
- {
- ZEN_WARN("unexpected socket read error: conn#{} {}", m_ConnectionId, Ec.message());
- }
-
- delete this;
- }
- else
- {
- ZEN_TRACE("read: conn#:{} seq#:{} t:{} bytes:{}",
- m_ConnectionId,
- m_RequestCounter.load(std::memory_order_relaxed),
- GetCurrentThreadId(),
- ByteCount);
-
- OnDataReceived(Ec, ByteCount);
- }
- });
+ [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnDataReceived(Ec, ByteCount); });
}
void
HttpServerConnection::OnDataReceived(const asio::error_code& Ec, std::size_t ByteCount)
{
- ZEN_UNUSED(ByteCount);
-
if (Ec)
{
- ZEN_ERROR("OnDataReceived Error: {}", Ec.message());
-
- return OnError();
+ if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kInitialRead)
+ {
+ ZEN_TRACE("on data received ERROR (EXPECTED), connection '{}' reason '{}'", m_ConnectionId, Ec.message());
+ return;
+ }
+ else
+ {
+ ZEN_ERROR("on data received ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message());
+ return OnError();
+ }
}
+ ZEN_TRACE("on data received, connection '{}', request '{}', thread '{}', bytes '{}'",
+ m_ConnectionId,
+ m_RequestCounter.load(std::memory_order_relaxed),
+ GetCurrentThreadId(),
+ NiceBytes(ByteCount));
+
while (m_RequestBuffer.size())
{
const asio::const_buffer& InputBuffer = m_RequestBuffer.data();
@@ -438,24 +423,34 @@ HttpServerConnection::OnDataReceived(const asio::error_code& Ec, std::size_t Byt
void
HttpServerConnection::OnResponseDataSent(const asio::error_code& Ec, std::size_t ByteCount, bool Pop)
{
- ZEN_UNUSED(ByteCount);
if (Ec)
{
- ZEN_ERROR("OnResponseDataSent Error: {}", Ec.message());
- return OnError();
+ ZEN_ERROR("on data sent ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message());
+ OnError();
}
else
{
+ ZEN_TRACE("on data sent, connection '{}', request '{}', thread '{}', bytes '{}'",
+ m_ConnectionId,
+ m_RequestCounter.load(std::memory_order_relaxed),
+ GetCurrentThreadId(),
+ NiceBytes(ByteCount));
+
if (!m_RequestData.IsKeepAlive())
{
m_RequestState = RequestState::kDone;
m_Socket->close();
}
- else if (Pop)
+ else
{
- RwLock::ExclusiveLockScope _(m_ResponsesLock);
- m_Responses.pop_front();
+ if (Pop)
+ {
+ RwLock::ExclusiveLockScope _(m_ResponsesLock);
+ m_Responses.pop_front();
+ }
+
+ m_RequestCounter.fetch_add(1);
}
}
}
@@ -478,7 +473,7 @@ HttpServerConnection::HandleRequest()
if (Ec)
{
- ZEN_WARN("socket shutdown reported error: {}", Ec.message());
+ ZEN_WARN("socket shutdown ERROR, reason '{}'", Ec.message());
}
}
else
@@ -486,14 +481,11 @@ HttpServerConnection::HandleRequest()
m_RequestState = RequestState::kWriting;
}
- const uint32_t RequestNum = m_RequestCounter.load(std::memory_order_relaxed);
- m_RequestCounter.fetch_add(1);
-
if (HttpService* Service = m_Server.RouteRequest(m_RequestData.Url()))
{
HttpAsioServerRequest Request(m_RequestData, *Service, m_RequestData.Body());
- ZEN_TRACE("Handling request: Conn#{} Req#{}", m_ConnectionId, RequestNum);
+ ZEN_TRACE("handle request, connection '{}' request '{}'", m_ConnectionId, m_RequestCounter.load(std::memory_order_relaxed));
Service->HandleRequest(Request);
@@ -525,9 +517,8 @@ HttpServerConnection::HandleRequest()
asio::async_write(*m_Socket.get(),
ResponseBuffers,
asio::transfer_exactly(ResponseLength),
- [this, RequestNum](const asio::error_code& Ec, std::size_t ByteCount) {
- ZEN_TRACE("Response sent: Conn#{} Req#{} ({})", m_ConnectionId, RequestNum, NiceBytes(ByteCount));
- OnResponseDataSent(Ec, ByteCount, true);
+ [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) {
+ Conn->OnResponseDataSent(Ec, ByteCount, true);
});
return;
@@ -548,9 +539,10 @@ HttpServerConnection::HandleRequest()
"\r\n"sv;
}
- asio::async_write(*m_Socket.get(), asio::buffer(Response), [this](const asio::error_code& Ec, std::size_t ByteCount) {
- OnResponseDataSent(Ec, ByteCount);
- });
+ asio::async_write(
+ *m_Socket.get(),
+ asio::buffer(Response),
+ [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnResponseDataSent(Ec, ByteCount); });
}
else
{
@@ -572,9 +564,10 @@ HttpServerConnection::HandleRequest()
"No suitable route found"sv;
}
- asio::async_write(*m_Socket.get(), asio::buffer(Response), [this](const asio::error_code& Ec, std::size_t ByteCount) {
- OnResponseDataSent(Ec, ByteCount);
- });
+ asio::async_write(
+ *m_Socket.get(),
+ asio::buffer(Response),
+ [Conn = AsSharedPtr()](const asio::error_code& Ec, std::size_t ByteCount) { Conn->OnResponseDataSent(Ec, ByteCount); });
}
}
@@ -875,8 +868,13 @@ struct HttpAcceptor
HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t Port)
: m_Server(Server)
, m_IoService(IoService)
- , m_Acceptor(m_IoService, asio::ip::tcp::endpoint(asio::ip::address_v4::any(), Port))
+ , m_Acceptor(m_IoService, asio::ip::tcp::v6())
{
+ m_Acceptor.set_option(asio::ip::v6_only(false));
+ m_Acceptor.set_option(asio::socket_base::reuse_address(true));
+ m_Acceptor.set_option(asio::ip::tcp::no_delay(true));
+ m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), Port));
+ m_Acceptor.listen();
}
void Start()
@@ -900,14 +898,14 @@ struct HttpAcceptor
else
{
// New connection established, pass socket ownership into connection object
- // and initiate request handling loop
+ // and initiate request handling loop. The connection lifetime is
+ // managed by the async read/write loop by passing the shared
+ // reference to the callbacks.
Socket->set_option(asio::ip::tcp::no_delay(true));
- HttpServerConnection* Conn = new HttpServerConnection(m_Server, std::move(Socket));
+ auto Conn = std::make_shared<HttpServerConnection>(m_Server, std::move(Socket));
Conn->HandleNewRequest();
-
- // note: the connection object is responsible for deleting itself
}
if (!m_IsStopped.load())
diff --git a/zenserver-test/zenserver-test.cpp b/zenserver-test/zenserver-test.cpp
index b3a4348f0..ad467753c 100644
--- a/zenserver-test/zenserver-test.cpp
+++ b/zenserver-test/zenserver-test.cpp
@@ -1745,6 +1745,7 @@ TEST_CASE("zcache.policy")
zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size());
zen::CbPackage Package;
const bool Ok = Package.TryLoad(Body);
+ CHECK(Ok);
CHECK(Ok);
@@ -1766,6 +1767,7 @@ TEST_CASE("zcache.policy")
zen::IoBuffer Body(zen::IoBuffer::Wrap, Result.text.data(), Result.text.size());
zen::CbPackage Package;
const bool Ok = Package.TryLoad(Body);
+ CHECK(Ok);
CHECK(Ok);
CHECK(Package.GetAttachments().size() != 0);
diff --git a/zenserver/config.cpp b/zenserver/config.cpp
index 3e85daa9e..1e847ce3d 100644
--- a/zenserver/config.cpp
+++ b/zenserver/config.cpp
@@ -79,8 +79,10 @@ ParseUpstreamCachePolicy(std::string_view Options)
}
}
+void ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions);
+
void
-ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, ZenServiceConfig& ServiceConfig)
+ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
{
#if ZEN_WITH_HTTPSYS
const char* DefaultHttp = "httpsys";
@@ -91,22 +93,23 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
cxxopts::Options options("zenserver", "Zen Server");
options.add_options()("dedicated",
"Enable dedicated server mode",
- cxxopts::value<bool>(GlobalOptions.IsDedicated)->default_value("false"));
- options.add_options()("d, debug", "Enable debugging", cxxopts::value<bool>(GlobalOptions.IsDebug)->default_value("false"));
+ cxxopts::value<bool>(ServerOptions.IsDedicated)->default_value("false"));
+ options.add_options()("d, debug", "Enable debugging", cxxopts::value<bool>(ServerOptions.IsDebug)->default_value("false"));
options.add_options()("help", "Show command line help");
- options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(GlobalOptions.IsTest)->default_value("false"));
- options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(GlobalOptions.LogId));
- options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::filesystem::path>(GlobalOptions.DataDir));
- options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::filesystem::path>(GlobalOptions.ContentDir));
- options.add_options()("abslog", "Path to log file", cxxopts::value<std::filesystem::path>(GlobalOptions.AbsLogFile));
+ options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(ServerOptions.IsTest)->default_value("false"));
+ options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(ServerOptions.LogId));
+ options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::filesystem::path>(ServerOptions.DataDir));
+ options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::filesystem::path>(ServerOptions.ContentDir));
+ options.add_options()("abslog", "Path to log file", cxxopts::value<std::filesystem::path>(ServerOptions.AbsLogFile));
+ options.add_options()("config", "Path to Lua config file", cxxopts::value<std::filesystem::path>(ServerOptions.ConfigFile));
options
- .add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value<int>(GlobalOptions.OwnerPid), "<identifier>");
+ .add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value<int>(ServerOptions.OwnerPid), "<identifier>");
options.add_option("lifetime",
"",
"child-id",
"Specify id which can be used to signal parent",
- cxxopts::value<std::string>(GlobalOptions.ChildId),
+ cxxopts::value<std::string>(ServerOptions.ChildId),
"<identifier>");
#if ZEN_PLATFORM_WINDOWS
@@ -114,13 +117,13 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"install",
"Install zenserver as a Windows service",
- cxxopts::value<bool>(GlobalOptions.InstallService),
+ cxxopts::value<bool>(ServerOptions.InstallService),
"");
options.add_option("lifetime",
"",
"uninstall",
"Uninstall zenserver as a Windows service",
- cxxopts::value<bool>(GlobalOptions.UninstallService),
+ cxxopts::value<bool>(ServerOptions.UninstallService),
"");
#endif
@@ -128,14 +131,14 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"http",
"Select HTTP server implementation (asio|httpsys|null)",
- cxxopts::value<std::string>(GlobalOptions.HttpServerClass)->default_value(DefaultHttp),
+ cxxopts::value<std::string>(ServerOptions.HttpServerClass)->default_value(DefaultHttp),
"<http class>");
options.add_option("network",
"p",
"port",
"Select HTTP port",
- cxxopts::value<int>(GlobalOptions.BasePort)->default_value("1337"),
+ cxxopts::value<int>(ServerOptions.BasePort)->default_value("1337"),
"<port number>");
#if ZEN_ENABLE_MESH
@@ -143,7 +146,7 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"m",
"mesh",
"Enable mesh network",
- cxxopts::value<bool>(ServiceConfig.MeshEnabled)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.MeshEnabled)->default_value("false"),
"");
#endif
@@ -151,7 +154,7 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"crash",
"Simulate a crash",
- cxxopts::value<bool>(ServiceConfig.ShouldCrash)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.ShouldCrash)->default_value("false"),
"");
std::string UpstreamCachePolicyOptions;
@@ -166,105 +169,105 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
"",
"upstream-jupiter-url",
"URL to a Jupiter instance",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Url)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-url",
"URL to the OAuth provier",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthProvider)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthProvider)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-clientid",
"The OAuth client ID",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-oauth-clientsecret",
"The OAuth client secret",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-namespace",
"The Common Blob Store API namespace",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-namespace-ddc",
"The lecacy DDC namespace",
- cxxopts::value<std::string>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""),
+ cxxopts::value<std::string>(ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-jupiter-prod",
"Enable Jupiter upstream caching using production settings",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseProductionSettings)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseProductionSettings)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-jupiter-dev",
"Enable Jupiter upstream caching using development settings",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-jupiter-use-legacy-ddc",
"Whether to store derived data using the legacy endpoint",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-zen-url",
"URL to remote Zen server. Use a comma separated list to choose the one with the best latency.",
- cxxopts::value<std::vector<std::string>>(ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls)->default_value(""),
+ cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Urls)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-zen-dns",
"DNS that resolves to one or more Zen server instance(s)",
- cxxopts::value<std::vector<std::string>>(ServiceConfig.UpstreamCacheConfig.ZenConfig.Dns)->default_value(""),
+ cxxopts::value<std::vector<std::string>>(ServerOptions.UpstreamCacheConfig.ZenConfig.Dns)->default_value(""),
"");
options.add_option("cache",
"",
"upstream-thread-count",
"Number of threads used for upstream procsssing",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.UpstreamThreadCount)->default_value("4"),
"");
options.add_option("cache",
"",
"upstream-stats",
"Collect performance metrics for upstream endpoints",
- cxxopts::value<bool>(ServiceConfig.UpstreamCacheConfig.StatsEnabled)->default_value("false"),
+ cxxopts::value<bool>(ServerOptions.UpstreamCacheConfig.StatsEnabled)->default_value("false"),
"");
options.add_option("cache",
"",
"upstream-connect-timeout-ms",
"Connect timeout in millisecond(s). Default 5000 ms.",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.ConnectTimeoutMilliseconds)->default_value("5000"),
"");
options.add_option("cache",
"",
"upstream-timeout-ms",
"Timeout in millisecond(s). Default 0 ms",
- cxxopts::value<int32_t>(ServiceConfig.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"),
+ cxxopts::value<int32_t>(ServerOptions.UpstreamCacheConfig.TimeoutMilliseconds)->default_value("0"),
"");
try
@@ -279,7 +282,16 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
exit(0);
}
- ServiceConfig.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions);
+ ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions);
+
+ if (!ServerOptions.ConfigFile.empty())
+ {
+ ParseConfigFile(ServerOptions.ConfigFile, ServerOptions);
+ }
+ else
+ {
+ ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions);
+ }
}
catch (cxxopts::OptionParseException& e)
{
@@ -288,32 +300,25 @@ ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, Z
throw;
}
- if (GlobalOptions.DataDir.empty())
+ if (ServerOptions.DataDir.empty())
{
- GlobalOptions.DataDir = PickDefaultStateDirectory();
+ ServerOptions.DataDir = PickDefaultStateDirectory();
}
}
void
-ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& ServiceConfig)
+ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions)
{
using namespace fmt::literals;
- std::filesystem::path ConfigScript = DataRoot / "zen_cfg.lua";
- zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(ConfigScript.native().c_str());
+ zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(Path.native().c_str());
if (LuaScript)
{
sol::state lua;
- // Provide some context to help derive defaults
- lua.set("dataroot", DataRoot.native());
-
lua.open_libraries(sol::lib::base);
- // We probably want to limit the scope of this so the script won't see
- // any more than it needs to
-
lua.set_function("getenv", [&](const std::string env) -> sol::object {
std::wstring EnvVarValue;
size_t RequiredSize = 0;
@@ -345,14 +350,50 @@ ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& Serv
}
catch (std::exception& e)
{
- ZEN_ERROR("config failure: {}", e.what());
+ throw std::runtime_error("failed to load config script ('{}'): {}"_format(Path, e.what()).c_str());
+ }
- throw std::runtime_error("failed to run global config script ('{}'): {}"_format(ConfigScript, e.what()).c_str());
+ if (sol::optional<sol::table> ServerConfig = lua["server"])
+ {
+ if (ServerOptions.DataDir.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["datadir"])
+ {
+ ServerOptions.DataDir = Opt.value();
+ }
+ }
+
+ if (ServerOptions.ContentDir.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["contentdir"])
+ {
+ ServerOptions.ContentDir = Opt.value();
+ }
+ }
+
+ if (ServerOptions.AbsLogFile.empty())
+ {
+ if (sol::optional<std::string> Opt = ServerConfig.value()["abslog"])
+ {
+ ServerOptions.AbsLogFile = Opt.value();
+ }
+ }
+
+ ServerOptions.IsDebug = ServerConfig->get_or("debug", ServerOptions.IsDebug);
}
+ if (sol::optional<sol::table> NetworkConfig = lua["network"])
+ {
+ if (sol::optional<std::string> Opt = NetworkConfig.value()["httpserverclass"])
+ {
+ ServerOptions.HttpServerClass = Opt.value();
+ }
+
+ ServerOptions.BasePort = NetworkConfig->get_or<int>("port", ServerOptions.BasePort);
#if ZEN_ENABLE_MESH
- ServiceConfig.MeshEnabled = lua["mesh"]["enable"].get_or(ServiceConfig.MeshEnabled);
+ ServerOptions.MeshEnabled = NetworkConfig->get_or<bool>("meshenabled", ServerOptions.MeshEnabled);
#endif
+ }
auto UpdateStringValueFromConfig = [](const sol::table& Table, std::string_view Key, std::string& OutValue) {
// Update the specified config value unless it has been set, i.e. from command line
@@ -362,56 +403,69 @@ ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& Serv
}
};
- if (sol::optional<sol::table> StructuredCacheConfig = lua["structuredcache"])
+ if (sol::optional<sol::table> StructuredCacheConfig = lua["cache"])
{
- ServiceConfig.StructuredCacheEnabled = StructuredCacheConfig->get_or("enable", ServiceConfig.StructuredCacheEnabled);
+ ServerOptions.StructuredCacheEnabled = StructuredCacheConfig->get_or("enable", ServerOptions.StructuredCacheEnabled);
if (auto UpstreamConfig = StructuredCacheConfig->get<sol::optional<sol::table>>("upstream"))
{
- std::string Policy = UpstreamConfig->get_or("policy", std::string());
- ServiceConfig.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(Policy);
- ServiceConfig.UpstreamCacheConfig.UpstreamThreadCount = UpstreamConfig->get_or("upstreamthreadcount", 4);
+ std::string Policy = UpstreamConfig->get_or("policy", std::string());
+ ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(Policy);
+ ServerOptions.UpstreamCacheConfig.UpstreamThreadCount =
+ UpstreamConfig->get_or("upstreamthreadcount", ServerOptions.UpstreamCacheConfig.UpstreamThreadCount);
if (auto JupiterConfig = UpstreamConfig->get<sol::optional<sol::table>>("jupiter"))
{
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("url"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.Url);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.Url);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthprovider"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthProvider);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthProvider);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthclientid"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientId);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientId);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("oauthclientsecret"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.OAuthClientSecret);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("namespace"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.Namespace);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.Namespace);
UpdateStringValueFromConfig(JupiterConfig.value(),
std::string_view("ddcnamespace"),
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.DdcNamespace);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.DdcNamespace);
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings =
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings =
JupiterConfig->get_or("usedevelopmentsettings",
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseDevelopmentSettings);
- ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc =
- JupiterConfig->get_or("uselegacyddc", ServiceConfig.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc);
+ ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc =
+ JupiterConfig->get_or("uselegacyddc", ServerOptions.UpstreamCacheConfig.JupiterConfig.UseLegacyDdc);
};
if (auto ZenConfig = UpstreamConfig->get<sol::optional<sol::table>>("zen"))
{
if (auto Url = ZenConfig.value().get<sol::optional<std::string>>("url"))
{
- ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls.push_back(Url.value());
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Url.value());
}
else if (auto Urls = ZenConfig.value().get<sol::optional<sol::table>>("url"))
{
for (const auto& Kv : Urls.value())
{
- ServiceConfig.UpstreamCacheConfig.ZenConfig.Urls.push_back(Kv.second.as<std::string>());
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Urls.push_back(Kv.second.as<std::string>());
+ }
+ }
+
+ if (auto Dns = ZenConfig.value().get<sol::optional<std::string>>("dns"))
+ {
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Dns.value());
+ }
+ else if (auto DnsArray = ZenConfig.value().get<sol::optional<sol::table>>("dns"))
+ {
+ for (const auto& Kv : DnsArray.value())
+ {
+ ServerOptions.UpstreamCacheConfig.ZenConfig.Dns.push_back(Kv.second.as<std::string>());
}
}
}
diff --git a/zenserver/config.h b/zenserver/config.h
index f6858b940..19fba71a3 100644
--- a/zenserver/config.h
+++ b/zenserver/config.h
@@ -17,23 +17,6 @@
# define ZEN_USE_EXEC 0
#endif
-struct ZenServerOptions
-{
- bool IsDebug = false;
- bool IsTest = false;
- bool IsDedicated = false; // Indicates a dedicated/shared instance, with larger resource requirements
- int BasePort = 1337; // Service listen port (used for both UDP and TCP)
- int OwnerPid = 0; // Parent process id (zero for standalone)
- std::string ChildId; // Id assigned by parent process (used for lifetime management)
- bool InstallService = false; // Flag used to initiate service install (temporary)
- bool UninstallService = false; // Flag used to initiate service uninstall (temporary)
- std::string LogId; // Id for tagging log output
- std::filesystem::path DataDir; // Root directory for state (used for testing)
- std::filesystem::path ContentDir; // Root directory for serving frontend content (experimental)
- std::string HttpServerClass; // Choice of HTTP server implementation
- std::filesystem::path AbsLogFile; // Absolute path to main log file
-};
-
struct ZenUpstreamJupiterConfig
{
std::string Url;
@@ -72,16 +55,29 @@ struct ZenUpstreamCacheConfig
bool StatsEnabled = false;
};
-struct ZenServiceConfig
+struct ZenServerOptions
{
- bool StructuredCacheEnabled = true;
- bool ShouldCrash = false; // Option for testing crash handling
- bool IsFirstRun = false;
+ ZenUpstreamCacheConfig UpstreamCacheConfig;
+ std::filesystem::path DataDir; // Root directory for state (used for testing)
+ std::filesystem::path ContentDir; // Root directory for serving frontend content (experimental)
+ std::filesystem::path AbsLogFile; // Absolute path to main log file
+ std::filesystem::path ConfigFile; // Path to Lua config file
+ std::string ChildId; // Id assigned by parent process (used for lifetime management)
+ std::string LogId; // Id for tagging log output
+ std::string HttpServerClass; // Choice of HTTP server implementation
+ int BasePort = 1337; // Service listen port (used for both UDP and TCP)
+ int OwnerPid = 0; // Parent process id (zero for standalone)
+ bool InstallService = false; // Flag used to initiate service install (temporary)
+ bool UninstallService = false; // Flag used to initiate service uninstall (temporary)
+ bool IsDebug = false;
+ bool IsTest = false;
+ bool IsDedicated = false; // Indicates a dedicated/shared instance, with larger resource requirements
+ bool StructuredCacheEnabled = true;
+ bool ShouldCrash = false; // Option for testing crash handling
+ bool IsFirstRun = false;
#if ZEN_ENABLE_MESH
bool MeshEnabled = false; // Experimental p2p mesh discovery
#endif
- ZenUpstreamCacheConfig UpstreamCacheConfig;
};
-void ParseGlobalCliOptions(int argc, char* argv[], ZenServerOptions& GlobalOptions, ZenServiceConfig& ServiceConfig);
-void ParseServiceConfig(const std::filesystem::path& DataRoot, ZenServiceConfig& ServiceConfig);
+void ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions);
diff --git a/zenserver/diag/diagsvcs.cpp b/zenserver/diag/diagsvcs.cpp
index edd9b782e..eed23dff2 100644
--- a/zenserver/diag/diagsvcs.cpp
+++ b/zenserver/diag/diagsvcs.cpp
@@ -61,8 +61,7 @@ HttpHealthService::HttpHealthService()
Writer << "BuildVersion"sv << m_HealthInfo.BuildVersion;
Writer << "HttpServerClass"sv << m_HealthInfo.HttpServerClass;
- ExtendableStringBuilder<256> Sb;
- HttpReq.WriteResponse(HttpResponseCode::OK, HttpContentType::kJSON, Writer.Save().ToJson(Sb).ToView());
+ HttpReq.WriteResponse(HttpResponseCode::OK, Writer.Save());
},
HttpVerb::kGet);
diff --git a/zenserver/upstream/jupiter.cpp b/zenserver/upstream/jupiter.cpp
index 9223ea0f4..1f82f4a04 100644
--- a/zenserver/upstream/jupiter.cpp
+++ b/zenserver/upstream/jupiter.cpp
@@ -673,6 +673,7 @@ CloudCacheSession::GetComputeUpdates(std::string_view ChannelId, const uint32_t
Session.SetOption(cpr::Url{Uri.c_str()});
Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/x-ue-cb"}});
+ Session.SetOption(cpr::Body{});
cpr::Response Response = Session.Post();
ZEN_DEBUG("POST {}", Response);
@@ -708,6 +709,7 @@ CloudCacheSession::GetObjectTree(const IoHash& Key)
Session.SetOption(cpr::Url{Uri.c_str()});
Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/octet-stream"}});
+ Session.SetOption(cpr::Body{});
cpr::Response Response = Session.Get();
ZEN_DEBUG("GET {}", Response);
@@ -772,6 +774,7 @@ CloudCacheSession::CacheTypeExists(std::string_view TypeId, const IoHash& Key)
Session.SetOption(cpr::Url{Uri.c_str()});
Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}});
+ Session.SetOption(cpr::Body{});
cpr::Response Response = Session.Head();
ZEN_DEBUG("HEAD {}", Response);
@@ -810,6 +813,7 @@ CloudCacheSession::CacheTypeExists(std::string_view TypeId, const std::set<IoHas
Session.SetOption(cpr::Url{Uri.c_str()});
Session.SetOption(cpr::Header{{"Authorization", AccessToken.Value}, {"Accept", "application/x-ue-cb"}});
+ Session.SetOption(cpr::Body{});
cpr::Response Response = Session.Post();
ZEN_DEBUG("POST {}", Response);
diff --git a/zenserver/upstream/upstreamapply.cpp b/zenserver/upstream/upstreamapply.cpp
index 651c2dcc8..0118902a6 100644
--- a/zenserver/upstream/upstreamapply.cpp
+++ b/zenserver/upstream/upstreamapply.cpp
@@ -1140,11 +1140,11 @@ struct UpstreamApplyStats
UpstreamApplyEndpointStats& Stats = Ep->Stats();
const uint64_t PostCount = Stats.PostCount;
const uint64_t CompleteCount = Stats.CompleteCount;
- const uint64_t UpdateCount = Stats.UpdateCount;
- const double DownBytes = Stats.DownBytes;
- const double SecondsDown = Stats.SecondsDown;
- const double UpBytes = Stats.UpBytes;
- const double SecondsUp = Stats.SecondsUp;
+ // const uint64_t UpdateCount = Stats.UpdateCount;
+ const double DownBytes = Stats.DownBytes;
+ const double SecondsDown = Stats.SecondsDown;
+ const double UpBytes = Stats.UpBytes;
+ const double SecondsUp = Stats.SecondsUp;
const double UpSpeed = UpBytes > 0 ? UpBytes / SecondsUp : 0.0;
const double DownSpeed = DownBytes > 0 ? DownBytes / SecondsDown : 0.0;
@@ -1284,8 +1284,8 @@ public:
UpstreamApplyEndpointStats& Stats = Ep->Stats();
const uint64_t PostCount = Stats.PostCount;
const uint64_t CompleteCount = Stats.CompleteCount;
- const uint64_t UpdateCount = Stats.UpdateCount;
- const double CompleteRate = CompleteCount > 0 ? (double(PostCount) / double(CompleteCount)) : 0.0;
+ // const uint64_t UpdateCount = Stats.UpdateCount;
+ const double CompleteRate = CompleteCount > 0 ? (double(PostCount) / double(CompleteCount)) : 0.0;
Status << "post_count" << PostCount;
Status << "complete_count" << PostCount;
diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp
index 567f1d40b..e9c41d070 100644
--- a/zenserver/zenserver.cpp
+++ b/zenserver/zenserver.cpp
@@ -151,12 +151,12 @@ namespace utils {
class ZenServer : public IHttpStatusProvider
{
public:
- void Initialize(ZenServiceConfig& ServiceConfig, const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry)
+ void Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry)
{
using namespace fmt::literals;
m_ServerEntry = ServerEntry;
- m_DebugOptionForcedCrash = ServiceConfig.ShouldCrash;
+ m_DebugOptionForcedCrash = ServerOptions.ShouldCrash;
const int ParentPid = ServerOptions.OwnerPid;
if (ParentPid)
@@ -188,7 +188,7 @@ public:
throw std::runtime_error("Failed to create mutex '{}' - is another instance already running?"_format(MutexName).c_str());
}
- InitializeState(ServiceConfig);
+ InitializeState(ServerOptions);
m_HealthService.SetHealthInfo({.DataRoot = m_DataRoot,
.AbsLogPath = ServerOptions.AbsLogFile,
@@ -237,9 +237,9 @@ public:
zen::CreateDirectories(ApplySandboxDir);
m_HttpFunctionService = std::make_unique<zen::HttpFunctionService>(*m_CasStore, *m_CidStore, ApplySandboxDir);
- if (ServiceConfig.StructuredCacheEnabled)
+ if (ServerOptions.StructuredCacheEnabled)
{
- InitializeStructuredCache(ServiceConfig);
+ InitializeStructuredCache(ServerOptions);
}
else
{
@@ -247,7 +247,7 @@ public:
}
#if ZEN_ENABLE_MESH
- if (ServiceConfig.MeshEnabled)
+ if (ServerOptions.MeshEnabled)
{
StartMesh(BasePort);
}
@@ -293,8 +293,8 @@ public:
}
}
- void InitializeState(ZenServiceConfig& ServiceConfig);
- void InitializeStructuredCache(ZenServiceConfig& ServiceConfig);
+ void InitializeState(const ZenServerOptions& ServerOptions);
+ void InitializeStructuredCache(const ZenServerOptions& ServerOptions);
#if ZEN_ENABLE_MESH
void StartMesh(int BasePort)
@@ -553,7 +553,7 @@ ZenServer::OnReady()
}
void
-ZenServer::InitializeState(ZenServiceConfig& ServiceConfig)
+ZenServer::InitializeState(const ZenServerOptions& ServerOptions)
{
// Check root manifest to deal with schema versioning
@@ -566,7 +566,7 @@ ZenServer::InitializeState(ZenServiceConfig& ServiceConfig)
if (ManifestData.ErrorCode)
{
- if (ServiceConfig.IsFirstRun)
+ if (ServerOptions.IsFirstRun)
{
ZEN_INFO("Initializing state at '{}'", m_DataRoot);
@@ -650,7 +650,7 @@ ZenServer::InitializeState(ZenServiceConfig& ServiceConfig)
}
void
-ZenServer::InitializeStructuredCache(ZenServiceConfig& ServiceConfig)
+ZenServer::InitializeStructuredCache(const ZenServerOptions& ServerOptions)
{
using namespace std::literals;
auto ValueOrDefault = [](std::string_view Value, std::string_view Default) { return Value.empty() ? Default : Value; };
@@ -659,13 +659,13 @@ ZenServer::InitializeStructuredCache(ZenServiceConfig& ServiceConfig)
m_CacheStore = std::make_unique<ZenCacheStore>(m_Gc, m_DataRoot / "cache");
std::unique_ptr<zen::UpstreamCache> UpstreamCache;
- if (ServiceConfig.UpstreamCacheConfig.CachePolicy != UpstreamCachePolicy::Disabled)
+ if (ServerOptions.UpstreamCacheConfig.CachePolicy != UpstreamCachePolicy::Disabled)
{
- const ZenUpstreamCacheConfig& UpstreamConfig = ServiceConfig.UpstreamCacheConfig;
+ const ZenUpstreamCacheConfig& UpstreamConfig = ServerOptions.UpstreamCacheConfig;
zen::UpstreamCacheOptions UpstreamOptions;
- UpstreamOptions.ReadUpstream = (uint8_t(ServiceConfig.UpstreamCacheConfig.CachePolicy) & uint8_t(UpstreamCachePolicy::Read)) != 0;
- UpstreamOptions.WriteUpstream = (uint8_t(ServiceConfig.UpstreamCacheConfig.CachePolicy) & uint8_t(UpstreamCachePolicy::Write)) != 0;
+ UpstreamOptions.ReadUpstream = (uint8_t(ServerOptions.UpstreamCacheConfig.CachePolicy) & uint8_t(UpstreamCachePolicy::Read)) != 0;
+ UpstreamOptions.WriteUpstream = (uint8_t(ServerOptions.UpstreamCacheConfig.CachePolicy) & uint8_t(UpstreamCachePolicy::Write)) != 0;
if (UpstreamConfig.UpstreamThreadCount < 32)
{
@@ -770,11 +770,7 @@ ZenServer::InitializeStructuredCache(ZenServiceConfig& ServiceConfig)
class ZenWindowsService : public WindowsService
{
public:
- ZenWindowsService(ZenServerOptions& GlobalOptions, ZenServiceConfig& ServiceConfig)
- : m_GlobalOptions(GlobalOptions)
- , m_ServiceConfig(ServiceConfig)
- {
- }
+ ZenWindowsService(ZenServerOptions& ServerOptions) : m_ServerOptions(ServerOptions) {}
ZenWindowsService(const ZenWindowsService&) = delete;
ZenWindowsService& operator=(const ZenWindowsService&) = delete;
@@ -782,8 +778,7 @@ public:
virtual int Run() override;
private:
- ZenServerOptions& m_GlobalOptions;
- ZenServiceConfig& m_ServiceConfig;
+ ZenServerOptions& m_ServerOptions;
zen::LockFile m_LockFile;
};
@@ -802,8 +797,7 @@ ZenWindowsService::Run()
auto _ = zen::MakeGuard([] { sentry_close(); });
#endif
- auto& GlobalOptions = m_GlobalOptions;
- auto& ServiceConfig = m_ServiceConfig;
+ auto& ServerOptions = m_ServerOptions;
try
{
@@ -811,13 +805,13 @@ ZenWindowsService::Run()
std::error_code Ec;
- std::filesystem::path LockFilePath = GlobalOptions.DataDir / ".lock";
+ std::filesystem::path LockFilePath = ServerOptions.DataDir / ".lock";
bool IsReady = false;
auto MakeLockData = [&] {
CbObjectWriter Cbo;
- Cbo << "pid" << _getpid() << "data" << ToUtf8(GlobalOptions.DataDir) << "port" << GlobalOptions.BasePort << "session_id"
+ Cbo << "pid" << _getpid() << "data" << ToUtf8(ServerOptions.DataDir) << "port" << ServerOptions.BasePort << "session_id"
<< GetSessionId() << "ready" << IsReady;
return Cbo.Save();
};
@@ -831,21 +825,15 @@ ZenWindowsService::Run()
std::exit(99);
}
- InitializeLogging(GlobalOptions);
-
- // Prototype config system, we'll see how this pans out
- //
- // TODO: we need to report any parse errors here
-
- ParseServiceConfig(GlobalOptions.DataDir, /* out */ ServiceConfig);
+ InitializeLogging(ServerOptions);
- ZEN_INFO(ZEN_APP_NAME " - starting on port {}, build '{}'", GlobalOptions.BasePort, BUILD_VERSION);
+ ZEN_INFO(ZEN_APP_NAME " - starting on port {}, build '{}'", ServerOptions.BasePort, BUILD_VERSION);
ZenServerState ServerState;
ServerState.Initialize();
ServerState.Sweep();
- ZenServerState::ZenServerEntry* Entry = ServerState.Lookup(GlobalOptions.BasePort);
+ ZenServerState::ZenServerEntry* Entry = ServerState.Lookup(ServerOptions.BasePort);
if (Entry)
{
@@ -853,34 +841,34 @@ ZenWindowsService::Run()
ZEN_WARN("Looks like there is already a process listening to this port (pid: {})", Entry->Pid);
- if (GlobalOptions.OwnerPid)
+ if (ServerOptions.OwnerPid)
{
- Entry->AddSponsorProcess(GlobalOptions.OwnerPid);
+ Entry->AddSponsorProcess(ServerOptions.OwnerPid);
std::exit(0);
}
}
- Entry = ServerState.Register(GlobalOptions.BasePort);
+ Entry = ServerState.Register(ServerOptions.BasePort);
- if (GlobalOptions.OwnerPid)
+ if (ServerOptions.OwnerPid)
{
- Entry->AddSponsorProcess(GlobalOptions.OwnerPid);
+ Entry->AddSponsorProcess(ServerOptions.OwnerPid);
}
std::unique_ptr<std::thread> ShutdownThread;
std::unique_ptr<zen::NamedEvent> ShutdownEvent;
zen::ExtendableStringBuilder<64> ShutdownEventName;
- ShutdownEventName << "Zen_" << GlobalOptions.BasePort << "_Shutdown";
+ ShutdownEventName << "Zen_" << ServerOptions.BasePort << "_Shutdown";
ShutdownEvent.reset(new zen::NamedEvent{ShutdownEventName});
ZenServer Server;
- Server.SetDataRoot(GlobalOptions.DataDir);
- Server.SetContentRoot(GlobalOptions.ContentDir);
- Server.SetTestMode(GlobalOptions.IsTest);
- Server.SetDedicatedMode(GlobalOptions.IsDedicated);
- Server.Initialize(ServiceConfig, GlobalOptions, Entry);
+ Server.SetDataRoot(ServerOptions.DataDir);
+ Server.SetContentRoot(ServerOptions.ContentDir);
+ Server.SetTestMode(ServerOptions.IsTest);
+ Server.SetDedicatedMode(ServerOptions.IsDedicated);
+ Server.Initialize(ServerOptions, Entry);
// Monitor shutdown signals
@@ -901,9 +889,9 @@ ZenWindowsService::Run()
m_LockFile.Update(MakeLockData(), Ec);
- if (!GlobalOptions.ChildId.empty())
+ if (!ServerOptions.ChildId.empty())
{
- zen::NamedEvent ParentEvent{GlobalOptions.ChildId};
+ zen::NamedEvent ParentEvent{ServerOptions.ChildId};
ParentEvent.Set();
}
});
@@ -961,25 +949,24 @@ main(int argc, char* argv[])
try
{
- ZenServerOptions GlobalOptions;
- ZenServiceConfig ServiceConfig;
- ParseGlobalCliOptions(argc, argv, GlobalOptions, ServiceConfig);
+ ZenServerOptions ServerOptions;
+ ParseCliOptions(argc, argv, ServerOptions);
- if (!std::filesystem::exists(GlobalOptions.DataDir))
+ if (!std::filesystem::exists(ServerOptions.DataDir))
{
- ServiceConfig.IsFirstRun = true;
- std::filesystem::create_directories(GlobalOptions.DataDir);
+ ServerOptions.IsFirstRun = true;
+ std::filesystem::create_directories(ServerOptions.DataDir);
}
#if ZEN_PLATFORM_WINDOWS
- if (GlobalOptions.InstallService)
+ if (ServerOptions.InstallService)
{
WindowsService::Install();
std::exit(0);
}
- if (GlobalOptions.UninstallService)
+ if (ServerOptions.UninstallService)
{
WindowsService::Delete();
@@ -987,7 +974,7 @@ main(int argc, char* argv[])
}
#endif
- ZenWindowsService App(GlobalOptions, ServiceConfig);
+ ZenWindowsService App(ServerOptions);
return App.ServiceMain();
}
catch (std::exception& Ex)