changeset 4495:fa2311f94d9f

IStorageArea::ReadRange()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 04 Feb 2021 18:01:07 +0100
parents 39192eb9b43d
children 9ea70ccf0c21
files OrthancFramework/Sources/DicomParsing/ParsedDicomCache.cpp OrthancFramework/Sources/DicomParsing/ParsedDicomCache.h OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp OrthancFramework/Sources/FileStorage/FilesystemStorage.h OrthancFramework/Sources/FileStorage/IStorageArea.h OrthancFramework/Sources/FileStorage/MemoryStorageArea.cpp OrthancFramework/Sources/FileStorage/MemoryStorageArea.h OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Sources/OrthancInitialization.cpp
diffstat 9 files changed, 196 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomCache.cpp	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomCache.cpp	Thu Feb 04 18:01:07 2021 +0100
@@ -186,6 +186,12 @@
   }
 
 
+  bool ParsedDicomCache::Accessor::IsValid() const
+  {
+    return file_ != NULL;
+  }
+
+
   ParsedDicomFile& ParsedDicomCache::Accessor::GetDicom() const
   {
     if (IsValid())
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomCache.h	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomCache.h	Thu Feb 04 18:01:07 2021 +0100
@@ -72,10 +72,7 @@
       Accessor(ParsedDicomCache& that,
                const std::string& id);
 
-      bool IsValid() const
-      {
-        return file_ != NULL;
-      }
+      bool IsValid() const;
 
       ParsedDicomFile& GetDicom() const;
 
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.cpp	Thu Feb 04 18:01:07 2021 +0100
@@ -164,6 +164,22 @@
   }
 
 
+  IMemoryBuffer* FilesystemStorage::ReadRange(const std::string& uuid,
+                                              FileContentType type,
+                                              uint64_t start /* inclusive */,
+                                              uint64_t end /* exclusive */)
+  {
+    LOG(INFO) << "Reading attachment \"" << uuid << "\" of \"" << GetDescriptionInternal(type) 
+              << "\" content type (range from " << start << " to " << end << ")";
+
+    std::string content;
+    SystemToolbox::ReadFileRange(
+      content, GetPath(uuid).string(), start, end, true /* throw if overflow */);
+
+    return StringMemoryBuffer::CreateFromSwap(content);
+  }
+
+
   uintmax_t FilesystemStorage::GetSize(const std::string& uuid) const
   {
     boost::filesystem::path path = GetPath(uuid);
--- a/OrthancFramework/Sources/FileStorage/FilesystemStorage.h	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/FileStorage/FilesystemStorage.h	Thu Feb 04 18:01:07 2021 +0100
@@ -81,6 +81,11 @@
     virtual IMemoryBuffer* Read(const std::string& uuid,
                                 FileContentType type) ORTHANC_OVERRIDE;
 
+    virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                     FileContentType type,
+                                     uint64_t start /* inclusive */,
+                                     uint64_t end /* exclusive */) ORTHANC_OVERRIDE;
+
     virtual void Remove(const std::string& uuid,
                         FileContentType type) ORTHANC_OVERRIDE;
 
--- a/OrthancFramework/Sources/FileStorage/IStorageArea.h	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/FileStorage/IStorageArea.h	Thu Feb 04 18:01:07 2021 +0100
@@ -44,6 +44,11 @@
     virtual IMemoryBuffer* Read(const std::string& uuid,
                                 FileContentType type) = 0;
 
+    virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                     FileContentType type,
+                                     uint64_t start /* inclusive */,
+                                     uint64_t end /* exclusive */) = 0;
+
     virtual void Remove(const std::string& uuid,
                         FileContentType type) = 0;
   };
--- a/OrthancFramework/Sources/FileStorage/MemoryStorageArea.cpp	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/FileStorage/MemoryStorageArea.cpp	Thu Feb 04 18:01:07 2021 +0100
@@ -91,6 +91,55 @@
   }
       
 
+  IMemoryBuffer* MemoryStorageArea::ReadRange(const std::string& uuid,
+                                              FileContentType type,
+                                              uint64_t start /* inclusive */,
+                                              uint64_t end /* exclusive */)
+  {
+    LOG(INFO) << "Reading attachment \"" << uuid << "\" of \""
+              << static_cast<int>(type) << "\" content type "
+              << "(range from " << start << " to " << end << ")";
+
+    if (start > end)
+    {
+      throw OrthancException(ErrorCode_BadRange);
+    }
+    else if (start == end)
+    {
+      return new StringMemoryBuffer;
+    }
+    else
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+
+      Content::const_iterator found = content_.find(uuid);
+
+      if (found == content_.end())
+      {
+        throw OrthancException(ErrorCode_InexistentFile);
+      }
+      else if (found->second == NULL)
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }
+      else if (end > found->second->size())
+      {
+        throw OrthancException(ErrorCode_BadRange);
+      }
+      else
+      {
+        std::string range;
+        range.resize(end - start);
+        assert(!range.empty());
+
+        memcpy(&range[0], &found->second[start], range.size());
+        
+        return StringMemoryBuffer::CreateFromSwap(range);
+      }
+    }
+  }
+
+
   void MemoryStorageArea::Remove(const std::string& uuid,
                                  FileContentType type)
   {
--- a/OrthancFramework/Sources/FileStorage/MemoryStorageArea.h	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancFramework/Sources/FileStorage/MemoryStorageArea.h	Thu Feb 04 18:01:07 2021 +0100
@@ -50,6 +50,11 @@
     virtual IMemoryBuffer* Read(const std::string& uuid,
                                 FileContentType type) ORTHANC_OVERRIDE;
 
+    virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                     FileContentType type,
+                                     uint64_t start /* inclusive */,
+                                     uint64_t end /* exclusive */) ORTHANC_OVERRIDE;
+    
     virtual void Remove(const std::string& uuid,
                         FileContentType type) ORTHANC_OVERRIDE;
   };
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Feb 04 18:01:07 2021 +0100
@@ -63,6 +63,7 @@
 #include "../../../OrthancFramework/Sources/MetricsRegistry.h"
 #include "../../../OrthancFramework/Sources/OrthancException.h"
 #include "../../../OrthancFramework/Sources/SerializationToolbox.h"
