changeset 1789:bdcc1dba4a53 worklists

optimization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 18 Nov 2015 16:38:08 +0100
parents 6a2d507ef064
children bec9edcf0d98
files OrthancServer/DicomProtocol/DicomFindAnswers.cpp OrthancServer/DicomProtocol/DicomFindAnswers.h OrthancServer/Internals/FindScp.cpp UnitTestsSources/FromDcmtkTests.cpp
diffstat 4 files changed, 117 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/DicomProtocol/DicomFindAnswers.cpp	Wed Nov 18 16:11:28 2015 +0100
+++ b/OrthancServer/DicomProtocol/DicomFindAnswers.cpp	Wed Nov 18 16:38:08 2015 +0100
@@ -38,56 +38,138 @@
 #include "../../Core/OrthancException.h"
 
 #include <memory>
+#include <dcmtk/dcmdata/dcfilefo.h>
+
 
 namespace Orthanc
 {
+  class DicomFindAnswers::Answer
+  {
+  private:
+    ParsedDicomFile* dicom_;
+    DicomMap*        map_;
+    
+  public:
+    Answer(ParsedDicomFile& dicom) : 
+      dicom_(dicom.Clone()),
+      map_(NULL)
+    {
+    }
+
+    Answer(const char* dicom,
+           size_t size) : 
+      dicom_(new ParsedDicomFile(dicom, size)),
+      map_(NULL)
+    {
+    }
+
+    Answer(const DicomMap& map) : 
+      dicom_(NULL),
+      map_(map.Clone())
+    {
+    }
+
+    ~Answer()
+    {
+      if (dicom_ != NULL)
+      {
+        delete dicom_;
+      }
+
+      if (map_ != NULL)
+      {
+        delete map_;
+      }
+    }
+
+    ParsedDicomFile& GetDicomFile()
+    {
+      if (dicom_ == NULL)
+      {
+        assert(map_ != NULL);
+        dicom_ = new ParsedDicomFile(*map_);
+      }
+
+      return *dicom_;
+    }
+
+    DcmDataset* ExtractDcmDataset() const
+    {
+      if (dicom_ != NULL)
+      {
+        return new DcmDataset(*dicom_->GetDcmtkObject().getDataset());
+      }
+      else
+      {
+        assert(map_ != NULL);
+        return ToDcmtkBridge::Convert(*map_);
+      }
+    }
+  };
+
+
   void DicomFindAnswers::Clear()
   {
-    for (size_t i = 0; i < items_.size(); i++)
+    for (size_t i = 0; i < answers_.size(); i++)
     {
-      assert(items_[i] != NULL);
-      delete items_[i];
+      assert(answers_[i] != NULL);
+      delete answers_[i];
     }
 
-    items_.clear();
+    answers_.clear();
   }
 
+
   void DicomFindAnswers::Reserve(size_t size)
   {
-    if (size > items_.size())
+    if (size > answers_.size())
     {
-      items_.reserve(size);
+      answers_.reserve(size);
     }
   }
 
 
   void DicomFindAnswers::Add(const DicomMap& map)
   {
-    items_.push_back(new ParsedDicomFile(map));
+    answers_.push_back(new Answer(map));
   }
 
+
   void DicomFindAnswers::Add(ParsedDicomFile& dicom)
   {
-    items_.push_back(dicom.Clone());
+    answers_.push_back(new Answer(dicom));
   }
 
+
   void DicomFindAnswers::Add(const char* dicom,
                              size_t size)
   {
-    items_.push_back(new ParsedDicomFile(dicom, size));
+    answers_.push_back(new Answer(dicom, size));
+  }
+
+
+  DicomFindAnswers::Answer& DicomFindAnswers::GetAnswerInternal(size_t index) const
+  {
+    if (index < answers_.size())
+    {
+      return *answers_.at(index);
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
   }
 
 
   ParsedDicomFile& DicomFindAnswers::GetAnswer(size_t index) const
   {
-    if (index < items_.size())
-    {
-      return *items_.at(index);
-    }
-    else
-    {
-      throw OrthancException(ErrorCode_ParameterOutOfRange);
-    }
+    return GetAnswerInternal(index).GetDicomFile();
+  }
+
+
+  DcmDataset* DicomFindAnswers::ExtractDcmDataset(size_t index) const
+  {
+    return GetAnswerInternal(index).ExtractDcmDataset();
   }
 
 
--- a/OrthancServer/DicomProtocol/DicomFindAnswers.h	Wed Nov 18 16:11:28 2015 +0100
+++ b/OrthancServer/DicomProtocol/DicomFindAnswers.h	Wed Nov 18 16:38:08 2015 +0100
@@ -39,7 +39,11 @@
   class DicomFindAnswers : public boost::noncopyable
   {
   private:
-    std::vector<ParsedDicomFile*> items_;
+    class Answer;
+
+    std::vector<Answer*> answers_;
+
+    Answer& GetAnswerInternal(size_t index) const;
 
   public:
     ~DicomFindAnswers()
@@ -60,11 +64,13 @@
 
     size_t GetSize() const
     {
-      return items_.size();
+      return answers_.size();
     }
 
     ParsedDicomFile& GetAnswer(size_t index) const;
 
+    DcmDataset* ExtractDcmDataset(size_t index) const;
+
     void ToJson(Json::Value& target,
                 bool simplify) const;
 
--- a/OrthancServer/Internals/FindScp.cpp	Wed Nov 18 16:11:28 2015 +0100
+++ b/OrthancServer/Internals/FindScp.cpp	Wed Nov 18 16:38:08 2015 +0100
@@ -186,11 +186,7 @@
       {
         // There are pending results that are still to be sent
         response->DimseStatus = STATUS_Pending;
-
-        DcmFileFormat& fileFormat = data.answers_.GetAnswer(responseCount - 1).GetDcmtkObject();
-
-        // TODO Is there a way to avoid this copy?
-        *responseIdentifiers = new DcmDataset(*fileFormat.getDataset());
+        *responseIdentifiers = data.answers_.ExtractDcmDataset(responseCount - 1);
       }
       else if (data.noCroppingOfResults_)
       {
--- a/UnitTestsSources/FromDcmtkTests.cpp	Wed Nov 18 16:11:28 2015 +0100
+++ b/UnitTestsSources/FromDcmtkTests.cpp	Wed Nov 18 16:38:08 2015 +0100
@@ -620,6 +620,12 @@
   }
 
   {
+    ParsedDicomFile d;
+    d.Replace(DICOM_TAG_PATIENT_ID, "my");
+    a.Add(d);
+  }
+
+  {
     DicomMap m;
     m.SetValue(DICOM_TAG_PATIENT_ID, "world");
     a.Add(m);
@@ -627,5 +633,7 @@
 
   Json::Value j;
   a.ToJson(j, true);
-  ASSERT_EQ(2u, j.size());
+  ASSERT_EQ(3u, j.size());
+
+  //std::cout << j;
 }