changeset 1116:a08699daf78b broker

ParsedDicomFileCache
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 04 Nov 2019 15:54:35 +0100
parents 3730956f41a5
children 383aa2a7d426
files Framework/Oracle/GenericOracleRunner.cpp Framework/Oracle/ParseDicomFileCommand.cpp Framework/Oracle/ParseDicomFileCommand.h Framework/Toolbox/ParsedDicomFileCache.cpp Framework/Toolbox/ParsedDicomFileCache.h Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 6 files changed, 177 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Oracle/GenericOracleRunner.cpp	Thu Oct 31 18:38:26 2019 +0100
+++ b/Framework/Oracle/GenericOracleRunner.cpp	Mon Nov 04 15:54:35 2019 +0100
@@ -231,6 +231,19 @@
   {
     std::string path = GetPath(root, command.GetPath());
 
+    if (!Orthanc::SystemToolbox::IsRegularFile(path))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentFile);
+    }
+
+    uint64_t fileSize = Orthanc::SystemToolbox::GetFileSize(path);
+
+    // Check for 32bit systems
+    if (fileSize != static_cast<uint64_t>(static_cast<size_t>(fileSize)))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory);
+    }
+    
     DcmFileFormat f;
     bool ok;
 
@@ -257,7 +270,7 @@
 
     if (ok)
     {
-      return new ParseDicomFileCommand::SuccessMessage(command, f);
+      return new ParseDicomFileCommand::SuccessMessage(command, f, static_cast<size_t>(fileSize));
     }
     else
     {
--- a/Framework/Oracle/ParseDicomFileCommand.cpp	Thu Oct 31 18:38:26 2019 +0100
+++ b/Framework/Oracle/ParseDicomFileCommand.cpp	Mon Nov 04 15:54:35 2019 +0100
@@ -28,39 +28,28 @@
 namespace OrthancStone
 {
   ParseDicomFileCommand::SuccessMessage::SuccessMessage(const ParseDicomFileCommand& command,
-                                                        DcmFileFormat& content) :
-    OriginMessage(command)
+                                                        DcmFileFormat& content,
+                                                        size_t fileSize) :
+    OriginMessage(command),
+    fileSize_(fileSize)
   {
     dicom_.reset(new Orthanc::ParsedDicomFile(content));
-  }
 
-
-  Orthanc::ParsedDicomFile& ParseDicomFileCommand::SuccessMessage::GetDicom() const
-  {
-    if (dicom_.get())
+    if (!dicom_->GetTagValue(sopInstanceUid_, Orthanc::DICOM_TAG_SOP_INSTANCE_UID))
     {
-      return *dicom_;
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
+                                      "DICOM instance missing tag SOPInstanceUID");
     }
   }
 
 
-  Orthanc::ParsedDicomFile* ParseDicomFileCommand::SuccessMessage::ReleaseDicom()
+  boost::shared_ptr<Orthanc::ParsedDicomFile> ParseDicomFileCommand::SuccessMessage::GetDicom() const
   {
-    if (dicom_.get())
-    {
-      return dicom_.release();
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
+    assert(dicom_.get() != NULL);
+    return dicom_;
   }
 
-  
+
   std::string ParseDicomFileCommand::GetDicomDirPath(const std::string& dicomDirPath,
                                                      const std::string& file)
   {
--- a/Framework/Oracle/ParseDicomFileCommand.h	Thu Oct 31 18:38:26 2019 +0100
+++ b/Framework/Oracle/ParseDicomFileCommand.h	Mon Nov 04 15:54:35 2019 +0100
@@ -46,20 +46,26 @@
       ORTHANC_STONE_MESSAGE(__FILE__, __LINE__);
 
     private:
-      std::auto_ptr<Orthanc::ParsedDicomFile>  dicom_;
+      boost::shared_ptr<Orthanc::ParsedDicomFile>  dicom_;
+      size_t                                       fileSize_;
+      std::string                                  sopInstanceUid_;
 
     public:
       SuccessMessage(const ParseDicomFileCommand& command,
-                     DcmFileFormat& content);
+                     DcmFileFormat& content,
+                     size_t fileSize);
 
-      bool HasDicom() const
+      size_t GetFileSize() const
       {
-        return dicom_.get() != NULL;
+        return fileSize_;
       }
-
-      Orthanc::ParsedDicomFile& GetDicom() const;
-
-      Orthanc::ParsedDicomFile* ReleaseDicom();
+      
+      const std::string& GetSopInstanceUid() const
+      {
+        return sopInstanceUid_;
+      }
+      
+      boost::shared_ptr<Orthanc::ParsedDicomFile> GetDicom() const;
     };
 
   private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Toolbox/ParsedDicomFileCache.cpp	Mon Nov 04 15:54:35 2019 +0100
