changeset 2965:9c0b0a6d8b54

MediaArchiveSize configuration option
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 05 Dec 2018 14:33:47 +0100
parents 6896a7c1cbe2
children 10c610e80b15
files OrthancServer/OrthancRestApi/OrthancRestApi.cpp OrthancServer/OrthancRestApi/OrthancRestApi.h OrthancServer/ServerContext.cpp OrthancServer/ServerContext.h OrthancServer/ServerJobs/ArchiveJob.cpp OrthancServer/ServerJobs/ArchiveJob.h Resources/Configuration.json
diffstat 7 files changed, 106 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Wed Dec 05 14:33:47 2018 +0100
@@ -173,6 +173,78 @@
   static const char* KEY_PRIORITY = "Priority";
   static const char* KEY_SYNCHRONOUS = "Synchronous";
   static const char* KEY_ASYNCHRONOUS = "Asynchronous";
+
+  
+  bool OrthancRestApi::IsSynchronousJobRequest(bool isDefaultSynchronous,
+                                               const Json::Value& body) const
+  {
+    if (body.isMember(KEY_SYNCHRONOUS))
+    {
+      return SerializationToolbox::ReadBoolean(body, KEY_SYNCHRONOUS);
+    }
+    else if (body.isMember(KEY_ASYNCHRONOUS))
+    {
+      return !SerializationToolbox::ReadBoolean(body, KEY_ASYNCHRONOUS);
+    }
+    else
+    {
+      return isDefaultSynchronous;
+    }
+  }
+
+
+  void OrthancRestApi::SubmitGenericJob(RestApiPostCall& call,
+                                        IJob* job,
+                                        bool isDefaultSynchronous,
+                                        const Json::Value& body) const
+  {
+    std::auto_ptr<IJob> raii(job);
+    
+    if (job == NULL)
+    {
+      throw OrthancException(ErrorCode_NullPointer);
+    }
+
+    if (body.type() != Json::objectValue)
+    {
+      throw OrthancException(ErrorCode_BadFileFormat);
+    }
+
+    int priority = 0;
+
+    if (body.isMember(KEY_PRIORITY))
+    {
+      priority = SerializationToolbox::ReadInteger(body, KEY_PRIORITY);
+    }
+
+    if (IsSynchronousJobRequest(isDefaultSynchronous, body))
+    {
+      Json::Value successContent;
+      if (context_.GetJobsEngine().GetRegistry().SubmitAndWait
+          (successContent, raii.release(), priority))
+      {
+        // Success in synchronous execution
+        call.GetOutput().AnswerJson(successContent);
+      }
+      else
+      {
+        // Error during synchronous execution
+        call.GetOutput().SignalError(HttpStatus_500_InternalServerError);
+      }
+    }
+    else
+    {
+      // Asynchronous mode: Submit the job, but don't wait for its completion
+      std::string id;
+      context_.GetJobsEngine().GetRegistry().Submit(id, raii.release(), priority);
+
+      Json::Value v;
+      v["ID"] = id;
+      v["Path"] = "/jobs/" + id;
+      call.GetOutput().AnswerJson(v);
+    }
+  }
+
   
   void OrthancRestApi::SubmitCommandsJob(RestApiPostCall& call,
                                          SetOfCommandsJob* job,
@@ -202,66 +274,6 @@
       job->SetPermissive(false);
     }
 
-    int priority = 0;
-
-    if (body.isMember(KEY_PRIORITY))
-    {
-      priority = SerializationToolbox::ReadInteger(body, KEY_PRIORITY);
-    }
-
-    bool synchronous = isDefaultSynchronous;
-    
-    if (body.isMember(KEY_SYNCHRONOUS))
-    {
-      synchronous = SerializationToolbox::ReadBoolean(body, KEY_SYNCHRONOUS);
-    }
-    else if (body.isMember(KEY_ASYNCHRONOUS))
-    {
-      synchronous = !SerializationToolbox::ReadBoolean(body, KEY_ASYNCHRONOUS);
-    }
-
-    if (synchronous)
-    {
-      Json::Value successContent;
-      if (context_.GetJobsEngine().GetRegistry().SubmitAndWait
-          (successContent, raii.release(), priority))
-      {
-        // Success in synchronous execution
-        call.GetOutput().AnswerJson(successContent);
-      }
-      else
-      {
-        // Error during synchronous execution
-        call.GetOutput().SignalError(HttpStatus_500_InternalServerError);
-      }
-    }
-    else
-    {
-      // Asynchronous mode: Submit the job, but don't wait for its completion
-      std::string id;
-      context_.GetJobsEngine().GetRegistry().Submit(id, raii.release(), priority);
-
-      Json::Value v;
-      v["ID"] = id;
-      v["Path"] = "/jobs/" + id;
-      call.GetOutput().AnswerJson(v);
-    }
-  }
-  
-
-  void OrthancRestApi::SubmitCommandsJob(RestApiPostCall& call,
-                                         SetOfCommandsJob* job,
-                                         bool isDefaultSynchronous) const
-  {
-    std::auto_ptr<SetOfCommandsJob> raii(job);
-    
-    Json::Value body;
-    
-    if (!call.ParseJsonRequest(body))
-    {
-      body = Json::objectValue;
-    }
-
-    SubmitCommandsJob(call, raii.release(), isDefaultSynchronous, body);
+    SubmitGenericJob(call, raii.release(), isDefaultSynchronous, body);
   }
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestApi.h	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/OrthancRestApi/OrthancRestApi.h	Wed Dec 05 14:33:47 2018 +0100
@@ -103,13 +103,17 @@
                               ResourceType resourceType,
                               StoreStatus status) const;
 
