diff options
| author | Per Larsson <[email protected]> | 2021-11-25 14:07:24 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2021-11-25 14:07:24 +0100 |
| commit | 522fbd01d25856c921bb1400b07ae900a0054627 (patch) | |
| tree | bf649ab7efe41c22661d77196fc52428911cdb57 | |
| parent | rpc: tactical checkin (diff) | |
| parent | Added support for loading Lua config file from CLI option and merged server/s... (diff) | |
| download | zen-522fbd01d25856c921bb1400b07ae900a0054627.tar.xz zen-522fbd01d25856c921bb1400b07ae900a0054627.zip | |
Merged main.
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | scripts/deploybuild.py | 22 | ||||
| -rw-r--r-- | xmake.lua | 50 | ||||
| -rw-r--r-- | zenhttp/httpasio.cpp | 122 | ||||
| -rw-r--r-- | zenserver-test/zenserver-test.cpp | 2 | ||||
| -rw-r--r-- | zenserver/config.cpp | 180 | ||||
| -rw-r--r-- | zenserver/config.h | 44 | ||||
| -rw-r--r-- | zenserver/diag/diagsvcs.cpp | 3 | ||||
| -rw-r--r-- | zenserver/upstream/jupiter.cpp | 4 | ||||
| -rw-r--r-- | zenserver/upstream/upstreamapply.cpp | 14 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 101 |
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!") @@ -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) |