changeset 4153:a4664f169cd7

"/peers/{id}/store": New option "Compress" to compress DICOM data using gzip
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 23 Aug 2020 12:13:27 +0200
parents 36257d6f348f
children 6e7c842679ec
files NEWS OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.h
diffstat 4 files changed, 94 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Aug 19 15:22:03 2020 +0200
+++ b/NEWS	Sun Aug 23 12:13:27 2020 +0200
@@ -1,6 +1,12 @@
 Pending changes in the mainline
 ===============================
 
+REST API
+--------
+
+* "/peers/{id}/store": New option "Compress" to compress DICOM data using gzip
+* "OrthancPeerStore" jobs now report the transmitted size in their public content
+
 Plugins
 -------
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Wed Aug 19 15:22:03 2020 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Sun Aug 23 12:13:27 2020 +0200
@@ -1143,6 +1143,13 @@
     {
       job->SetTranscode(SerializationToolbox::ReadString(request, TRANSCODE));
     }
+
+    static const char* COMPRESS = "Compress";
+    if (request.type() == Json::objectValue &&
+        request.isMember(COMPRESS))
+    {
+      job->SetCompress(SerializationToolbox::ReadBoolean(request, COMPRESS));
+    }
     
     {
       OrthancConfiguration::ReaderLock lock;
--- a/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp	Wed Aug 19 15:22:03 2020 +0200
+++ b/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.cpp	Sun Aug 23 12:13:27 2020 +0200
@@ -34,6 +34,7 @@
 #include "../PrecompiledHeadersServer.h"
 #include "OrthancPeerStoreJob.h"
 
+#include "../../../OrthancFramework/Sources/Compression/GzipCompressor.h"
 #include "../../../OrthancFramework/Sources/Logging.h"
 #include "../../../OrthancFramework/Sources/SerializationToolbox.h"
 #include "../ServerContext.h"
@@ -51,11 +52,19 @@
     {
       client_.reset(new HttpClient(peer_, "instances"));
       client_->SetMethod(HttpMethod_Post);
+
+      if (compress_)
+      {
+        client_->AddHeader("Expect", "");
+        client_->AddHeader("Content-Encoding", "gzip");
+      }
     }
       
     LOG(INFO) << "Sending instance " << instance << " to peer \"" 
               << peer_.GetUrl() << "\"";
 
+    std::string body;
+
     try
     {
       if (transcode_)
@@ -71,17 +80,17 @@
 
         if (context_.Transcode(transcoded, source, syntaxes, true))
         {
-          client_->GetBody().assign(reinterpret_cast<const char*>(transcoded.GetBufferData()),
-                                    transcoded.GetBufferSize());
+          body.assign(reinterpret_cast<const char*>(transcoded.GetBufferData()),
+                      transcoded.GetBufferSize());
         }
         else
         {
-          client_->GetBody().swap(dicom);
+          body.swap(dicom);
         }
       }
       else
       {
-        context_.ReadDicom(client_->GetBody(), instance);
+        context_.ReadDicom(body, instance);
       }
     }
     catch (OrthancException& e)
@@ -90,6 +99,19 @@
       return false;
     }
 
+    if (compress_)
+    {
+      GzipCompressor compressor;
+      compressor.SetCompressionLevel(9);  // Max compression level
+      IBufferCompressor::Compress(client_->GetBody(), compressor, body);
+    }
+    else
+    {
+      client_->GetBody().swap(body);
+    }
+
+    size_ += client_->GetBody().size();
+
     std::string answer;
     if (client_->Apply(answer))
     {
@@ -176,6 +198,19 @@
   }
 
 
+  void OrthancPeerStoreJob::SetCompress(bool compress)
+  {
+    if (IsStarted())
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      compress_ = compress;
+    }    
+  }
+
+
   void OrthancPeerStoreJob::Stop(JobStopReason reason)   // For pausing jobs
   {
     client_.reset(NULL);
@@ -191,16 +226,23 @@
                     false /* allow simple format if possible */,
                     false /* don't include passwords */);
     value["Peer"] = v;
+    value["Compress"] = compress_;
     
     if (transcode_)
     {
       value["Transcode"] = GetTransferSyntaxUid(transferSyntax_);
     }
+
+    static const uint64_t MEGA_BYTES = 1024 * 1024;
+    value["Size"] = boost::lexical_cast<std::string>(size_);
+    value["SizeMB"] = static_cast<unsigned int>(size_ / MEGA_BYTES);
   }
 
 
   static const char* PEER = "Peer";
   static const char* TRANSCODE = "Transcode";
+  static const char* COMPRESS = "Compress";
+  static const char* SIZE = "Size";
 
   OrthancPeerStoreJob::OrthancPeerStoreJob(ServerContext& context,
                                            const Json::Value& serialized) :
@@ -217,6 +259,25 @@
     else
     {
       transcode_ = false;
+      transferSyntax_ = DicomTransferSyntax_LittleEndianExplicit;  // Dummy value
+    }
+
+    if (serialized.isMember(COMPRESS))
+    {
+      SetCompress(SerializationToolbox::ReadBoolean(serialized, COMPRESS));
+    }
+    else
+    {
+      compress_ = false;
+    }
+
+    if (serialized.isMember(SIZE))
+    {
+      size_ = boost::lexical_cast<uint64_t>(SerializationToolbox::ReadString(serialized, SIZE));
+    }
+    else
+    {
+      size_ = 0;
     }
   }
 
@@ -238,6 +299,9 @@
       {
         target[TRANSCODE] = GetTransferSyntaxUid(transferSyntax_);
       }
+
+      target[COMPRESS] = compress_;
+      target[SIZE] = boost::lexical_cast<std::string>(size_);
       
       return true;
     }
--- a/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.h	Wed Aug 19 15:22:03 2020 +0200
+++ b/OrthancServer/Sources/ServerJobs/OrthancPeerStoreJob.h	Sun Aug 23 12:13:27 2020 +0200
@@ -50,6 +50,8 @@
     std::unique_ptr<HttpClient>  client_;
     bool                         transcode_;
     DicomTransferSyntax          transferSyntax_;
+    bool                         compress_;
+    uint64_t                     size_;
 
   protected:
     virtual bool HandleInstance(const std::string& instance);
@@ -59,7 +61,10 @@
   public:
     OrthancPeerStoreJob(ServerContext& context) :
       context_(context),
-      transcode_(false)
+      transcode_(false),
+      transferSyntax_(DicomTransferSyntax_LittleEndianExplicit),  // Dummy value
+      compress_(false),
+      size_(0)
     {
     }
 
@@ -78,6 +83,11 @@
       return transcode_;
     }
 
+    bool IsCompress() const
+    {
+      return compress_;
+    }
+
     DicomTransferSyntax GetTransferSyntax() const;
 
     void SetTranscode(DicomTransferSyntax syntax);
@@ -86,6 +96,8 @@
 
     void ClearTranscode();
 
+    void SetCompress(bool compress);
+
     virtual void Stop(JobStopReason reason);   // For pausing jobs
 
     virtual void GetJobType(std::string& target)