diff Framework/Plugins/StorageBackend.cpp @ 242:b97a537f4613

MySQL: Support of range reads for the storage area
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Apr 2021 17:00:02 +0200
parents 0a9b48d19643
children 02cd7254c949
line wrap: on
line diff
--- a/Framework/Plugins/StorageBackend.cpp	Tue Apr 13 12:07:30 2021 +0200
+++ b/Framework/Plugins/StorageBackend.cpp	Tue Apr 13 17:00:02 2021 +0200
@@ -85,10 +85,10 @@
   }
     
 
-  void StorageBackend::Accessor::Create(const std::string& uuid,
-                                        const void* content,
-                                        size_t size,
-                                        OrthancPluginContentType type)
+  void StorageBackend::AccessorBase::Create(const std::string& uuid,
+                                            const void* content,
+                                            size_t size,
+                                            OrthancPluginContentType type)
   {
     DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite);
 
@@ -113,9 +113,9 @@
   }
 
 
-  void StorageBackend::Accessor::Read(StorageBackend::IFileContentVisitor& visitor,
-                                      const std::string& uuid,
-                                      OrthancPluginContentType type) 
+  void StorageBackend::AccessorBase::ReadWhole(StorageBackend::IFileContentVisitor& visitor,
+                                               const std::string& uuid,
+                                               OrthancPluginContentType type) 
   {
     DatabaseManager::Transaction transaction(manager_, TransactionType_ReadOnly);
 
@@ -170,8 +170,18 @@
   }
 
 
-  void StorageBackend::Accessor::Remove(const std::string& uuid,
-                                        OrthancPluginContentType type)
+  void StorageBackend::AccessorBase::ReadRange(IFileContentVisitor& visitor,
+                                               const std::string& uuid,
+                                               OrthancPluginContentType type,
+                                               uint64_t start,
+                                               uint64_t length)
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+  }
+
+
+  void StorageBackend::AccessorBase::Remove(const std::string& uuid,
+                                            OrthancPluginContentType type)
   {
     DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite);
 
@@ -212,8 +222,8 @@
       }
       else
       {
-        StorageBackend::Accessor accessor(*backend_);
-        accessor.Create(uuid, content, static_cast<size_t>(size), type);
+        std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor());
+        accessor->Create(uuid, content, static_cast<size_t>(size), type);
         return OrthancPluginErrorCode_Success;
       }
     }
@@ -237,6 +247,10 @@
         target_(target),
         success_(false)
       {
+        if (target == NULL)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+        }
       }
 
       virtual bool IsSuccess() const ORTHANC_OVERRIDE
@@ -269,24 +283,94 @@
         }
       }
     };
-    
+
+
     try
     {
       if (backend_.get() == NULL)
       {
         throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
       }
-      else if (target == NULL)
+      else
+      {
+        Visitor visitor(target);
+
+        {
+          std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor());
+          accessor->ReadWhole(visitor, uuid, type);
+        }
+
+        return OrthancPluginErrorCode_Success;
+      }
+    }
+    ORTHANC_PLUGINS_DATABASE_CATCH;
+  }
+
+  
+  static OrthancPluginErrorCode StorageReadRange(OrthancPluginMemoryBuffer64* target,
+                                                 const char* uuid,
+                                                 OrthancPluginContentType type,
+                                                 uint64_t start)
+  {
+    class Visitor : public StorageBackend::IFileContentVisitor
+    {
+    private:
+      OrthancPluginMemoryBuffer64* target_;  // This buffer is already allocated by the Orthanc core
+      bool                         success_;
+      
+    public:
+      Visitor(OrthancPluginMemoryBuffer64* target) :
+        target_(target),
+        success_(false)
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+        if (target == NULL)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+        }
+      }
+
+      virtual bool IsSuccess() const ORTHANC_OVERRIDE
+      {
+        return success_;
+      }
+      
+      virtual void Assign(const std::string& content) ORTHANC_OVERRIDE
+      {
+        if (success_)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+        }
+        else
+        {
+          if (content.size() != target_->size)
+          {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+          }
+          
+          if (!content.empty())
+          {
+            memcpy(target_->data, content.c_str(), content.size());
+          }
+
+          success_ = true;
+        }
+      }
+    };
+
+
+    try
+    {
+      if (backend_.get() == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
       }
       else
       {
         Visitor visitor(target);
 
         {
-          StorageBackend::Accessor accessor(*backend_);
-          accessor.Read(visitor, uuid, type);
+          std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor());
+          accessor->ReadRange(visitor, uuid, type, start, target->size);
         }
 
         return OrthancPluginErrorCode_Success;
@@ -377,8 +461,8 @@
         Visitor visitor(data, size);
 
         {
-          StorageBackend::Accessor accessor(*backend_);
-          accessor.Read(visitor, uuid, type);
+          std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor());
+          accessor->ReadWhole(visitor, uuid, type);
         }
 
         return OrthancPluginErrorCode_Success;