@@ -0,0 +1,69 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "ParsedDicomFileCache.h"
+
+namespace OrthancStone
+{
+  class ParsedDicomFileCache::Item : public Orthanc::ICacheable
+  {
+  private:
+    std::auto_ptr<Orthanc::ParsedDicomFile>  dicom_;
+    size_t                                   fileSize_;
+
+  public:
+    Item(Orthanc::ParsedDicomFile* dicom,
+         size_t fileSize) :
+      dicom_(dicom),
+      fileSize_(fileSize)
+    {
+      if (dicom == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      }
+    }           
+           
+    virtual size_t GetMemoryUsage() const
+    {
+      return fileSize_;
+    }
+
+    const Orthanc::ParsedDicomFile& GetDicom() const
+    {
+      assert(dicom_.get() != NULL);
+      return *dicom_;
+    }
+  };
+    
+
+  void ParsedDicomFileCache::Acquire(const std::string& sopInstanceUid,
+                                     Orthanc::ParsedDicomFile* dicom,
+                                     size_t fileSize)
+  {
+    cache_.Acquire(sopInstanceUid, new Item(dicom, fileSize));
+  }
+
+  
+  const Orthanc::ParsedDicomFile& ParsedDicomFileCache::Reader::GetDicom() const
+  {
+    return dynamic_cast<const Item&>(reader_.GetValue()).GetDicom();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Toolbox/ParsedDicomFileCache.h	Mon Nov 04 15:54:35 2019 +0100
@@ -0,0 +1,66 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include <Core/Cache/MemoryObjectCache.h>
+#include <Core/DicomParsing/ParsedDicomFile.h>
+
+namespace OrthancStone
+{
+  class ParsedDicomFileCache : public boost::noncopyable
+  {
+  private:
+    class Item;
+    
+    Orthanc::MemoryObjectCache  cache_;
+
+  public:
+    ParsedDicomFileCache(size_t size)
+    {
+      cache_.SetMaximumSize(size);
+    }
+    
+    void Acquire(const std::string& sopInstanceUid,
+                 Orthanc::ParsedDicomFile* dicom,  // Takes ownership
+                 size_t fileSize);
+
+    class Reader : public boost::noncopyable
+    {
+    private:
+      Orthanc::MemoryObjectCache::Reader reader_;
+
+    public:
+      Reader(ParsedDicomFileCache& cache,
+             const std::string& sopInstanceUid) :
+        reader_(cache.cache_, sopInstanceUid)
+      {
+      }
+
+      bool IsValid() const
+      {
+        return reader_.IsValid();
+      }
+
+      const Orthanc::ParsedDicomFile& GetDicom() const;
+    };
+  };
+}
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Thu Oct 31 18:38:26 2019 +0100
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Mon Nov 04 15:54:35 2019 +0100
@@ -402,6 +402,7 @@
 if (ENABLE_DCMTK)
   list(APPEND ORTHANC_STONE_SOURCES
     ${ORTHANC_STONE_ROOT}/Framework/Oracle/ParseDicomFileCommand.cpp
+    ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ParsedDicomFileCache.cpp
     )
 endif()
 
@@ -562,6 +563,8 @@
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/Extent2D.h
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/FiniteProjectiveCamera.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/FiniteProjectiveCamera.h
+  ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GenericToolbox.cpp
+  ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GenericToolbox.h
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GeometryToolbox.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GeometryToolbox.h
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ImageGeometry.cpp
@@ -578,8 +581,6 @@
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/TextRenderer.h
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/UndoRedoStack.cpp
   ${ORTHANC_STONE_ROOT}/Framework/Toolbox/UndoRedoStack.h
-  ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GenericToolbox.cpp
-  ${ORTHANC_STONE_ROOT}/Framework/Toolbox/GenericToolbox.h
   
   ${ORTHANC_STONE_ROOT}/Framework/Viewport/IViewport.h
   ${ORTHANC_STONE_ROOT}/Framework/Viewport/ViewportBase.h