[med-svn] [Git][med-team/orthanc-dicomweb][master] 4 commits: New upstream version 1.21+dfsg

Sebastien Jodogne (@jodogne-guest) gitlab at salsa.debian.org
Tue Dec 9 07:29:02 GMT 2025



Sebastien Jodogne pushed to branch master at Debian Med / orthanc-dicomweb


Commits:
fdf3ede8 by jodogne-guest at 2025-08-19T15:29:53+02:00
New upstream version 1.21+dfsg

- - - - -
6a230c4d by jodogne-guest at 2025-12-09T08:16:35+01:00
New upstream version 1.22+dfsg
- - - - -
ad6a25b8 by jodogne-guest at 2025-12-09T08:16:35+01:00
Update upstream source from tag 'upstream/1.22+dfsg'

Update to upstream version '1.22+dfsg'
with Debian dir e186629040c9b44f381e4951db6e32bbfd9d628b
- - - - -
4d36ea3b by jodogne-guest at 2025-12-09T08:23:00+01:00
preparing 1.22+dfsg-1

- - - - -


16 changed files:

- .hg_archival.txt
- CMakeLists.txt
- NEWS
- Plugin/Plugin.cpp
- Plugin/WadoRs.cpp
- Resources/Orthanc/CMake/AutoGeneratedCode.cmake
- Resources/Orthanc/CMake/Compiler.cmake
- Resources/Orthanc/CMake/DownloadOrthancFramework.cmake
- Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp
- Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h
- Resources/SyncOrthancFolder.py
- debian/changelog
- debian/patches/cmake
- − debian/patches/embed-resources
- + debian/patches/orthanc-framework
- debian/patches/series


Changes:

=====================================
.hg_archival.txt
=====================================
@@ -1,6 +1,6 @@
 repo: d5f45924411123cfd02d035fd50b8e37536eadef
-node: 00cae2648bcb72d3ff12e6244ca63a2bc467b935
-branch: OrthancDicomWeb-1.21
+node: 1174d2027f6a4499996100f16bb2ad64c3d69802
+branch: OrthancDicomWeb-1.22
 latesttag: null
-latesttagdistance: 635
-changessincelatesttag: 685
+latesttagdistance: 648
+changessincelatesttag: 700


=====================================
CMakeLists.txt
=====================================
@@ -19,17 +19,17 @@
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 
 
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8...4.0)
 
 project(OrthancDicomWeb)
 
-set(ORTHANC_DICOM_WEB_VERSION "1.21")
+set(ORTHANC_DICOM_WEB_VERSION "1.22")
 
 if (ORTHANC_DICOM_WEB_VERSION STREQUAL "mainline")
   set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline")
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg")
 else()
-  set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.5")
+  set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "e0979326ac53")  # while waiting for 1.12.11
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web")
 endif()
 
