changeset 996:cf52f3bcb2b3 lua-scripting

clarification of Lua classes wrt multithreading
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 03 Jul 2014 16:27:16 +0200
parents 8c67382f44a7
children 1b1d51e9f1a2
files Core/Lua/LuaContext.cpp Core/Lua/LuaContext.h Core/Lua/LuaFunctionCall.cpp Core/Lua/LuaFunctionCall.h OrthancServer/OrthancRestApi/OrthancRestSystem.cpp OrthancServer/ServerContext.cpp OrthancServer/ServerContext.h OrthancServer/main.cpp
diffstat 8 files changed, 73 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Lua/LuaContext.cpp	Thu Jul 03 15:58:53 2014 +0200
+++ b/Core/Lua/LuaContext.cpp	Thu Jul 03 16:27:16 2014 +0200
@@ -34,6 +34,7 @@
 #include "LuaContext.h"
 
 #include <glog/logging.h>
+#include <cassert>
 
 extern "C" 
 {
@@ -111,8 +112,6 @@
   void LuaContext::Execute(std::string* output,
                            const std::string& command)
   {
-    boost::mutex::scoped_lock lock(mutex_);
-
     log_.clear();
     int error = (luaL_loadbuffer(lua_, command.c_str(), command.size(), "line") ||
                  lua_pcall(lua_, 0, 0, 0));
@@ -143,7 +142,6 @@
 
   bool LuaContext::IsExistingFunction(const char* name)
   {
-    boost::mutex::scoped_lock lock(mutex_);
     lua_settop(lua_, 0);
     lua_getglobal(lua_, name);
     return lua_type(lua_, -1) == LUA_TFUNCTION;
--- a/Core/Lua/LuaContext.h	Thu Jul 03 15:58:53 2014 +0200
+++ b/Core/Lua/LuaContext.h	Thu Jul 03 16:27:16 2014 +0200
@@ -34,8 +34,6 @@
 
 #include "LuaException.h"
 
-#include <boost/thread.hpp>
-
 extern "C" 
 {
 #include <lua.h>
@@ -43,6 +41,7 @@
 
 #include <EmbeddedResources.h>
 
+#include <boost/noncopyable.hpp>
 
 namespace Orthanc
 {
@@ -52,7 +51,6 @@
     friend class LuaFunctionCall;
 
     lua_State *lua_;
-    boost::mutex mutex_;
     std::string log_;
 
     static int PrintToLog(lua_State *L);
--- a/Core/Lua/LuaFunctionCall.cpp	Thu Jul 03 15:58:53 2014 +0200
+++ b/Core/Lua/LuaFunctionCall.cpp	Thu Jul 03 16:27:16 2014 +0200
@@ -33,6 +33,8 @@
 #include "../PrecompiledHeaders.h"
 #include "LuaFunctionCall.h"
 
+#include <cassert>
+
 
 namespace Orthanc
 {
@@ -47,7 +49,6 @@
   LuaFunctionCall::LuaFunctionCall(LuaContext& context,
                                    const char* functionName) : 
     context_(context),
-    lock_(context.mutex_),
     isExecuted_(false)
   {
     // Clear the stack to fulfill the invariant
--- a/Core/Lua/LuaFunctionCall.h	Thu Jul 03 15:58:53 2014 +0200
+++ b/Core/Lua/LuaFunctionCall.h	Thu Jul 03 16:27:16 2014 +0200
@@ -36,14 +36,12 @@
 
 #include <json/json.h>
 
-
 namespace Orthanc
 {
   class LuaFunctionCall : public boost::noncopyable
   {
   private:
     LuaContext& context_;
-    boost::mutex::scoped_lock lock_;
     bool isExecuted_;
 
     void CheckAlreadyExecuted();
--- a/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Thu Jul 03 15:58:53 2014 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Thu Jul 03 16:27:16 2014 +0200
@@ -90,7 +90,12 @@
   {
     std::string result;
     ServerContext& context = OrthancRestApi::GetContext(call);
-    context.GetLuaContext().Execute(result, call.GetPostBody());
+
+    {
+      ServerContext::LuaContextLocker locker(context);
+      locker.GetLua().Execute(result, call.GetPostBody());
+    }
+
     call.GetOutput().AnswerBuffer(result, "text/plain");
   }
 
--- a/OrthancServer/ServerContext.cpp	Thu Jul 03 15:58:53 2014 +0200
+++ b/OrthancServer/ServerContext.cpp	Thu Jul 03 16:27:16 2014 +0200
@@ -46,6 +46,7 @@
 #define ENABLE_DICOM_CACHE  1
 
 static const char* RECEIVED_INSTANCE_FILTER = "ReceivedInstanceFilter";
+static const char* ON_STORED_INSTANCE = "OnStoredInstance";
 
 static const size_t DICOM_CACHE_SIZE = 2;
 
@@ -91,6 +92,31 @@
     storage_.Remove(fileUuid);
   }
 
+
+  bool ServerContext::ApplyReceivedInstanceFilter(const Json::Value& dicomJson,
+                                                  const std::string& remoteAet)
+  {
+    LuaContextLocker locker(*this);
+
+    if (locker.GetLua().IsExistingFunction(RECEIVED_INSTANCE_FILTER))
+    {
+      Json::Value simplified;
+      SimplifyTags(simplified, dicomJson);
+
+      LuaFunctionCall call(locker.GetLua(), RECEIVED_INSTANCE_FILTER);
+      call.PushJSON(simplified);
+      call.PushString(remoteAet);
+
+      if (!call.ExecutePredicate())
+      {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+
   StoreStatus ServerContext::Store(const char* dicomInstance,
                                    size_t dicomSize,
                                    const DicomMap& dicomSummary,
@@ -98,20 +124,10 @@
                                    const std::string& remoteAet)
   {
     // Test if the instance must be filtered out
-    if (lua_.IsExistingFunction(RECEIVED_INSTANCE_FILTER))
+    if (!ApplyReceivedInstanceFilter(dicomJson, remoteAet))
     {
-      Json::Value simplified;
-      SimplifyTags(simplified, dicomJson);
-
-      LuaFunctionCall call(lua_, RECEIVED_INSTANCE_FILTER);
-      call.PushJSON(simplified);
-      call.PushString(remoteAet);
-
-      if (!call.ExecutePredicate())
-      {
-        LOG(INFO) << "An incoming instance has been discarded by the filter";
-        return StoreStatus_FilteredOut;
-      }
+      LOG(INFO) << "An incoming instance has been discarded by the filter";
+      return StoreStatus_FilteredOut;
     }
 
     if (compressionEnabled_)
--- a/OrthancServer/ServerContext.h	Thu Jul 03 15:58:53 2014 +0200
+++ b/OrthancServer/ServerContext.h	Thu Jul 03 16:27:16 2014 +0200
@@ -65,6 +65,9 @@
       virtual IDynamicObject* Provide(const std::string& id);
     };
 
+    bool ApplyReceivedInstanceFilter(const Json::Value& dicomJson,
+                                     const std::string& remoteAet);
+
     FileStorage storage_;
     ServerIndex index_;
     CompressedFileStorageAccessor accessor_;
@@ -76,10 +79,11 @@
     ReusableDicomUserConnection scu_;
     ServerScheduler scheduler_;
 
+    boost::mutex luaMutex_;
     LuaContext lua_;
 
   public:
-    class DicomCacheLocker
+    class DicomCacheLocker : public boost::noncopyable
     {
     private:
       ServerContext& that_;
@@ -97,6 +101,28 @@
       }
     };
 
+    class LuaContextLocker : public boost::noncopyable
+    {
+    private:
+      ServerContext& that_;
+
+    public:
+      LuaContextLocker(ServerContext& that) : that_(that)
+      {
+        that.luaMutex_.lock();
+      }
+
+      ~LuaContextLocker()
+      {
+        that_.luaMutex_.unlock();
+      }
+
+      LuaContext& GetLua()
+      {
+        return that_.lua_;
+      }
+    };
+
     ServerContext(const boost::filesystem::path& storagePath,
                   const boost::filesystem::path& indexPath);
 
@@ -153,11 +179,6 @@
                   FileContentType content,
                   bool uncompressIfNeeded = true);
 
-    LuaContext& GetLuaContext()
-    {
-      return lua_;
-    }
-
     void SetStoreMD5ForAttachments(bool storeMD5);
 
     bool IsStoreMD5ForAttachments() const
--- a/OrthancServer/main.cpp	Thu Jul 03 15:58:53 2014 +0200
+++ b/OrthancServer/main.cpp	Thu Jul 03 16:27:16 2014 +0200
@@ -186,10 +186,12 @@
   {
     static const char* HTTP_FILTER = "IncomingHttpRequestFilter";
 
+    ServerContext::LuaContextLocker locker(context_);
+
     // Test if the instance must be filtered out
-    if (context_.GetLuaContext().IsExistingFunction(HTTP_FILTER))
+    if (locker.GetLua().IsExistingFunction(HTTP_FILTER))
     {
-      LuaFunctionCall call(context_.GetLuaContext(), HTTP_FILTER);
+      LuaFunctionCall call(locker.GetLua(), HTTP_FILTER);
 
       switch (method)
       {
@@ -371,7 +373,9 @@
       LOG(WARNING) << "Installing the Lua scripts from: " << path;
       std::string script;
       Toolbox::ReadFile(script, path);
-      context.GetLuaContext().Execute(script);
+
+      ServerContext::LuaContextLocker locker(context);
+      locker.GetLua().Execute(script);
     }