diff OrthancServer/ServerJobs/LuaJobManager.cpp @ 2604:76ef12fa136c jobs

fix race conditions if creating Lua jobs
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 18 May 2018 17:37:14 +0200
parents 988936118354
children 1e11b0229e04
line wrap: on
line diff
--- a/OrthancServer/ServerJobs/LuaJobManager.cpp	Fri May 18 17:02:25 2018 +0200
+++ b/OrthancServer/ServerJobs/LuaJobManager.cpp	Fri May 18 17:37:14 2018 +0200
@@ -34,6 +34,13 @@
 #include "../PrecompiledHeadersServer.h"
 #include "LuaJobManager.h"
 
+#include "DeleteResourceOperation.h"
+#include "StoreScuOperation.h"
+#include "../../Core/JobsEngine/Operations/LogJobOperation.h"
+
+#include "DicomInstanceOperationValue.h"
+#include "../../Core/JobsEngine/Operations/NullOperationValue.h"
+#include "../../Core/JobsEngine/Operations/StringOperationValue.h"
 
 namespace Orthanc
 {
@@ -59,8 +66,7 @@
   }
 
 
-  LuaJobManager::LuaJobManager(JobsEngine&  engine) :
-    engine_(engine),
+  LuaJobManager::LuaJobManager() :
     currentJob_(NULL),
     maxOperations_(1000),
     priority_(0),
@@ -102,30 +108,108 @@
   }
 
 
-  LuaJobManager::Lock* LuaJobManager::Modify()
+  LuaJobManager::Lock::Lock(LuaJobManager& that,
+                            JobsEngine& engine) :
+    that_(that),
+    lock_(that.mutex_),
+    engine_(engine)
   {
-    boost::mutex::scoped_lock lock(mutex_);
-
-    if (currentJob_ != NULL)
+    if (that_.currentJob_ == NULL)
+    {
+      isNewJob_ = true;
+    }
+    else
     {
-      std::auto_ptr<Lock> result(new Lock(*currentJob_));
+      jobLock_.reset(new SequenceOfOperationsJob::Lock(*that_.currentJob_));
 
-      if (!result->IsDone() &&
-          result->GetOperationsCount() < maxOperations_)
+      if (jobLock_->IsDone() ||
+          jobLock_->GetOperationsCount() >= that_.maxOperations_)
       {
-        return result.release();
+        jobLock_.reset(NULL);
+        isNewJob_ = true;
+      }
+      else
+      {
+        isNewJob_ = false;
       }
     }
 
-    // Need to create a new job, as the previous one is either
-    // finished, or is getting too long
-    currentJob_ = new SequenceOfOperationsJob;
+    if (isNewJob_)
+    {
+      // Need to create a new job, as the previous one is either
+      // finished, or is getting too long
+      that_.currentJob_ = new SequenceOfOperationsJob;
+      jobLock_.reset(new SequenceOfOperationsJob::Lock(*that_.currentJob_));
+      jobLock_->SetTrailingOperationTimeout(that_.trailingTimeout_);
+    }
+
+    assert(jobLock_.get() != NULL);
+  }
+
+
+  LuaJobManager::Lock::~Lock()
+  {
+    assert(jobLock_.get() != NULL);
+    jobLock_.reset(NULL);
+
+    if (isNewJob_)
+    {
+      engine_.GetRegistry().Submit(that_.currentId_, that_.currentJob_, that_.priority_);
+    }
+  }
+
+
+  size_t LuaJobManager::Lock::AddDeleteResourceOperation(ServerContext& context)
+  {
+    assert(jobLock_.get() != NULL);
+    return jobLock_->AddOperation(new DeleteResourceOperation(context));
+  }
+
+
+  size_t LuaJobManager::Lock::AddLogOperation()
+  {
+    assert(jobLock_.get() != NULL);
+    return jobLock_->AddOperation(new LogJobOperation);
+  }
+
 
-    engine_.GetRegistry().Submit(currentId_, currentJob_, priority_);
+  size_t LuaJobManager::Lock::AddStoreScuOperation(const std::string& localAet,
+                                                   const RemoteModalityParameters& modality,
+                                                   IDicomConnectionManager& manager)
+  {
+    assert(jobLock_.get() != NULL);
+    return jobLock_->AddOperation(new StoreScuOperation(localAet, modality, that_.connectionManager_));    
+  }
+
+
+  void LuaJobManager::Lock::AddNullInput(size_t operation)
+  {
+    assert(jobLock_.get() != NULL);
+    jobLock_->AddInput(operation, NullOperationValue());
+  }
+
 
-    std::auto_ptr<Lock> result(new Lock(*currentJob_));
-    result->SetTrailingOperationTimeout(trailingTimeout_);
+  void LuaJobManager::Lock::AddStringInput(size_t operation,
+                                           const std::string& content)
+  {
+    assert(jobLock_.get() != NULL);
+    jobLock_->AddInput(operation, StringOperationValue(content));
+  }
+
 
-    return result.release();
+  void LuaJobManager::Lock::AddDicomInstanceInput(size_t operation,
+                                                  ServerContext& context,
+                                                  const std::string& instanceId)
+  {
+    assert(jobLock_.get() != NULL);
+    jobLock_->AddInput(operation, DicomInstanceOperationValue(context, instanceId));
+  }
+
+
+  void LuaJobManager::Lock::Connect(size_t operation1,
+                                    size_t operation2)
+  {
+    assert(jobLock_.get() != NULL);
+    jobLock_->Connect(operation1, operation2);
   }
 }