+    bool IsSynchronousJobRequest(bool isDefaultSynchronous,
+                                 const Json::Value& body) const;
+    
+    void SubmitGenericJob(RestApiPostCall& call,
+                          IJob* job,
+                          bool isDefaultSynchronous,
+                          const Json::Value& body) const;
+
     void SubmitCommandsJob(RestApiPostCall& call,
                            SetOfCommandsJob* job,
                            bool isDefaultSynchronous,
                            const Json::Value& body) const;
-
-    void SubmitCommandsJob(RestApiPostCall& call,
-                           SetOfCommandsJob* job,
-                           bool isDefaultSynchronous) const;
   };
 }
--- a/OrthancServer/ServerContext.cpp	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/ServerContext.cpp	Wed Dec 05 14:33:47 2018 +0100
@@ -235,8 +235,11 @@
   {
     {
       OrthancConfiguration::ReaderLock lock;
+
       queryRetrieveArchive_.reset(
         new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("QueryRetrieveSize", 10)));
+      mediaArchive_.reset(
+        new SharedArchive(lock.GetConfiguration().GetUnsignedIntegerParameter("MediaArchiveSize", 1)));
       defaultLocalAet_ = lock.GetConfiguration().GetStringParameter("DicomAet", "ORTHANC");
       jobsEngine_.SetWorkersCount(lock.GetConfiguration().GetUnsignedIntegerParameter("ConcurrentJobs", 2));
     }
--- a/OrthancServer/ServerContext.h	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/ServerContext.h	Wed Dec 05 14:33:47 2018 +0100
@@ -189,6 +189,8 @@
     std::string defaultLocalAet_;
     OrthancHttpHandler  httpHandler_;
 
+    std::auto_ptr<SharedArchive>  mediaArchive_;
+    
   public:
     class DicomCacheLocker : public boost::noncopyable
     {
@@ -310,6 +312,11 @@
       return *queryRetrieveArchive_;
     }
 
+    SharedArchive& GetMediaArchive()
+    {
+      return *mediaArchive_;
+    }
+
     const std::string& GetDefaultLocalApplicationEntityTitle() const
     {
       return defaultLocalAet_;
--- a/OrthancServer/ServerJobs/ArchiveJob.cpp	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/ServerJobs/ArchiveJob.cpp	Wed Dec 05 14:33:47 2018 +0100
@@ -778,11 +778,11 @@
   };
 
 
-  ArchiveJob::ArchiveJob(boost::shared_ptr<TemporaryFile>& target,
+  ArchiveJob::ArchiveJob(boost::shared_ptr<TemporaryFile>& synchronousTarget,
                          ServerContext& context,
                          bool isMedia,
                          bool enableExtendedSopClass) :
-    target_(target),
+    synchronousTarget_(synchronousTarget),
     context_(context),
     archive_(new ArchiveIndex(ResourceType_Patient)),  // root
     isMedia_(isMedia),
@@ -791,7 +791,7 @@
     instancesCount_(0),
     uncompressedSize_(0)
   {
-    if (target.get() == NULL)
+    if (synchronousTarget.get() == NULL)
     {
       throw OrthancException(ErrorCode_NullPointer);
     }
@@ -824,7 +824,7 @@
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
     }
 
-    writer_.reset(new ZipWriterIterator(*target_, context_, *archive_,
+    writer_.reset(new ZipWriterIterator(*synchronousTarget_, context_, *archive_,
                                         isMedia_, enableExtendedSopClass_));
 
     instancesCount_ = writer_->GetInstancesCount();
@@ -836,7 +836,7 @@
   {
     assert(writer_.get() != NULL);
 
-    if (target_.unique())
+    if (synchronousTarget_.unique())
     {
       LOG(WARNING) << "A client has disconnected while creating an archive";
       return JobStepResult::Failure(ErrorCode_NetworkProtocol);          
--- a/OrthancServer/ServerJobs/ArchiveJob.h	Wed Dec 05 12:58:56 2018 +0100
+++ b/OrthancServer/ServerJobs/ArchiveJob.h	Wed Dec 05 14:33:47 2018 +0100
@@ -50,7 +50,7 @@
     class ZipCommands;
     class ZipWriterIterator;
     
-    boost::shared_ptr<TemporaryFile>      target_;
+    boost::shared_ptr<TemporaryFile>      synchronousTarget_;
     ServerContext&                        context_;
     boost::shared_ptr<ArchiveIndex>       archive_;
     bool                                  isMedia_;
@@ -63,7 +63,7 @@
     uint64_t                              uncompressedSize_;
 
   public:
-    ArchiveJob(boost::shared_ptr<TemporaryFile>& target,
+    ArchiveJob(boost::shared_ptr<TemporaryFile>& synchronousTarget,
                ServerContext& context,
                bool isMedia,
                bool enableExtendedSopClass);
--- a/Resources/Configuration.json	Wed Dec 05 12:58:56 2018 +0100
+++ b/Resources/Configuration.json	Wed Dec 05 14:33:47 2018 +0100
@@ -440,5 +440,12 @@
   // instance replaces the old one. If set to "false", the new
   // instance is discarded and the old one is kept. Up to Orthanc
   // 1.4.1, the implicit behavior corresponded to "false".
-  "OverwriteInstances" : false
+  "OverwriteInstances" : false,
+
+  // Maximum number of ZIP/media archives that are maintained by
+  // Orthanc, as a response to the asynchronous creation of archives.
+  // The least recently used archives get deleted as new archives are
+  // generated. This option was introduced in Orthanc 1.4.3, and has
+  // no effect on the synchronous generation of archives.
+  "MediaArchiveSize" : 1
 }