aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-09-01 07:29:41 -0400
committerGitHub <[email protected]>2023-09-01 13:29:41 +0200
commita165efeaf58dc7336e40d812359b0fc2ce0e7a83 (patch)
tree6c7aa1dd0cbb7f0fa751f7bc1bff9b3e8205e1da /src
parent0.2.19 (diff)
downloadzen-a165efeaf58dc7336e40d812359b0fc2ce0e7a83.tar.xz
zen-a165efeaf58dc7336e40d812359b0fc2ce0e7a83.zip
add `--write-config` to zenserver options (#382)
- Feature: `zen up` command has two new command line options - `--config <file_path>` tells zenserver to start with a specific config file - `--owner-pid <pid>` tells zenserver to start with a owning process id - Feature: `zen attach` command to add additional owning processes to a running zenserver instance - `--owner-pid <pid>` adds pid to running zenserver instance list of owning processes - Feature: `--write-config` command line option for zenserver - `--write-config <file_path>` path to a file which will contain a lua config file for zenserver combining all command line options and optional lua config files - Improvement: `zen up` command will check if zenserver is currently running before starting up a new instance
Diffstat (limited to 'src')
-rw-r--r--src/zen/cmds/up.cpp76
-rw-r--r--src/zen/cmds/up.h18
-rw-r--r--src/zen/zen.cpp2
-rw-r--r--src/zenserver/config.cpp30
4 files changed, 115 insertions, 11 deletions
diff --git a/src/zen/cmds/up.cpp b/src/zen/cmds/up.cpp
index 69bcbe829..d1ae0794a 100644
--- a/src/zen/cmds/up.cpp
+++ b/src/zen/cmds/up.cpp
@@ -12,6 +12,13 @@ namespace zen {
UpCommand::UpCommand()
{
+ m_Options.add_option("lifetime",
+ "",
+ "owner-pid",
+ "Specify owning process id",
+ cxxopts::value(m_OwnerPid)->default_value("0"),
+ "<identifier>");
+ m_Options.add_options()("config", "Path to Lua config file", cxxopts::value(m_ConfigFile));
}
UpCommand::~UpCommand() = default;
@@ -21,12 +28,34 @@ UpCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
ZEN_UNUSED(GlobalOptions, argc, argv);
- std::filesystem::path ExePath = zen::GetRunningExecutablePath();
+ if (!ParseOptions(argc, argv))
+ {
+ return 0;
+ }
- ZenServerEnvironment ServerEnvironment;
+ {
+ ZenServerState State;
+ if (State.InitializeReadOnly())
+ {
+ ZEN_CONSOLE("Zen server already running");
+ return 0;
+ }
+ }
+
+ std::filesystem::path ExePath = zen::GetRunningExecutablePath();
+ ZenServerEnvironment ServerEnvironment;
ServerEnvironment.Initialize(ExePath.parent_path());
ZenServerInstance Server(ServerEnvironment);
- Server.SpawnServer();
+ if (m_OwnerPid != 0)
+ {
+ Server.SetOwnerPid(m_OwnerPid);
+ }
+ std::string AdditionalArguments;
+ if (!m_ConfigFile.empty())
+ {
+ AdditionalArguments = fmt::format("--config {}", m_ConfigFile);
+ }
+ Server.SpawnServer(0, AdditionalArguments);
int Timeout = 10000;
@@ -44,6 +73,45 @@ UpCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
//////////////////////////////////////////////////////////////////////////
+AttachCommand::AttachCommand()
+{
+ m_Options.add_option("", "p", "port", "Host port", cxxopts::value(m_Port)->default_value("1337"), "<hostport>");
+ m_Options.add_option("lifetime", "", "owner-pid", "Specify owning process id", cxxopts::value(m_OwnerPid), "<identifier>");
+}
+
+AttachCommand::~AttachCommand() = default;
+
+int
+AttachCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
+{
+ ZEN_UNUSED(GlobalOptions, argc, argv);
+
+ if (!ParseOptions(argc, argv))
+ {
+ return 0;
+ }
+
+ ZenServerState Instance;
+ Instance.Initialize();
+ ZenServerState::ZenServerEntry* Entry = Instance.Lookup(m_Port);
+ if (!Entry)
+ {
+ ZEN_WARN("no zen server instance to add sponsor process to");
+ return 1;
+ }
+
+ if (!Entry->AddSponsorProcess(m_OwnerPid))
+ {
+ ZEN_WARN("unable to add sponsor process to running zen server instance");
+ return 1;
+ }
+
+ ZEN_CONSOLE("added sponsor process {} to running instance {} on port {}", m_OwnerPid, Entry->Pid.load(), m_Port);
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
DownCommand::DownCommand()
{
m_Options.add_option("", "p", "port", "Host port", cxxopts::value(m_Port)->default_value("1337"), "<hostport>");
@@ -97,7 +165,7 @@ DownCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
// Since we cannot obtain a handle to the process we are unable to block on the process
// handle to determine when the server has shut down. Thus we signal that we would like
- // a shutdown via the shutdown flag and then
+ // a shutdown via the shutdown flag and then exit.
ZEN_CONSOLE("requesting shutdown of server on port {}", m_Port);
Entry->SignalShutdownRequest();
diff --git a/src/zen/cmds/up.h b/src/zen/cmds/up.h
index 5af05541a..5b5c6a3f8 100644
--- a/src/zen/cmds/up.h
+++ b/src/zen/cmds/up.h
@@ -17,6 +17,24 @@ public:
private:
cxxopts::Options m_Options{"up", "Bring up zen service"};
+ uint16_t m_Port;
+ int m_OwnerPid;
+ std::string m_ConfigFile;
+};
+
+class AttachCommand : public ZenCmdBase
+{
+public:
+ AttachCommand();
+ ~AttachCommand();
+
+ virtual int Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
+ virtual cxxopts::Options& Options() override { return m_Options; }
+
+private:
+ cxxopts::Options m_Options{"attach", "Add a sponsor process to a running zen service"};
+ uint16_t m_Port;
+ int m_OwnerPid;
};
class DownCommand : public ZenCmdBase
diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp
index 204a91f74..f1cfe9796 100644
--- a/src/zen/zen.cpp
+++ b/src/zen/zen.cpp
@@ -216,6 +216,7 @@ main(int argc, char** argv)
StatusCommand StatusCmd;
TopCommand TopCmd;
UpCommand UpCmd;
+ AttachCommand AttachCmd;
VersionCommand VersionCmd;
#if ZEN_WITH_TESTS
RunTestsCommand RunTestsCmd;
@@ -263,6 +264,7 @@ main(int argc, char** argv)
{"status", &StatusCmd, "Show zen status"},
{"top", &TopCmd, "Monitor zen server activity"},
{"up", &UpCmd, "Bring zen server up"},
+ {"attach", &AttachCmd, "Add a sponsor process to a running zen service"},
{"version", &VersionCmd, "Get zen server version"},
#if ZEN_WITH_TESTS
{"runtests", &RunTestsCmd, "Run zen tests"},
diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp
index 2d286b02a..1f5a3eb21 100644
--- a/src/zenserver/config.cpp
+++ b/src/zenserver/config.cpp
@@ -10,6 +10,7 @@
#include <zencore/iobuffer.h>
#include <zencore/string.h>
#include <zenhttp/zenhttp.h>
+#include <zenutil/basicfile.h>
ZEN_THIRD_PARTY_INCLUDES_START
#include <fmt/format.h>
@@ -136,15 +137,15 @@ ParseBucketConfigs(std::span<std::string> Buckets)
}
static std::string
-MakeSafePath(const std::string& Path)
+MakeSafePath(const std::string_view Path)
{
#if ZEN_PLATFORM_WINDOWS
if (Path.empty())
{
- return Path;
+ return std::string(Path);
}
- std::string FixedPath = Path;
+ std::string FixedPath(Path);
std::replace(FixedPath.begin(), FixedPath.end(), '/', '\\');
if (!FixedPath.starts_with("\\\\?\\"))
{
@@ -152,7 +153,7 @@ MakeSafePath(const std::string& Path)
}
return FixedPath;
#else
- return Path;
+ return std::string(Path);
#endif
};
@@ -768,7 +769,10 @@ private:
} // namespace LuaConfig
void
-ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptions, const cxxopts::ParseResult& CmdLineResult)
+ParseConfigFile(const std::filesystem::path& Path,
+ ZenServerOptions& ServerOptions,
+ const cxxopts::ParseResult& CmdLineResult,
+ std::string_view OutputConfigFile)
{
using namespace std::literals;
@@ -923,6 +927,16 @@ ParseConfigFile(const std::filesystem::path& Path, ZenServerOptions& ServerOptio
{
LuaOptions.Touch("server.objectstore.buckets"sv);
}
+
+ if (!OutputConfigFile.empty())
+ {
+ std::filesystem::path WritePath(MakeSafePath(OutputConfigFile));
+ zen::ExtendableStringBuilder<512> ConfigStringBuilder;
+ LuaOptions.Print(ConfigStringBuilder, CmdLineResult);
+ zen::BasicFile Output;
+ Output.Open(WritePath, zen::BasicFile::Mode::kTruncate);
+ Output.Write(ConfigStringBuilder.Data(), ConfigStringBuilder.Size(), 0);
+ }
}
void
@@ -943,6 +957,7 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
std::string ContentDir;
std::string AbsLogFile;
std::string ConfigFile;
+ std::string OutputConfigFile;
cxxopts::Options options("zenserver", "Zen Server");
options.add_options()("dedicated",
@@ -956,6 +971,7 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
options.add_options()("content-dir", "Frontend content directory", cxxopts::value<std::string>(ContentDir));
options.add_options()("abslog", "Path to log file", cxxopts::value<std::string>(AbsLogFile));
options.add_options()("config", "Path to Lua config file", cxxopts::value<std::string>(ConfigFile));
+ options.add_options()("write-config", "Path to output Lua config file", cxxopts::value<std::string>(OutputConfigFile));
options.add_options()("no-sentry",
"Disable Sentry crash handler",
cxxopts::value<bool>(ServerOptions.NoSentry)->default_value("false"));
@@ -1380,11 +1396,11 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions)
if (!ServerOptions.ConfigFile.empty())
{
- ParseConfigFile(ServerOptions.ConfigFile, ServerOptions, result);
+ ParseConfigFile(ServerOptions.ConfigFile, ServerOptions, result, OutputConfigFile);
}
else
{
- ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions, result);
+ ParseConfigFile(ServerOptions.DataDir / "zen_cfg.lua", ServerOptions, result, OutputConfigFile);
}
ValidateOptions(ServerOptions);