@@ -399,8 +483,8 @@
       }
       else
       {
-        StorageBackend::Accessor accessor(*backend_);
-        accessor.Remove(uuid, type);
+        std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor());
+        accessor->Remove(uuid, type);
         return OrthancPluginErrorCode_Success;
       }
     }
@@ -434,8 +518,13 @@
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 0)
       if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 0) == 1)
       {
-        OrthancPluginRegisterStorageArea2(context_, StorageCreate, StorageReadWhole,
-                                          NULL /* TODO - StorageReadRange */, StorageRemove);
+        OrthancPluginStorageReadRange readRange = NULL;
+        if (backend_->HasReadRange())
+        {
+          readRange = StorageReadRange;
+        }
+        
+        OrthancPluginRegisterStorageArea2(context_, StorageCreate, StorageReadWhole, readRange, StorageRemove);
         hasLoadedV2 = true;
       }
 #  endif
@@ -456,44 +545,67 @@
   }
 
 
-  void StorageBackend::Accessor::ReadToString(std::string& target,
-                                              const std::string& uuid,
-                                              OrthancPluginContentType type)
+  class StorageBackend::StringVisitor : public StorageBackend::IFileContentVisitor
   {
-    class Visitor : public StorageBackend::IFileContentVisitor
+  private:
+    std::string&  target_;
+    bool          success_;
+      
+  public:
+    StringVisitor(std::string& target) :
+      target_(target),
+      success_(false)
     {
-    private:
-      std::string&  target_;
-      bool          success_;
-      
-    public:
-      Visitor(std::string& target) :
-        target_(target),
-        success_(false)
-      {
-      }
+    }
 
-      virtual bool IsSuccess() const ORTHANC_OVERRIDE
-      {
-        return success_;
-      }
+    virtual bool IsSuccess() const ORTHANC_OVERRIDE
+    {
+      return success_;
+    }
       
-      virtual void Assign(const std::string& content) ORTHANC_OVERRIDE
+    virtual void Assign(const std::string& content) ORTHANC_OVERRIDE
+    {
+      if (success_)
       {
-        if (success_)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-        }
-        else
-        {
-          target_.assign(content);
-          success_ = true;
-        }
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
       }
-    };
+      else
+      {
+        target_.assign(content);
+        success_ = true;
+      }
+    }
+  };
     
 
-    Visitor visitor(target);
-    Read(visitor, uuid, type);
+  void StorageBackend::ReadWholeToString(std::string& target,
+                                         IAccessor& accessor,
+                                         const std::string& uuid,
+                                         OrthancPluginContentType type)
+  {
+    StringVisitor visitor(target);
+    accessor.ReadWhole(visitor, uuid, type);
+
+    if (!visitor.IsSuccess())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
+  }
+    
+
+  void StorageBackend::ReadRangeToString(std::string& target,
+                                         IAccessor& accessor,
+                                         const std::string& uuid,
+                                         OrthancPluginContentType type,
+                                         uint64_t start,
+                                         uint64_t length)
+  {
+    StringVisitor visitor(target);
+    accessor.ReadRange(visitor, uuid, type, start, length);
+
+    if (!visitor.IsSuccess())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
   }
 }