diff options
| author | Martin Ridgers <[email protected]> | 2021-10-20 13:19:39 +0200 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-10-20 13:19:39 +0200 |
| commit | 13feae57532a1ad4d14feb5ee00f397fa6c370cc (patch) | |
| tree | 4bfdfe0aa239435baddef9ee64965c39ec7f6551 /zenserver/zenserver.cpp | |
| parent | Compile fixes due to std::fs::path's differing character types (diff) | |
| parent | zen server: Added root manifest, with support for explicit schema versioning (diff) | |
| download | zen-13feae57532a1ad4d14feb5ee00f397fa6c370cc.tar.xz zen-13feae57532a1ad4d14feb5ee00f397fa6c370cc.zip | |
Merged main
Diffstat (limited to 'zenserver/zenserver.cpp')
| -rw-r--r-- | zenserver/zenserver.cpp | 117 |
1 files changed, 101 insertions, 16 deletions
diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index c9b52604d..269db7394 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -1,6 +1,7 @@ // Copyright Epic Games, Inc. All Rights Reserved. #include <zencore/compactbinarybuilder.h> +#include <zencore/compactbinaryvalidation.h> #include <zencore/filesystem.h> #include <zencore/fmtutils.h> #include <zencore/iobuffer.h> @@ -40,6 +41,8 @@ ZEN_THIRD_PARTY_INCLUDES_END # define BUILD_VERSION ("dev-build") #endif +#define ZEN_SCHEMA_VERSION 1 + ////////////////////////////////////////////////////////////////////////// // We don't have any doctest code in this file but this is needed to bring // in some shared code into the executable @@ -154,6 +157,78 @@ public: throw std::runtime_error("Failed to create mutex '{}' - is another instance already running?"_format(MutexName).c_str()); } + // Check root manifest to deal with schema versioning + + bool WipeState = false; + std::string WipeReason = "Unspecified"; + + std::filesystem::path ManifestPath = m_DataRoot / "root_manifest"; + FileContents ManifestData = zen::ReadFile(ManifestPath); + + if (ManifestData.ErrorCode) + { + WipeState = true; + WipeReason = "No manifest present at '{}'"_format(ManifestPath); + } + else + { + IoBuffer Manifest = ManifestData.Flatten(); + + if (CbValidateError ValidationResult = ValidateCompactBinary(Manifest, CbValidateMode::All); + ValidationResult != CbValidateError::None) + { + ZEN_ERROR("Manifest validation failed: {}, state will be wiped", ValidationResult); + + WipeState = true; + WipeReason = "Validation of manifest at '{}' failed: {}"_format(ManifestPath, ValidationResult); + } + else + { + m_RootManifest = LoadCompactBinaryObject(Manifest); + + const int32_t ManifestVersion = m_RootManifest["schema_version"].AsInt32(0); + + if (ManifestVersion != ZEN_SCHEMA_VERSION) + { + WipeState = true; + WipeReason = "Manifest schema version: {}, differs from required: {}"_format(ManifestVersion, ZEN_SCHEMA_VERSION); + } + } + } + + // Handle any state wipe + + if (WipeState) + { + ZEN_WARN("Wiping state at '{}' - reason: '{}'", m_DataRoot, WipeReason); + + std::error_code Ec; + for (const std::filesystem::directory_entry& DirEntry : std::filesystem::directory_iterator{m_DataRoot, Ec}) + { + if (DirEntry.is_directory()) + { + ZEN_INFO("Deleting '{}'", DirEntry.path()); + + std::filesystem::remove_all(DirEntry.path(), Ec); + + if (Ec) + { + ZEN_WARN("Delete of '{}' returned error: '{}'", DirEntry.path(), Ec.message()); + } + } + } + + ZEN_INFO("Wiped all directories in data root"); + + // Write new manifest + + CbObjectWriter Cbo; + Cbo << "schema_version" << ZEN_SCHEMA_VERSION; + m_RootManifest = Cbo.Save(); + + WriteFile(ManifestPath, m_RootManifest.GetBuffer().AsIoBuffer()); + } + // Ok so now we're configured, let's kick things off m_Http = zen::CreateHttpServer(HttpServerClass); @@ -409,6 +484,7 @@ private: ZenServerState::ZenServerEntry* m_ServerEntry = nullptr; bool m_IsDedicatedMode = false; bool m_TestMode = false; + CbObject m_RootManifest; std::filesystem::path m_DataRoot; std::filesystem::path m_ContentRoot; std::jthread m_IoRunner; @@ -693,27 +769,36 @@ main(int argc, char* argv[]) mi_version(); #endif - ZenServerOptions GlobalOptions; - ZenServiceConfig ServiceConfig; - ParseGlobalCliOptions(argc, argv, GlobalOptions, ServiceConfig); - InitializeLogging(GlobalOptions); + try + { + ZenServerOptions GlobalOptions; + ZenServiceConfig ServiceConfig; + ParseGlobalCliOptions(argc, argv, GlobalOptions, ServiceConfig); + InitializeLogging(GlobalOptions); #if ZEN_PLATFORM_WINDOWS - if (GlobalOptions.InstallService) - { - WindowsService::Install(); + if (GlobalOptions.InstallService) + { + WindowsService::Install(); - std::exit(0); - } + std::exit(0); + } - if (GlobalOptions.UninstallService) - { - WindowsService::Delete(); + if (GlobalOptions.UninstallService) + { + WindowsService::Delete(); - std::exit(0); - } + std::exit(0); + } #endif - ZenWindowsService App(GlobalOptions, ServiceConfig); - return App.ServiceMain(); + ZenWindowsService App(GlobalOptions, ServiceConfig); + return App.ServiceMain(); + } + catch (std::exception& Ex) + { + fprintf(stderr, "ERROR: Caught exception in main: '%s'", Ex.what()); + + return 1; + } } |