+#include "../../../OrthancFramework/Sources/StringMemoryBuffer.h"
 #include "../../../OrthancFramework/Sources/Toolbox.h"
 #include "../../Sources/OrthancConfiguration.h"
 #include "../../Sources/OrthancFindRequestHandler.h"
@@ -211,6 +212,46 @@
       {
         return errorDictionary_;
       }
+
+      IMemoryBuffer* RangeFromWhole(const std::string& uuid,
+                                    FileContentType type,
+                                    uint64_t start /* inclusive */,
+                                    uint64_t end /* exclusive */)
+      {
+        if (start > end)
+        {
+          throw OrthancException(ErrorCode_BadRange);
+        }
+        else if (start == end)
+        {
+          return new StringMemoryBuffer;  // Empty
+        }
+        else
+        {
+          std::unique_ptr<IMemoryBuffer> whole(Read(uuid, type));
+
+          if (start == 0 &&
+              end == whole->GetSize())
+          {
+            return whole.release();
+          }
+          else if (end > whole->GetSize())
+          {
+            throw OrthancException(ErrorCode_BadRange);
+          }
+          else
+          {
+            std::string range;
+            range.resize(end - start);
+            assert(!range.empty());
+            
+            memcpy(&range[0], reinterpret_cast<const char*>(whole->GetData()) + start, range.size());
+
+            whole.reset(NULL);
+            return StringMemoryBuffer::CreateFromSwap(range);
+          }
+        }
+      }      
       
     public:
       StorageAreaBase(OrthancPluginStorageCreate create,
@@ -306,6 +347,14 @@
           throw OrthancException(static_cast<ErrorCode>(error));
         }
       }
+
+      virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                       FileContentType type,
+                                       uint64_t start /* inclusive */,
+                                       uint64_t end /* exclusive */) ORTHANC_OVERRIDE
+      {
+        return RangeFromWhole(uuid, type, start, end);
+      }
     };
 
 
@@ -349,6 +398,51 @@
           throw OrthancException(static_cast<ErrorCode>(error));
         }
       }
+
+      virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                       FileContentType type,
+                                       uint64_t start /* inclusive */,
+                                       uint64_t end /* exclusive */) ORTHANC_OVERRIDE
+      {
+        if (readRange_ == NULL)
+        {
+          return RangeFromWhole(uuid, type, start, end);
+        }
+        else
+        {
+          if (start > end)
+          {
+            throw OrthancException(ErrorCode_BadRange);
+          }
+          else if (start == end)
+          {
+            return new StringMemoryBuffer;
+          }
+          else
+          {
+            std::string range;
+            range.resize(end - start);
+            assert(!range.empty());
+
+            OrthancPluginMemoryBuffer64 buffer;
+            buffer.data = &range[0];
+            buffer.size = static_cast<uint64_t>(range.size());
+
+            OrthancPluginErrorCode error =
+              readRange_(&buffer, uuid.c_str(), Plugins::Convert(type), start);
+
+            if (error == OrthancPluginErrorCode_Success)
+            {
+              return StringMemoryBuffer::CreateFromSwap(range);
+            }
+            else
+            {
+              GetErrorDictionary().LogError(error, true);
+              throw OrthancException(static_cast<ErrorCode>(error));
+            }
+          }
+        }
+      }
     };
 
 
--- a/OrthancServer/Sources/OrthancInitialization.cpp	Thu Feb 04 15:31:00 2021 +0100
+++ b/OrthancServer/Sources/OrthancInitialization.cpp	Thu Feb 04 18:01:07 2021 +0100
@@ -380,6 +380,21 @@
         }
       }
 
+      virtual IMemoryBuffer* ReadRange(const std::string& uuid,
+                                       FileContentType type,
+                                       uint64_t start /* inclusive */,
+                                       uint64_t end /* exclusive */) ORTHANC_OVERRIDE
+      {
+        if (type != FileContentType_Dicom)
+        {
+          return storage_.ReadRange(uuid, type, start, end);
+        }
+        else
+        {
+          throw OrthancException(ErrorCode_UnknownResource);
+        }
+      }
+
       virtual void Remove(const std::string& uuid,
                           FileContentType type) ORTHANC_OVERRIDE
       {