From 372d3a8a1ff65e53d139a7ee1db022d8cfa55982 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Thu, 16 Nov 2023 17:20:52 +0100 Subject: add zenserver state snapshot support (#543) this introduces a --snapshot-dir command line option to zenserver which specifies a directory which will be propagated to the persistence root directory on start-up. This is most powerful with file systems which support block cloning, such as ReFS on Windows. This allows even very large state snapshots to be used repeatedly without having to worry about mutating the original dataset on disk. When using ReFS the state copy for even large state directories can be very fast since the duration is primarily proportional to the number of files in the tree rather than the size of the files being cloned. The storage requirements are also minimal as all data will be handled in a copy-on-write manner. --- src/zenserver/config.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/zenserver/config.cpp') diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index e7edd5745..e33c6ff70 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -938,6 +938,7 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) std::string AbsLogFile; std::string ConfigFile; std::string OutputConfigFile; + std::string BaseSnapshotDir; cxxopts::Options options("zenserver", "Zen Server"); options.add_options()("dedicated", @@ -951,6 +952,9 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) options.add_options()("t, test", "Enable test mode", cxxopts::value(ServerOptions.IsTest)->default_value("false")); options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value(ServerOptions.LogId)); options.add_options()("data-dir", "Specify persistence root", cxxopts::value(DataDir)); + options.add_options()("snapshot-dir", + "Specify a snapshot of server state to mirror into the persistence root at startup", + cxxopts::value(BaseSnapshotDir)); options.add_options()("content-dir", "Frontend content directory", cxxopts::value(ContentDir)); options.add_options()("abslog", "Path to log file", cxxopts::value(AbsLogFile)); options.add_options()("config", "Path to Lua config file", cxxopts::value(ConfigFile)); @@ -1362,11 +1366,21 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) } ServerOptions.DataDir = MakeSafePath(DataDir); + ServerOptions.BaseSnapshotDir = MakeSafePath(BaseSnapshotDir); ServerOptions.ContentDir = MakeSafePath(ContentDir); ServerOptions.AbsLogFile = MakeSafePath(AbsLogFile); ServerOptions.ConfigFile = MakeSafePath(ConfigFile); ServerOptions.UpstreamCacheConfig.CachePolicy = ParseUpstreamCachePolicy(UpstreamCachePolicyOptions); + if (!BaseSnapshotDir.empty()) + { + if (DataDir.empty()) + throw zen::OptionParseException("You must explicitly specify a data directory when specifying a base snapshot"); + + if (!std::filesystem::is_directory(ServerOptions.BaseSnapshotDir)) + throw OptionParseException(fmt::format("Snapshot directory must be a directory: '{}", BaseSnapshotDir)); + } + if (OpenIdProviderUrl.empty() == false) { if (OpenIdClientId.empty()) -- cgit v1.2.3