From 36547d1e9eef093ebbfc8612c973df4a1f37c155 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 26 May 2022 20:59:53 +0200 Subject: [PATCH] Move PluginMonitor out of TLuaEngine --- CMakeLists.txt | 1 + include/Common.h | 2 ++ include/TLuaEngine.h | 16 +-------- include/TPluginMonitor.h | 23 ++++++++++++ src/TLuaEngine.cpp | 71 ++---------------------------------- src/TPluginMonitor.cpp | 78 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 3 ++ 7 files changed, 110 insertions(+), 84 deletions(-) create mode 100644 include/TPluginMonitor.h create mode 100644 src/TPluginMonitor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 928c6bc..4df517e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,7 @@ set(BeamMP_Sources include/TScopedTimer.h src/TScopedTimer.cpp include/SignalHandling.h src/SignalHandling.cpp include/ArgsParser.h src/ArgsParser.cpp + include/TPluginMonitor.h src/TPluginMonitor.cpp include/Environment.h ) diff --git a/include/Common.h b/include/Common.h index fe5c4d5..abf758a 100644 --- a/include/Common.h +++ b/include/Common.h @@ -16,6 +16,8 @@ extern TSentry Sentry; #include #include +#include +namespace fs = std::filesystem; #include "Compat.h" diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 706ecbf..ee4e953 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -60,20 +60,7 @@ struct TLuaChunk { std::string PluginPath; }; -class TPluginMonitor : IThreaded { -public: - TPluginMonitor(const fs::path& Path, TLuaEngine& Engine, std::atomic_bool& Shutdown); - - void operator()(); - -private: - TLuaEngine& mEngine; - fs::path mPath; - std::atomic_bool& mShutdown; - std::unordered_map mFileTimes; -}; - -class TLuaEngine : IThreaded, public std::enable_shared_from_this { +class TLuaEngine : public std::enable_shared_from_this, IThreaded { public: enum CallStrategy : int { BestEffort, @@ -245,7 +232,6 @@ private: TNetwork* mNetwork; TServer* mServer; - TPluginMonitor mPluginMonitor; std::atomic_bool mShutdown { false }; fs::path mResourceServerPath; std::vector> mLuaPlugins; diff --git a/include/TPluginMonitor.h b/include/TPluginMonitor.h new file mode 100644 index 0000000..3d82c4f --- /dev/null +++ b/include/TPluginMonitor.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Common.h" +#include "IThreaded.h" + +#include +#include +#include + +class TLuaEngine; + +class TPluginMonitor : IThreaded, public std::enable_shared_from_this { +public: + TPluginMonitor(const fs::path& Path, std::shared_ptr Engine); + + void operator()(); + +private: + std::shared_ptr mEngine; + fs::path mPath; + std::atomic_bool mShutdown; + std::unordered_map mFileTimes; +}; diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index db0f825..74b01c3 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -15,8 +15,7 @@ TLuaEngine* LuaAPI::MP::Engine; -TLuaEngine::TLuaEngine() - : mPluginMonitor(fs::path(Application::Settings.Resource) / "Server", *this, mShutdown) { +TLuaEngine::TLuaEngine() { Application::SetSubsystemStatus("LuaEngine", Application::Status::Starting); LuaAPI::MP::Engine = this; if (!fs::exists(Application::Settings.Resource)) { @@ -35,7 +34,7 @@ TLuaEngine::TLuaEngine() } Application::SetSubsystemStatus("LuaEngine", Application::Status::Shutdown); }); - Start(); + IThreaded::Start(); } TEST_CASE("TLuaEngine ctor & dtor") { @@ -988,69 +987,3 @@ bool TLuaEngine::TimedEvent::Expired() { void TLuaEngine::TimedEvent::Reset() { LastCompletion = std::chrono::high_resolution_clock::now(); } - -TPluginMonitor::TPluginMonitor(const fs::path& Path, TLuaEngine& Engine, std::atomic_bool& Shutdown) - : mEngine(Engine) - , mPath(Path) - , mShutdown(Shutdown) { - if (!fs::exists(mPath)) { - fs::create_directories(mPath); - } - for (const auto& Entry : fs::recursive_directory_iterator(mPath)) { - // TODO: trigger an event when a subfolder file changes - if (Entry.is_regular_file()) { - mFileTimes[Entry.path().string()] = fs::last_write_time(Entry.path()); - } - } - Start(); -} - -void TPluginMonitor::operator()() { - RegisterThread("PluginMonitor"); - beammp_info("PluginMonitor started"); - while (!mShutdown) { - std::this_thread::sleep_for(std::chrono::seconds(3)); - std::vector ToRemove; - for (const auto& Pair : mFileTimes) { - try { - auto CurrentTime = fs::last_write_time(Pair.first); - if (CurrentTime != Pair.second) { - mFileTimes[Pair.first] = CurrentTime; - // grandparent of the path should be Resources/Server - if (fs::equivalent(fs::path(Pair.first).parent_path().parent_path(), mPath)) { - beammp_info("File \"" + Pair.first + "\" changed, reloading"); - // is in root folder, so reload - std::ifstream FileStream(Pair.first, std::ios::in | std::ios::binary); - auto Size = std::filesystem::file_size(Pair.first); - auto Contents = std::make_shared(); - Contents->resize(Size); - FileStream.read(Contents->data(), Contents->size()); - TLuaChunk Chunk(Contents, Pair.first, fs::path(Pair.first).parent_path().string()); - auto StateID = mEngine.GetStateIDForPlugin(fs::path(Pair.first).parent_path()); - auto Res = mEngine.EnqueueScript(StateID, Chunk); - // TODO: call onInit - mEngine.AddResultToCheck(Res); - } else { - // TODO: trigger onFileChanged event - beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet"); - /* - // is in subfolder, dont reload, just trigger an event - auto Results = mEngine.TriggerEvent("onFileChanged", "", Pair.first); - mEngine.WaitForAll(Results); - for (const auto& Result : Results) { - if (Result->Error) { - beammp_lua_error(Result->ErrorMessage); - } - }*/ - } - } - } catch (const std::exception& e) { - ToRemove.push_back(Pair.first); - } - } - for (const auto& File : ToRemove) { - mFileTimes.erase(File); - beammp_warn("file '" + File + "' couldn't be accessed, so it was removed from plugin hot reload monitor (probably got deleted)"); - } - } -} diff --git a/src/TPluginMonitor.cpp b/src/TPluginMonitor.cpp new file mode 100644 index 0000000..5c940be --- /dev/null +++ b/src/TPluginMonitor.cpp @@ -0,0 +1,78 @@ +#include "TPluginMonitor.h" + +#include "TLuaEngine.h" + +TPluginMonitor::TPluginMonitor(const fs::path& Path, std::shared_ptr Engine) + : mEngine(Engine) + , mPath(Path) { + if (!fs::exists(mPath)) { + fs::create_directories(mPath); + } + for (const auto& Entry : fs::recursive_directory_iterator(mPath)) { + // TODO: trigger an event when a subfolder file changes + if (Entry.is_regular_file()) { + mFileTimes[Entry.path().string()] = fs::last_write_time(Entry.path()); + } + } + + Application::RegisterShutdownHandler([this] { + mShutdown = true; + if (mThread.joinable()) { + mThread.join(); + } + }); + + Start(); +} + +void TPluginMonitor::operator()() { + RegisterThread("PluginMonitor"); + beammp_info("PluginMonitor started"); + while (!mShutdown) { + std::vector ToRemove; + for (const auto& Pair : mFileTimes) { + try { + auto CurrentTime = fs::last_write_time(Pair.first); + if (CurrentTime != Pair.second) { + mFileTimes[Pair.first] = CurrentTime; + // grandparent of the path should be Resources/Server + if (fs::equivalent(fs::path(Pair.first).parent_path().parent_path(), mPath)) { + beammp_info("File \"" + Pair.first + "\" changed, reloading"); + // is in root folder, so reload + std::ifstream FileStream(Pair.first, std::ios::in | std::ios::binary); + auto Size = std::filesystem::file_size(Pair.first); + auto Contents = std::make_shared(); + Contents->resize(Size); + FileStream.read(Contents->data(), Contents->size()); + TLuaChunk Chunk(Contents, Pair.first, fs::path(Pair.first).parent_path().string()); + auto StateID = mEngine->GetStateIDForPlugin(fs::path(Pair.first).parent_path()); + auto Res = mEngine->EnqueueScript(StateID, Chunk); + // TODO: call onInit + mEngine->AddResultToCheck(Res); + } else { + // TODO: trigger onFileChanged event + beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet"); + /* + // is in subfolder, dont reload, just trigger an event + auto Results = mEngine.TriggerEvent("onFileChanged", "", Pair.first); + mEngine.WaitForAll(Results); + for (const auto& Result : Results) { + if (Result->Error) { + beammp_lua_error(Result->ErrorMessage); + } + }*/ + } + } + } catch (const std::exception& e) { + ToRemove.push_back(Pair.first); + } + for (size_t i = 0; i < 3 && !mShutdown; ++i) { + std::this_thread::sleep_for(std::chrono::seconds(i)); + } + } + for (const auto& File : ToRemove) { + mFileTimes.erase(File); + beammp_warn("file '" + File + "' couldn't be accessed, so it was removed from plugin hot reload monitor (probably got deleted)"); + } + } +} diff --git a/src/main.cpp b/src/main.cpp index 74dbbfd..f3e23f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "TLuaEngine.h" #include "TNetwork.h" #include "TPPSMonitor.h" +#include "TPluginMonitor.h" #include "TResourceManager.h" #include "TScopedTimer.h" #include "TServer.h" @@ -159,6 +160,8 @@ int BeamMPServerMain(MainArguments Arguments) { PPSMonitor.SetNetwork(Network); Application::CheckForUpdates(); + TPluginMonitor PluginMonitor(fs::path(Application::Settings.Resource) / "Server", LuaEngine); + if (Application::Settings.HTTPServerEnabled) { Http::Server::THttpServerInstance HttpServerInstance {}; }