@@ -60,7 +60,13 @@ include(${CMAKE_SOURCE_DIR}/Resources/Orthanc/CMake/DownloadOrthancFramework.cma
 
 if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
   if (ORTHANC_FRAMEWORK_USE_SHARED)
-    include(FindBoost)
+    # https://cmake.org/cmake/help/latest/policy/CMP0167.html
+    if (CMAKE_VERSION VERSION_GREATER "3.30")
+      find_package(Boost CONFIG)
+    else()
+      include(FindBoost)
+    endif()
+
     find_package(Boost COMPONENTS regex thread)
     
     if (NOT Boost_FOUND)


=====================================
NEWS
=====================================
@@ -1,3 +1,12 @@
+Version 1.22 (2025-12-02)
+=========================
+
+* Fixed a possible deadlock when using "WadoRsLoaderThreadsCount" > 1 when the HTTP
+  client disconnects while downloading the response.
+* Fixed "Success: Success" errors when trying to send resources synchronously to a remote DICOMweb
+  server while the Orthanc job engine was busy with other tasks.
+
+
 Version 1.21 (2025-08-14)
 =========================
 
@@ -9,7 +18,8 @@ Version 1.21 (2025-08-14)
   only showing the time required to execute a WADO-RS query.  For example:
   WADO-RS: elapsed: 26106623 us, rate: 14.86 instances/s, 155.23Mbps
 * Fix false errors logs generated e.g when OHIF requests the /dicom-web/studies/../metadata route:
-  "dicom-web:/Configuration.cpp:643] Unsupported return MIME type: application/dicom+json, multipart/related; type=application/octet-stream; transfer-syntax=*, will return DICOM+JSON"
+  "dicom-web:/Configuration.cpp:643] Unsupported return MIME type: application/dicom+json,
+  multipart/related; type=application/octet-stream; transfer-syntax=*, will return DICOM+JSON"
 
 
 Version 1.20 (2025-05-12)


=====================================
Plugin/Plugin.cpp
=====================================
@@ -747,7 +747,10 @@ extern "C"
         std::string publicUrlRoot = OrthancPlugins::Configuration::GetPublicRoot();
         LOG(WARNING) << "DICOMweb public root: " << publicUrlRoot;
 
-        LOG(WARNING) << "The DICOMWeb plugin will use " << (OrthancPlugins::Configuration::GetWadoRsLoaderThreadsCount() == 0 ? 1 : OrthancPlugins::Configuration::GetWadoRsLoaderThreadsCount()) << " threads to load DICOM files for WADO-RS queries";
+        LOG(WARNING) << "The DICOMweb plugin will use "
+                     << (OrthancPlugins::Configuration::GetWadoRsLoaderThreadsCount() == 0 ? 1 :
+                         OrthancPlugins::Configuration::GetWadoRsLoaderThreadsCount())
+                     << " threads to load DICOM files for WADO-RS queries";
       }
       else
       {


=====================================
Plugin/WadoRs.cpp
=====================================
@@ -32,7 +32,7 @@
 #include <Toolbox.h>
 #include <SerializationToolbox.h>
 #include <MultiThreading/SharedMessageQueue.h>
-#include <MultiThreading/Semaphore.h>
+#include <MultiThreading/BlockingSharedMessageQueue.h>
 #include <Compression/GzipCompressor.h>
 
 #include <memory>
@@ -449,16 +449,16 @@ class ThreadedInstanceLoader : public InstanceLoader
 
   Orthanc::SharedMessageQueue         instancesToPreload_;
 
-  Orthanc::SharedMessageQueue         loadedInstances_;
+  Orthanc::BlockingSharedMessageQueue loadedInstances_;
 
-  Orthanc::Semaphore                  bufferSemaphore_;
+  bool                                loadersShouldStop_;
 
 public:
   ThreadedInstanceLoader(size_t threadCount, bool transcode, Orthanc::DicomTransferSyntax transferSyntax)
   : InstanceLoader(transcode, transferSyntax),
     instancesToPreload_(0),
-    loadedInstances_(0),
-    bufferSemaphore_(3*threadCount) // to limit the number of loaded instances in memory
+    loadedInstances_(3*threadCount), // to limit the number of loaded instances in memory
+    loadersShouldStop_(false)
   {
     for (size_t i = 0; i < threadCount; i++)
     {
@@ -473,21 +473,32 @@ public:
 
   void Clear()
   {
-    for (size_t i = 0; i < threads_.size(); i++)
+    if (threads_.size() > 0)
     {
-      instancesToPreload_.Enqueue(NULL);
-    }
+      loadersShouldStop_ = true; // not need to protect this by a mutex.  This is the only "writer" and all loaders are "readers"
 
-    for (size_t i = 0; i < threads_.size(); i++)
-    {
-      if (threads_[i]->joinable())
+      LOG(INFO) << "Waiting for loader threads to complete";
+
+      // unlock the loaders if they are waiting on this message queue (this happens when the job completes sucessfully)
+      for (size_t i = 0; i < threads_.size(); i++)
       {
-        threads_[i]->join();
+        instancesToPreload_.Enqueue(NULL);
       }
-      delete threads_[i];
-    }
 
-    threads_.clear();
+
+      for (size_t i = 0; i < threads_.size(); i++)
+      {
+        if (threads_[i]->joinable())
+        {
+          threads_[i]->join();
+        }
+        delete threads_[i];
+      }
+
+      threads_.clear();
+
+      LOG(INFO) << "Waiting for loader threads to complete - done";
+    }
   }
 
   static void PreloaderWorkerThread(ThreadedInstanceLoader* that)
@@ -495,20 +506,20 @@ public:
     static uint16_t threadCounter = 0;
     Orthanc::Logging::SetCurrentThreadName(std::string("WADO-LOAD-") + boost::lexical_cast<std::string>(threadCounter++));
 
+    LOG(INFO) << "Loader thread has started";
+
     while (true)
     {
-      std::unique_ptr<InstanceToPreload> instanceToPreload(dynamic_cast<InstanceToPreload*>(that->instancesToPreload_.Dequeue(0)));
-      if (instanceToPreload.get() == NULL)  // that's the signal to exit the thread
+      std::unique_ptr<InstanceToPreload> instancesToPreload(dynamic_cast<InstanceToPreload*>(that->instancesToPreload_.Dequeue(0)));
+      if (instancesToPreload.get() == NULL || that->loadersShouldStop_)  // that's the signal to exit the thread
       {
+        LOG(INFO) << "Loader thread has completed";
         return;
       }
       
-      // wait for the consumers, no need to accumulate instances in memory if loaders are faster than writers
-      that->bufferSemaphore_.Acquire();
-
       try
       {
-        std::unique_ptr<OrthancPlugins::DicomInstance> dicom(that->GetAndTranscodeDicom(instanceToPreload.get()));
+        std::unique_ptr<OrthancPlugins::DicomInstance> dicom(that->GetAndTranscodeDicom(instancesToPreload.get()));
         that->loadedInstances_.Enqueue(new LoadedInstance(dicom.release()));
       }
       catch (Orthanc::OrthancException& e)
@@ -521,7 +532,6 @@ public:
         LOG(ERROR) << "Unknown error while loading instances ";
         that->loadedInstances_.Enqueue(NULL);
       }
-
     }
   }
 
@@ -534,16 +544,13 @@ public:
   {
     std::unique_ptr<LoadedInstance> loadedInstance(dynamic_cast<LoadedInstance*>(loadedInstances_.Dequeue(0)));
     
-    // unlock preloader threads to buffer the following instances
-    bufferSemaphore_.Release();
-
     if (loadedInstance.get() != NULL)
     {
       return loadedInstance->ReleaseInstance();
     }
     else
     {
-      return NULL;
+      return NULL; // happens when the loader threads are exiting
     }
   }
 };
@@ -1685,6 +1692,9 @@ public:
 
 void InstanceWorkerThread(InstanceWorkerData* data)
 {
+  static uint16_t threadCounter = 0;
+  Orthanc::Logging::SetCurrentThreadName(std::string("DW-META-") + boost::lexical_cast<std::string>(threadCounter++));
+
   while (true)
   {
     try


=====================================
Resources/Orthanc/CMake/AutoGeneratedCode.cmake
=====================================
@@ -20,7 +20,7 @@
 # <http://www.gnu.org/licenses/>.
 
 
-set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/../EmbedResources.py"
+set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py"
   CACHE INTERNAL "Path to the EmbedResources.py script from Orthanc")
 set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED")
 set(AUTOGENERATED_SOURCES)


=====================================
Resources/Orthanc/CMake/Compiler.cmake
=====================================
@@ -21,6 +21,8 @@
 
 
 # This file sets all the compiler-related flags
+message(STATUS "CMAKE_CXX_COMPILER_ID is ${CMAKE_CXX_COMPILER_ID}")
+message(STATUS "CMAKE_SYSTEM_NAME is ${CMAKE_SYSTEM_NAME}")
 
 if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
   # Since Orthanc 1.12.7 that allows CMake 4.0, builds for macOS
@@ -246,6 +248,9 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
   # fix this error that appears with recent compilers on MacOS: boost/mpl/aux_/integral_wrapper.hpp:73:31: error: integer value -1 is outside the valid range of values [0, 3] for this enumeration type [-Wenum-constexpr-conversion]
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-enum-constexpr-conversion")
 
+  # it seems that some recent MacOS compilers don't set these flags correctly which prevents zlib from building correctly
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64")
+
   add_definitions(
     -D_XOPEN_SOURCE=1
     )


=====================================
Resources/Orthanc/CMake/DownloadOrthancFramework.cmake
=====================================
@@ -175,6 +175,8 @@ if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
         set(ORTHANC_FRAMEWORK_MD5 "eb1c719234338e8277b80d3453563e9f")
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.9")
         set(ORTHANC_FRAMEWORK_MD5 "66b5a2ee60706c4a502896083b9e1a01")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.10")
+        set(ORTHANC_FRAMEWORK_MD5 "d5e1ba442104c89a24013cb859a9d6bf")
 
       # Below this point are development snapshots that were used to
       # release some plugin, before an official release of the Orthanc
@@ -207,6 +209,23 @@ if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
         # DICOMweb 1.15 (framework pre-1.12.2)
         set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
         set(ORTHANC_FRAMEWORK_MD5 "ebe8bdf388319f1c9536b2b680451848")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "36cd91a53403")
+        # Advanced storage 0.2.0 (framework pre-1.12.10)
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "911105f18a154b5e106985d8fcfcb620")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "9eb77f159b9d")
+        # Advanced storage 0.2.2 (framework pre-1.12.10)
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "bd5ba2cec329010b912209345acbdeaf")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "0ebe8cfd9bf7")
+        # Worklists plugin 0.9.0 (framework pre-1.12.10)
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "17a5ca9254e881ab89c93d052d4655cb")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "e0979326ac53")
+        # DICOMweb 1.22 + PG 10.0 (framework post-1.12.10)
+        # for BlockingSharedMessageQueue + fix SetCurrentThreadName from plugins
+        set(ORTHANC_FRAMEWORK_PRE_RELEASE ON)
+        set(ORTHANC_FRAMEWORK_MD5 "e66a7e996d56063b3abb790bb8f12e8d")
       endif()
     endif()
   endif()


=====================================
Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp
=====================================
@@ -23,6 +23,7 @@
 
 #include "OrthancPluginCppWrapper.h"
 
+#include <cassert>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/move/unique_ptr.hpp>
 #include <boost/thread.hpp>
@@ -220,6 +221,19 @@ namespace OrthancPlugins
   }
 
 
+  MemoryBuffer::~MemoryBuffer()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void MemoryBuffer::Clear()
   {
     if (buffer_.data != NULL)
@@ -350,6 +364,38 @@ namespace OrthancPlugins
     }
   }
 
+
+#if (HAS_ORTHANC_PLUGIN_PEERS == 1) || (HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1) || (HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1)
+  static void DecodeHttpHeaders(HttpHeaders& target,
+                                const MemoryBuffer& source)
+  {
+    Json::Value v;
+    source.ToJson(v);
+
+    if (v.type() != Json::objectValue)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
+    }
+
+    Json::Value::Members members = v.getMemberNames();
+    target.clear();
+
+    for (size_t i = 0; i < members.size(); i++)
+    {
+      const Json::Value& h = v[members[i]];
+      if (h.type() != Json::stringValue)
+      {
+        ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
+      }
+      else
+      {
+        target[members[i]] = h.asString();
+      }
+    }
+  }
+#endif
+
+
   // helper class to convert std::map of headers to the plugin SDK C structure
   class PluginHttpHeaders
   {
@@ -623,6 +669,19 @@ namespace OrthancPlugins
   }
 
 
+  OrthancString::~OrthancString()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void OrthancString::Assign(char* str)
   {
     Clear();
@@ -1272,6 +1331,20 @@ namespace OrthancPlugins
     }
   }
 
+
+  OrthancImage::~OrthancImage()
+  {
+    try
+    {
+      Clear();
+    }
+    catch (ORTHANC_PLUGINS_EXCEPTION_CLASS&)
+    {
+      // Don't throw exceptions in destructors
+    }
+  }
+
+
   void OrthancImage::UncompressPngImage(const void* data,
                                         size_t size)
   {
@@ -2083,8 +2156,30 @@ namespace OrthancPlugins
                             unsigned int timeout) const
   {
     MemoryBuffer buffer;
+    HttpHeaders answerHeaders;
+
+    if (DoPost(buffer, answerHeaders, index, uri, body, headers, timeout))
+    {
+      buffer.ToJson(target);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  bool OrthancPeers::DoPost(Json::Value& target,
+                            HttpHeaders& answerHeaders,
+                            size_t index,
+                            const std::string& uri,
+                            const std::string& body,
+                            const HttpHeaders& headers, 
+                            unsigned int timeout) const
+  {
+    MemoryBuffer buffer;
 
-    if (DoPost(buffer, index, uri, body, headers, timeout))
+    if (DoPost(buffer, answerHeaders, index, uri, body, headers, timeout))
     {
       buffer.ToJson(target);
       return true;
@@ -2142,11 +2237,23 @@ namespace OrthancPlugins
                             const std::string& body,
                             const HttpHeaders& headers) const
   {
-    return DoPost(target, index, uri, body, headers, timeout_);
+    HttpHeaders answerHeaders;
+    return DoPost(target, answerHeaders, index, uri, body, headers, timeout_);
   }
 
+  bool OrthancPeers::DoPost(MemoryBuffer& target,
+                            size_t index,
+                            const std::string& uri,
+                            const std::string& body,
+                            const HttpHeaders& headers,
+                            unsigned int timeout) const
+  {
+    HttpHeaders answerHeaders;
+    return DoPost(target, answerHeaders, index, uri, body, headers, timeout);
+  }
 
   bool OrthancPeers::DoPost(MemoryBuffer& target,
+                            HttpHeaders& answerHeaders,
                             size_t index,
                             const std::string& uri,
                             const std::string& body,
@@ -2165,17 +2272,20 @@ namespace OrthancPlugins
     }
 
     OrthancPlugins::MemoryBuffer answer;
+    OrthancPlugins::MemoryBuffer answerHeadersBuffer;
     uint16_t status;
     PluginHttpHeaders pluginHeaders(headers);
 
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
-      (GetGlobalContext(), *answer, NULL, &status, peers_,
+      (GetGlobalContext(), *answer, *answerHeadersBuffer, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
        pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout);
 
     if (code == OrthancPluginErrorCode_Success)
     {
       target.Swap(answer);
+      DecodeHttpHeaders(answerHeaders, answerHeadersBuffer);
+      
       return (status == 200);
     }
     else
@@ -2610,33 +2720,43 @@ namespace OrthancPlugins
 
         return;
       }
-      else if (state == "Running")
+      else if (state == "Running" ||
+               state == "Pending" ||
+               state == "Paused" ||
+               state == "Retry")
       {
         continue;
       }
-      else if (!status.isMember("ErrorCode") ||
-               status["ErrorCode"].type() != Json::intValue)
+      else if (state == "Failure")
       {
-        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
-      }
-      else
-      {
-        if (!status.isMember("ErrorDescription") ||
-            status["ErrorDescription"].type() != Json::stringValue)
+        if (!status.isMember("ErrorCode") ||
+            status["ErrorCode"].type() != Json::intValue)
         {
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());
+          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
         }
         else
         {
-#if HAS_ORTHANC_EXCEPTION == 1
-          throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
-                                          status["ErrorDescription"].asString());
-#else
-          ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString());
-          ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
-#endif
+          if (!status.isMember("ErrorDescription") ||
+              status["ErrorDescription"].type() != Json::stringValue)
+          {
+            ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());
+          }
+          else
+          {
+  #if HAS_ORTHANC_EXCEPTION == 1
+            throw Orthanc::OrthancException(static_cast<Orthanc::ErrorCode>(status["ErrorCode"].asInt()),
+                                            status["ErrorDescription"].asString());
+  #else
+            ORTHANC_PLUGINS_LOG_ERROR("Exception while executing the job: " + status["ErrorDescription"].asString());
+            ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(status["ErrorCode"].asInt());          
+  #endif
+          }
         }
       }
+      else
+      {
+        ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_InternalError);
+      }
     }
   }
 
@@ -3222,36 +3342,6 @@ namespace OrthancPlugins
   }
 #endif    
 
-
-  static void DecodeHttpHeaders(HttpHeaders& target,
-                                const MemoryBuffer& source)
-  {
-    Json::Value v;
-    source.ToJson(v);
-
-    if (v.type() != Json::objectValue)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-    }
-
-    Json::Value::Members members = v.getMemberNames();
-    target.clear();
-
-    for (size_t i = 0; i < members.size(); i++)
-    {
-      const Json::Value& h = v[members[i]];
-      if (h.type() != Json::stringValue)
-      {
-        ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
-      }
-      else
-      {
-        target[members[i]] = h.asString();
-      }
-    }
-  }
-
-
   void HttpClient::ExecuteWithoutStream(uint16_t& httpStatus,
                                         HttpHeaders& answerHeaders,
                                         std::string& answerBody,
@@ -4571,8 +4661,11 @@ namespace OrthancPlugins
     uint8_t found = false;
     OrthancPlugins::MemoryBuffer valueBuffer;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     OrthancPluginErrorCode code = OrthancPluginDequeueValue(OrthancPlugins::GetGlobalContext(), &found,
                                                             *valueBuffer, queueId_.c_str(), origin);
+#pragma GCC diagnostic pop
 
     if (code != OrthancPluginErrorCode_Success)
     {
@@ -4607,4 +4700,54 @@ namespace OrthancPlugins
     }
   }
 #endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+  bool Queue::ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout)
+  {
+    uint8_t found = false;
+    OrthancPlugins::MemoryBuffer valueBuffer;
+
+    OrthancPluginErrorCode code = OrthancPluginReserveQueueValue(OrthancPlugins::GetGlobalContext(), &found,
+                                                                 *valueBuffer, &valueId, queueId_.c_str(), origin, releaseTimeout);
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else if (found)
+    {
+      valueBuffer.ToString(value);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+  bool Queue::ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
+  {
+    return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Back, releaseTimeout);
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+  bool Queue::ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
+  {
+    return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Front, releaseTimeout);
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+  void Queue::Acknowledge(uint64_t valueId)
+  {
+    OrthancPluginAcknowledgeQueueValue(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), valueId);
+  }
+#endif
 }


=====================================
Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h
=====================================
@@ -142,6 +142,12 @@
 #  define HAS_ORTHANC_PLUGIN_QUEUES            0
 #endif
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 10)
+#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   1
+#else
+#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   0
+#endif
+
 
 // Macro to tag a function as having been deprecated
 #if (__cplusplus >= 201402L)  // C++14
@@ -213,10 +219,7 @@ namespace OrthancPlugins
   public:
     MemoryBuffer();
 
-    ~MemoryBuffer()
-    {
-      Clear();
-    }
+    ~MemoryBuffer();
 
     OrthancPluginMemoryBuffer* operator*()
     {
@@ -371,10 +374,7 @@ namespace OrthancPlugins
     {
     }
 
-    ~OrthancString()
-    {
-      Clear();
-    }
+    ~OrthancString();
 
     // This transfers ownership, warning: The string must have been
     // allocated by the Orthanc core
@@ -491,10 +491,7 @@ namespace OrthancPlugins
                  uint32_t                  pitch,
                  void*                     buffer);
 
-    ~OrthancImage()
-    {
-      Clear();
-    }
+    ~OrthancImage();
 
     void UncompressPngImage(const void* data,
                             size_t size);
@@ -878,6 +875,14 @@ namespace OrthancPlugins
                 const HttpHeaders& headers,
                 unsigned int timeout) const;
 
+    bool DoPost(MemoryBuffer& target,
+                HttpHeaders& answerHeaders,
+                size_t index,
+                const std::string& uri,
+                const std::string& body,
+                const HttpHeaders& headers,
+                unsigned int timeout) const;
+
     bool DoPost(MemoryBuffer& target,
                 const std::string& name,
                 const std::string& uri,
@@ -896,6 +901,14 @@ namespace OrthancPlugins
                 const std::string& body,
                 const HttpHeaders& headers,
                 unsigned int timeout) const;
+    
+    bool DoPost(Json::Value& target,
+                HttpHeaders& answerHeaders,
+                size_t index,
+                const std::string& uri,
+                const std::string& body,
+                const HttpHeaders& headers,
+                unsigned int timeout) const;
 
     bool DoPost(Json::Value& target,
                 const std::string& name,
@@ -1710,6 +1723,10 @@ void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* reque
 
     bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin);
 
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    bool ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout);
+#endif
+
   public:
     explicit Queue(const std::string& queueId) :
       queueId_(queueId)
@@ -1729,17 +1746,37 @@ void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* reque
       Enqueue(value.empty() ? NULL : value.c_str(), value.size());
     }
 
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    // Use ReserveBack() instead
+    ORTHANC_PLUGIN_DEPRECATED
+#endif
     bool DequeueBack(std::string& value)
     {
       return DequeueInternal(value, OrthancPluginQueueOrigin_Back);
     }
 
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    // Use ReserveFront() instead
+    ORTHANC_PLUGIN_DEPRECATED
+#endif
     bool DequeueFront(std::string& value)
     {
       return DequeueInternal(value, OrthancPluginQueueOrigin_Front);
     }
 
     uint64_t GetSize();
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    bool ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
+#endif
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    bool ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
+#endif
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
+    void Acknowledge(uint64_t valueId);
+#endif
   };
 #endif
 }


=====================================
Resources/SyncOrthancFolder.py
=====================================
@@ -19,8 +19,8 @@ FILES = [
     ('OrthancFramework/Resources/CMake/Compiler.cmake', 'CMake'),
     ('OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', 'CMake'),
     ('OrthancFramework/Resources/CMake/DownloadPackage.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/EmbedResources.py', 'CMake'),
     ('OrthancFramework/Resources/CMake/GoogleTestConfiguration.cmake', 'CMake'),
-    ('OrthancFramework/Resources/EmbedResources.py', 'CMake'),
     ('OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake', 'Toolchains'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain32.cmake', 'Toolchains'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain64.cmake', 'Toolchains'),


=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+orthanc-dicomweb (1.22+dfsg-1) UNRELEASED; urgency=medium
+
+  * New upstream version
+
+ -- Sebastien Jodogne <s.jodogne at gmail.com>  Tue, 09 Dec 2025 08:16:43 +0100
+
 orthanc-dicomweb (1.21+dfsg-2) unstable; urgency=medium
 
   * Added dependency on libjs-jquery. Closes: #1121714


=====================================
debian/patches/cmake
=====================================
@@ -2,11 +2,11 @@ Description: Fix the inclusion of the JavaScript libraries
 Author: Sebastien Jodogne <s.jodogne at orthanc-labs.com>
 ---
 This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
-Index: OrthancDicomWeb-1.21/CMakeLists.txt
+Index: OrthancDicomWeb-1.22/CMakeLists.txt
 ===================================================================
---- OrthancDicomWeb-1.21.orig/CMakeLists.txt
-+++ OrthancDicomWeb-1.21/CMakeLists.txt
-@@ -92,7 +92,7 @@ else()
+--- OrthancDicomWeb-1.22.orig/CMakeLists.txt
++++ OrthancDicomWeb-1.22/CMakeLists.txt
+@@ -98,7 +98,7 @@ else()
  endif()
  
  


=====================================
debian/patches/embed-resources deleted
=====================================
@@ -1,18 +0,0 @@
-Description: Fix the path to EmbedResources.py
-Author: Sebastien Jodogne <s.jodogne at orthanc-labs.com>
-Forwarded: https://orthanc.uclouvain.be/hg/orthanc-dicomweb/rev/d3bc898d8124
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
-Index: OrthancDicomWeb-1.21/Resources/Orthanc/CMake/AutoGeneratedCode.cmake
-===================================================================
---- OrthancDicomWeb-1.21.orig/Resources/Orthanc/CMake/AutoGeneratedCode.cmake
-+++ OrthancDicomWeb-1.21/Resources/Orthanc/CMake/AutoGeneratedCode.cmake
-@@ -20,7 +20,7 @@
- # <http://www.gnu.org/licenses/>.
- 
- 
--set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/../EmbedResources.py"
-+set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py"
-   CACHE INTERNAL "Path to the EmbedResources.py script from Orthanc")
- set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED")
- set(AUTOGENERATED_SOURCES)


=====================================
debian/patches/orthanc-framework
=====================================
@@ -0,0 +1,53 @@
+Description: Fix compatibility with Orthanc framework <= 1.12.10
+Author: Sebastien Jodogne <s.jodogne at orthanc-labs.com>
+Forwarded: https://orthanc.uclouvain.be/hg/orthanc-dicomweb/rev/f91a925218f2
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+Index: OrthancDicomWeb-1.22/Plugin/WadoRs.cpp
+===================================================================
+--- OrthancDicomWeb-1.22.orig/Plugin/WadoRs.cpp
++++ OrthancDicomWeb-1.22/Plugin/WadoRs.cpp
+@@ -32,9 +32,12 @@
+ #include <Toolbox.h>
+ #include <SerializationToolbox.h>
+ #include <MultiThreading/SharedMessageQueue.h>
+-#include <MultiThreading/BlockingSharedMessageQueue.h>
+ #include <Compression/GzipCompressor.h>
+ 
++#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 11)
++#  include <MultiThreading/BlockingSharedMessageQueue.h>
++#endif
++
+ #include <memory>
+ #include <boost/thread/mutex.hpp>
+ #include <boost/thread.hpp>
+@@ -445,11 +448,16 @@ public:
+ 
+ class ThreadedInstanceLoader : public InstanceLoader
+ {
++private:
+   std::vector<boost::thread*>         threads_;
+ 
+   Orthanc::SharedMessageQueue         instancesToPreload_;
+ 
++#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 11)
+   Orthanc::BlockingSharedMessageQueue loadedInstances_;
++#else
++  Orthanc::SharedMessageQueue         loadedInstances_;
++#endif
+ 
+   bool                                loadersShouldStop_;
+ 
+@@ -457,7 +465,11 @@ public:
+   ThreadedInstanceLoader(size_t threadCount, bool transcode, Orthanc::DicomTransferSyntax transferSyntax)
+   : InstanceLoader(transcode, transferSyntax),
+     instancesToPreload_(0),
+-    loadedInstances_(3*threadCount), // to limit the number of loaded instances in memory
++#if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 11)
++    loadedInstances_(3 * threadCount), // to limit the number of loaded instances in memory
++#else
++    loadedInstances_(0),  // don't limit the number of loaded instances, otherwise extra instances would be lost
++#endif
+     loadersShouldStop_(false)
+   {
+     for (size_t i = 0; i < threadCount; i++)


=====================================
debian/patches/series
=====================================
@@ -1,2 +1,2 @@
 cmake
-embed-resources
+orthanc-framework



View it on GitLab: https://salsa.debian.org/med-team/orthanc-dicomweb/-/compare/a8eb38aeba37ecf6528b33d336bd5fc041ae33d3...4d36ea3bf28a3e4af7b03296c9eb5d4a36b8c629

-- 
View it on GitLab: https://salsa.debian.org/med-team/orthanc-dicomweb/-/compare/a8eb38aeba37ecf6528b33d336bd5fc041ae33d3...4d36ea3bf28a3e4af7b03296c9eb5d4a36b8c629
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20251209/5fac3340/attachment-0001.htm>


More information about the debian-med-commit mailing list