changeset 6800:7d025f650e9f

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 18 May 2026 14:07:18 +0200
parents cdf8b88c60c8 (current diff) 8ac77592226e (diff)
children e98c73866fcb
files OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h
diffstat 2 files changed, 39 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Sources/ServerContext.cpp	Mon May 18 14:02:50 2026 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Mon May 18 14:07:18 2026 +0200
@@ -1404,6 +1404,16 @@
                                 std::string& attachmentId,
                                 const std::string& instancePublicId)
   {
+    std::unique_ptr<Semaphore::Locker> dummyLargeDicomLocker;  // only the DicomCacheLocker uses a real largeDicomLocker_
+    ReadDicomInternal(dicom, attachmentId, instancePublicId, dummyLargeDicomLocker, 0);
+  }
+
+  void ServerContext::ReadDicomInternal(std::string& dicom,
+                                        std::string& attachmentId,
+                                        const std::string& instancePublicId,
+                                        std::unique_ptr<Semaphore::Locker>& largeDicomLocker,
+                                        std::size_t largeDicomThreshold)
+  {
     FileInfo attachment;
     int64_t revision;
 
@@ -1417,6 +1427,11 @@
     assert(attachment.GetContentType() == FileContentType_Dicom);
     attachmentId = attachment.GetUuid();
 
+    if (attachment.GetUncompressedSize() < largeDicomThreshold)  // release ASAP (before the read) if we don't plan to hold the lock (https://discourse.orthanc-server.org/t/patch-release-large-dicom-semaphore-lock-early-for-better-performance/6440)
+    {
+      largeDicomLocker.reset(NULL);
+    }
+
     ReadAttachment(dicom, attachment, true /* uncompress */);
   }
 
@@ -1428,6 +1443,15 @@
     ReadDicom(dicom, attachmentId, instancePublicId);    
   }
 
+  void ServerContext::ReadDicomInternal(std::string& dicom,
+                                        const std::string& instancePublicId,
+                                        std::unique_ptr<Semaphore::Locker>& largeDicomLocker,
+                                        std::size_t largeDicomThreshold)
+  {
+    std::string attachmentId;
+    ReadDicomInternal(dicom, attachmentId, instancePublicId, largeDicomLocker, largeDicomThreshold);
+  }
+
   void ServerContext::ReadDicomForHeader(std::string& dicom,
                                          const std::string& instancePublicId)
   {
@@ -1540,17 +1564,12 @@
     {
       accessor_.reset(NULL);
 
-      // Throttle to avoid loading several large DICOM files simultaneously
+      // Throttle to avoid loading several large DICOM files simultaneously (since the ParsedDicomCache is 128MB, loading multiple 50MB files would throw them out directly after loading)
       largeDicomLocker_.reset(new Semaphore::Locker(context.largeDicomThrottler_));
       
-      context_.ReadDicom(buffer_, instancePublicId_);
-
       // Release the throttle if loading "small" DICOM files (under
       // 50MB, which is an arbitrary value)
-      if (buffer_.size() < static_cast<size_t>(50) * 1024 * 1024)
-      {
-        largeDicomLocker_.reset(NULL);
-      }
+      context_.ReadDicomInternal(buffer_, instancePublicId_, largeDicomLocker_, static_cast<size_t>(50) * 1024 * 1024);
       
       dicom_.reset(new ParsedDicomFile(buffer_));
       dicomSize_ = buffer_.size();
--- a/OrthancServer/Sources/ServerContext.h	Mon May 18 14:02:50 2026 +0200
+++ b/OrthancServer/Sources/ServerContext.h	Mon May 18 14:07:18 2026 +0200
@@ -398,6 +398,19 @@
     void ReadDicomAsJson(Json::Value& result,
                          const std::string& instancePublicId);  // TODO-FIND: Can this be removed?
 
+private:
+    void ReadDicomInternal(std::string& dicom,
+                           const std::string& instancePublicId,
+                           std::unique_ptr<Semaphore::Locker>& largeDicomLocker,
+                           std::size_t largeDicomThreshold);
+
+    void ReadDicomInternal(std::string& dicom,
+                           std::string& attachmentId,
+                           const std::string& instancePublicId,
+                           std::unique_ptr<Semaphore::Locker>& largeDicomLocker,
+                           std::size_t largeDicomThreshold);
+
+public:
     void ReadDicom(std::string& dicom,
                    const std::string& instancePublicId);