# HG changeset patch # User Alain Mazy # Date 1655219993 -7200 # Node ID 4be5a8b0af1d360ac6828810fbf3e78a9ba7d362 # Parent c89ffa13173e6af7e985a58163ba5b550e164203# Parent eb8ca34039838f8740ce3f43ef1b14823b88667c merge lua-heart-beat diff -r c89ffa13173e -r 4be5a8b0af1d NEWS --- a/NEWS Mon Jun 13 16:55:22 2022 +0200 +++ b/NEWS Tue Jun 14 17:19:53 2022 +0200 @@ -5,6 +5,8 @@ ------- * Lua: new "SetHttpTimeout" function +* Lua: new "OnHeartBeat" callback called at regular interval provided that + you have configured "LuaHeartBeatPeriod" > 0. Maintenance diff -r c89ffa13173e -r 4be5a8b0af1d OrthancServer/Resources/Configuration.json --- a/OrthancServer/Resources/Configuration.json Mon Jun 13 16:55:22 2022 +0200 +++ b/OrthancServer/Resources/Configuration.json Tue Jun 14 17:19:53 2022 +0200 @@ -52,6 +52,15 @@ "LuaScripts" : [ ], + // The period (in seconds) between 2 calls of the "OnHeartBeat" + // lua callback. O means the heart beat is disabled. + // TODO: text below for Orthanc book: + // Note: that the period is not actually the delay between + // the end of an execution and the triggering of the next one. + // Since there is only one lua context, if other lua code is being + // executed, the heart beat might be delayed even more. + "LuaHeartBeatPeriod" : 0, + // List of paths to the plugins that are to be loaded into this // instance of Orthanc (e.g. "./libPluginTest.so" for Linux, or // "./PluginTest.dll" for Windows). These paths can refer to diff -r c89ffa13173e -r 4be5a8b0af1d OrthancServer/Sources/LuaScripting.cpp --- a/OrthancServer/Sources/LuaScripting.cpp Mon Jun 13 16:55:22 2022 +0200 +++ b/OrthancServer/Sources/LuaScripting.cpp Tue Jun 14 17:19:53 2022 +0200 @@ -759,7 +759,8 @@ LuaScripting::LuaScripting(ServerContext& context) : context_(context), - state_(State_Setup) + state_(State_Setup), + heartBeatPeriod_(0) { lua_.SetGlobalVariable("_ServerContext", &context); lua_.RegisterFunction("RestApiGet", RestApiGet); @@ -782,6 +783,40 @@ } } + void LuaScripting::HeartBeatThread(LuaScripting* that) + { + static const boost::posix_time::time_duration PERIODICITY = + boost::posix_time::seconds(that->heartBeatPeriod_); + + unsigned int sleepDelay = 100; + + boost::posix_time::ptime next = + boost::posix_time::microsec_clock::universal_time() + PERIODICITY; + + bool shouldStop = false; + + while (!shouldStop) + { + boost::this_thread::sleep(boost::posix_time::milliseconds(sleepDelay)); + + if (boost::posix_time::microsec_clock::universal_time() >= next) + { + LuaScripting::Lock lock(*that); + + if (lock.GetLua().IsExistingFunction("OnHeartBeat")) + { + LuaFunctionCall call(lock.GetLua(), "OnHeartBeat"); + call.Execute(); + } + + next = boost::posix_time::microsec_clock::universal_time() + PERIODICITY; + } + + boost::recursive_mutex::scoped_lock lock(that->mutex_); + shouldStop = that->state_ == State_Done; + } + + } void LuaScripting::EventThread(LuaScripting* that) { @@ -829,6 +864,14 @@ { LOG(INFO) << "Starting the Lua engine"; eventThread_ = boost::thread(EventThread, this); + + LuaScripting::Lock lock(*this); + + if (heartBeatPeriod_ > 0 && lock.GetLua().IsExistingFunction("OnHeartBeat")) + { + LOG(INFO) << "Starting the Lua HeartBeat thread with a period of " << heartBeatPeriod_ << " seconds"; + heartBeatThread_ = boost::thread(HeartBeatThread, this); + } state_ = State_Running; } } @@ -853,6 +896,10 @@ { LOG(INFO) << "Stopping the Lua engine"; eventThread_.join(); + if (heartBeatThread_.joinable()) + { + heartBeatThread_.join(); + } LOG(INFO) << "The Lua engine has stopped"; } } @@ -989,6 +1036,7 @@ std::list luaScripts; configLock.GetConfiguration().GetListOfStringsParameter(luaScripts, "LuaScripts"); + heartBeatPeriod_ = configLock.GetConfiguration().GetIntegerParameter("LuaHeartBeatPeriod", 0); LuaScripting::Lock lock(*this); diff -r c89ffa13173e -r 4be5a8b0af1d OrthancServer/Sources/LuaScripting.h --- a/OrthancServer/Sources/LuaScripting.h Mon Jun 13 16:55:22 2022 +0200 +++ b/OrthancServer/Sources/LuaScripting.h Tue Jun 14 17:19:53 2022 +0200 @@ -75,10 +75,14 @@ LuaJobManager jobManager_; State state_; boost::thread eventThread_; + boost::thread heartBeatThread_; + unsigned int heartBeatPeriod_; SharedMessageQueue pendingEvents_; static void EventThread(LuaScripting* that); + static void HeartBeatThread(LuaScripting* that); + void LoadGlobalConfiguration(); public: