[med-svn] [Git][med-team/orthanc-dicomweb][master] 9 commits: New upstream version 1.15+dfsg

Andreas Tille (@tille) gitlab at salsa.debian.org
Sun Oct 29 20:23:51 GMT 2023



Andreas Tille pushed to branch master at Debian Med / orthanc-dicomweb


Commits:
c893b9e5 by Andreas Tille at 2023-10-29T20:52:03+01:00
New upstream version 1.15+dfsg
- - - - -
dcf2a253 by Andreas Tille at 2023-10-29T20:52:03+01:00
routine-update: New upstream version

- - - - -
c420bc14 by Andreas Tille at 2023-10-29T20:52:03+01:00
Update upstream source from tag 'upstream/1.15+dfsg'

Update to upstream version '1.15+dfsg'
with Debian dir 231ce8d945996f039d432309e041e4cea744fcdd
- - - - -
91d0cfaf by Andreas Tille at 2023-10-29T20:52:03+01:00
routine-update: debhelper-compat 13

- - - - -
7108c956 by Andreas Tille at 2023-10-29T20:52:07+01:00
routine-update: Remove trailing whitespace in debian/copyright

- - - - -
a2a63e4a by Andreas Tille at 2023-10-29T20:52:07+01:00
routine-update: Add salsa-ci file

- - - - -
f5a37951 by Andreas Tille at 2023-10-29T20:52:07+01:00
routine-update: Rules-Requires-Root: no

- - - - -
3283571f by Andreas Tille at 2023-10-29T20:52:24+01:00
routine-update: watch file standard 4

- - - - -
c12b17a5 by Andreas Tille at 2023-10-29T21:23:20+01:00
Build-Depends: pybuild-plugin-pyproject

- - - - -


19 changed files:

- .hg_archival.txt
- CMakeLists.txt
- NEWS
- Plugin/Configuration.cpp
- Plugin/Configuration.h
- Plugin/DicomWebFormatter.cpp
- Plugin/DicomWebFormatter.h
- Plugin/Plugin.cpp
- Plugin/WadoRs.cpp
- Plugin/WadoRs.h
- README
- Resources/CMake/JavaScriptLibraries.cmake
- Resources/Orthanc/CMake/DownloadOrthancFramework.cmake
- debian/changelog
- − debian/compat
- debian/control
- debian/copyright
- + debian/salsa-ci.yml
- debian/watch


Changes:

=====================================
.hg_archival.txt
=====================================
@@ -1,6 +1,6 @@
 repo: d5f45924411123cfd02d035fd50b8e37536eadef
-node: b208c07f0fcea822e44208ee4d9927ea0af803ee
-branch: OrthancDicomWeb-1.14
+node: 8ccaf9f005a783c7ccd0a98aa438c58bd07a922a
+branch: OrthancDicomWeb-1.15
 latesttag: null
-latesttagdistance: 540
-changessincelatesttag: 572
+latesttagdistance: 549
+changessincelatesttag: 581


=====================================
CMakeLists.txt
=====================================
@@ -22,13 +22,13 @@ cmake_minimum_required(VERSION 2.8)
 
 project(OrthancDicomWeb)
 
-set(ORTHANC_DICOM_WEB_VERSION "1.14")
+set(ORTHANC_DICOM_WEB_VERSION "1.15")
 
 if (ORTHANC_DICOM_WEB_VERSION STREQUAL "mainline")
   set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline")
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg")
 else()
-  set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.1")
+  set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "daf4807631c5")  # TODO: upgrade to 1.12.2 when available
   set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web")
 endif()
 
@@ -85,7 +85,8 @@ else()
   set(ENABLE_PUGIXML ON)
   set(ENABLE_MODULE_JOBS OFF)
   set(USE_BOOST_ICONV ON)
-  
+  set(ENABLE_ZLIB ON)
+    
   include(${ORTHANC_FRAMEWORK_ROOT}/../Resources/CMake/OrthancFrameworkConfiguration.cmake)
   include_directories(${ORTHANC_FRAMEWORK_ROOT})
 endif()
@@ -204,6 +205,8 @@ add_library(OrthancDicomWeb SHARED ${CORE_SOURCES}
 
 add_dependencies(OrthancDicomWeb AutogeneratedTarget)
 
+DefineSourceBasenameForTarget(OrthancDicomWeb)
+
 message("Setting the version of the library to ${ORTHANC_DICOM_WEB_VERSION}")
 
 add_definitions(-DORTHANC_DICOM_WEB_VERSION="${ORTHANC_DICOM_WEB_VERSION}")


=====================================
NEWS
=====================================
@@ -1,3 +1,16 @@
+Version 1.15 (2023-08-24)
+=========================
+
+* speed improvement:
+  - Now storing the output of /dicom-web/studies/../series/../metadata route in an attachment that can be used
+    by the "Full" mode.
+    The json file is gzipped and stored in attachment 4301 everytime a series is stable or the first time
+    its /dicom-web/studies/../series/../metadata route is called in "Full" mode if the attachment does not exist yet.
+    A new route /studies/{orthancId}/update-dicomweb-cache has also been added to allow e.g. the Housekeeper plugin
+    to generate these attachment for old studies.
+    This cache can be disabled by setting "EnableMetadataCache" to false.  However, disabling the cache
+    won't delete the already cached data.  You may call DELETE /series/../attachments/4031 to clear the cache.
+
 Version 1.14 (2023-07-05)
 =========================
 


=====================================
Plugin/Configuration.cpp
=====================================
@@ -676,6 +676,11 @@ namespace OrthancPlugins
       return GetUnsignedIntegerValue("MetadataWorkerThreadsCount", 4);
     }
 
+    bool IsMetadataCacheEnabled()
+    {
+      return GetBooleanValue("EnableMetadataCache", true);
+    }
+
     
     MetadataMode GetMetadataMode(Orthanc::ResourceType level)
     {


=====================================
Plugin/Configuration.h
=====================================
@@ -48,7 +48,7 @@ namespace OrthancPlugins
 
   enum MetadataMode
   {
-    MetadataMode_Full,           // Read all the DICOM instances from the storage area
+    MetadataMode_Full,           // Read all the DICOM instances from the storage area and store them in an attachment on StableSeries event
     MetadataMode_MainDicomTags,  // Only use the Orthanc database (main DICOM tags only)
     MetadataMode_Extrapolate     // Extrapolate user-specified tags from a few DICOM instances
   };
@@ -139,5 +139,7 @@ namespace OrthancPlugins
     void SaveDicomWebServers();
 
     unsigned int GetMetadataWorkerThreadsCount();
+
+    bool IsMetadataCacheEnabled();
   }
 }


=====================================
Plugin/DicomWebFormatter.cpp
=====================================
@@ -165,7 +165,7 @@ namespace OrthancPlugins
     first_(true)
   {
     if (context_ == NULL ||
-        output_ == NULL)
+        (isXml_ && output_ == NULL))  // allow no output when working with Json output.
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
     }
@@ -289,8 +289,8 @@ namespace OrthancPlugins
   }
 
 
-  void DicomWebFormatter::HttpWriter::AddDicomWebSerializedJson(const void* data,
-                                                                size_t size)
+  void DicomWebFormatter::HttpWriter::AddDicomWebInstanceSerializedJson(const void* data,
+                                                                        size_t size)
   {
     if (isXml_)
     {
@@ -318,6 +318,41 @@ namespace OrthancPlugins
     jsonBuffer_.AddChunk(data, size);
   }
 
+  void DicomWebFormatter::HttpWriter::AddDicomWebSeriesSerializedJson(const void* data,
+                                                                      size_t size)
+  {
+    if (isXml_)
+    {
+      // This function can only be used in the JSON case
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+
+#if !defined(NDEBUG)  // In debug mode, check that the value is actually a JSON string
+    Json::Value json;
+    if (!OrthancPlugins::ReadJson(json, data, size))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+    }
+#endif
+    
+    if (size <= 2 ||
+        reinterpret_cast<const char*>(data)[0] != '[' ||
+        reinterpret_cast<const char*>(data)[size-1] != ']')
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "The series metadata json does not contain an array.");
+    }
+
+    if (first_)
+    {
+      first_ = false;
+    }
+    else
+    {
+      jsonBuffer_.AddChunk(",");
+    }
+    
+    jsonBuffer_.AddChunk(reinterpret_cast<const char*>(data) + 1, size - 2);  // remove leading and trailing []
+  }
 
   void DicomWebFormatter::HttpWriter::Send()
   {
@@ -331,6 +366,15 @@ namespace OrthancPlugins
     }
   }
 
+  void DicomWebFormatter::HttpWriter::CloseAndGetJsonOutput(std::string& target)
+  {
+    if (!isXml_)
+    {
+      jsonBuffer_.AddChunk("]");
+      
+      jsonBuffer_.Flatten(target);
+    }
+  }
 
   void DicomWebFormatter::HttpWriter::AddInstance(const DicomInstance& instance,
                                                   const std::string& bulkRoot)


=====================================
Plugin/DicomWebFormatter.h
=====================================
@@ -115,11 +115,16 @@ namespace OrthancPlugins
 
       void AddOrthancJson(const Json::Value& value);
 
-      void AddDicomWebSerializedJson(const void* data,
-                                     size_t size);
+      void AddDicomWebInstanceSerializedJson(const void* data,
+                                             size_t size);
+
+      void AddDicomWebSeriesSerializedJson(const void* data,
+                                           size_t size);
 
       void Send();
 
+      void CloseAndGetJsonOutput(std::string& target);
+
       void AddInstance(const DicomInstance& instance,
                        const std::string& bulkRoot);
     };


=====================================
Plugin/Plugin.cpp
=====================================
@@ -471,6 +471,10 @@ static OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeTyp
         OrthancPlugins::Configuration::LoadDicomWebServers();
         break;
 
+      case OrthancPluginChangeType_StableSeries:
+        CacheSeriesMetadata(resourceId);
+        break;
+
       default:
         break;
     }
@@ -599,6 +603,8 @@ extern "C"
         OrthancPlugins::RegisterRestCallback<RetrieveInstanceRendered>(root + "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/rendered", true);
         OrthancPlugins::RegisterRestCallback<RetrieveFrameRendered>(root + "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/frames/([^/]*)/rendered", true);
 
+        OrthancPlugins::RegisterRestCallback<UpdateSeriesMetadataCache>("/studies/([^/]*)/update-dicomweb-cache", true);
+
         OrthancPluginRegisterOnChangeCallback(context, OnChangeCallback);
 
 


=====================================
Plugin/WadoRs.cpp
=====================================
@@ -29,12 +29,18 @@
 #include <HttpServer/HttpContentNegociation.h>
 #include <Logging.h>
 #include <Toolbox.h>
+#include <SerializationToolbox.h>
 #include <MultiThreading/SharedMessageQueue.h>
+#include <Compression/GzipCompressor.h>
 
 #include <memory>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/predicate.hpp>
 
+static const std::string SERIES_METADATA_ATTACHMENT_ID = "4301";
+static std::string WADO_BASE_PLACEHOLDER = "$WADO_BASE_PLACEHOLDER$";
 static const char* const MAIN_DICOM_TAGS = "MainDicomTags";
 static const char* const REQUESTED_TAGS = "RequestedTags";
 static const char* const INSTANCES = "Instances";
@@ -878,7 +884,7 @@ static void WriteInstanceMetadata(OrthancPlugins::DicomWebFormatter::HttpWriter&
   {
     if (buffer.RestApiGet("/instances/" + orthancId + "/attachments/4444/data", false))
     {
-      writer.AddDicomWebSerializedJson(buffer.GetData(), buffer.GetSize());
+      writer.AddDicomWebInstanceSerializedJson(buffer.GetData(), buffer.GetSize());
     }
     else if (buffer.RestApiGet("/instances/" + orthancId + "/file", false))
     {
@@ -894,7 +900,7 @@ static void WriteInstanceMetadata(OrthancPlugins::DicomWebFormatter::HttpWriter&
       }
 
       buffer.RestApiPut("/instances/" + orthancId + "/attachments/4444", dicomweb, false);
-      writer.AddDicomWebSerializedJson(dicomweb.c_str(), dicomweb.size());
+      writer.AddDicomWebInstanceSerializedJson(dicomweb.c_str(), dicomweb.size());
     }
   }
 #endif
@@ -1074,7 +1080,7 @@ void RetrieveDicomInstance(OrthancPluginRestOutput* output,
 }
 
 
-static void GetChildrenIdentifiers(std::list<std::string>& target,
+static void GetChildrenIdentifiers(std::set<std::string>& target,
                                    std::string& resourceDicomUid,
                                    Orthanc::ResourceType level,
                                    const std::string& orthancId)
@@ -1119,7 +1125,7 @@ static void GetChildrenIdentifiers(std::list<std::string>& target,
 
     for (Json::Value::ArrayIndex i = 0; i < children.size(); i++)
     {
-      target.push_back(children[i].asString());
+      target.insert(children[i].asString());
     }
   }  
 }
@@ -1250,7 +1256,7 @@ void InstanceWorkerThread(InstanceWorkerData* data)
           instanceToLoad->bulkRoot = (data->wadoBase +
                               "studies/" + instanceToLoad->studyInstanceUid +
                               "/series/" + instanceToLoad->seriesInstanceUid + 
-                              "/instances/" + instanceResource["MainDicomTags"]["SOPInstanceUID"].asString() + "/bulk");
+                              "/instances/" + instanceResource[MAIN_DICOM_TAGS]["SOPInstanceUID"].asString() + "/bulk");
         }
       }
 
@@ -1278,7 +1284,7 @@ void InstanceWorkerThread(InstanceWorkerData* data)
   }
 }
 
-void RetrieveSeriesMetadataInternal(OrthancPluginRestOutput* output,
+void RetrieveSeriesMetadataInternal(std::set<std::string>& instancesIds,
                                     OrthancPlugins::DicomWebFormatter::HttpWriter& writer,
                                     MainDicomTagsCache& cache,
                                     const OrthancPlugins::MetadataMode& mode,
@@ -1289,7 +1295,6 @@ void RetrieveSeriesMetadataInternal(OrthancPluginRestOutput* output,
                                     const std::string& wadoBase)
 {
   ChildrenMainDicomMaps instancesDicomMaps;
-  std::list<std::string> instancesIds;
   std::string seriesDicomUid;
 
   unsigned int workersCount =  OrthancPlugins::Configuration::GetMetadataWorkerThreadsCount();
@@ -1299,6 +1304,10 @@ void RetrieveSeriesMetadataInternal(OrthancPluginRestOutput* output,
   if (oneLargeQuery)
   {
     GetChildrenMainDicomTags(instancesDicomMaps, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId);
+    for (ChildrenMainDicomMaps::const_iterator it = instancesDicomMaps.begin(); it != instancesDicomMaps.end(); ++it)
+    {
+      instancesIds.insert(it->first);
+    }
   }
   else
   {
@@ -1334,7 +1343,7 @@ void RetrieveSeriesMetadataInternal(OrthancPluginRestOutput* output,
     }
     else
     {
-      for (std::list<std::string>::const_iterator i = instancesIds.begin(); i != instancesIds.end(); ++i)
+      for (std::set<std::string>::const_iterator i = instancesIds.begin(); i != instancesIds.end(); ++i)
       {
         instancesQueue.Enqueue(new InstanceToLoad(*i, "", writerMutex, writer, isXml, OrthancPluginDicomWebBinaryMode_BulkDataUri, studyInstanceUid, seriesInstanceUid));
       }
@@ -1358,18 +1367,190 @@ void RetrieveSeriesMetadataInternal(OrthancPluginRestOutput* output,
   }
   else
   { // old single threaded code
-    std::list<std::string> instances;
+    std::set<std::string> instances;
     std::string seriesDicomUid;  // not used
 
     GetChildrenIdentifiers(instances, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId);
 
-    for (std::list<std::string>::const_iterator i = instances.begin(); i != instances.end(); ++i)
+    for (std::set<std::string>::const_iterator i = instances.begin(); i != instances.end(); ++i)
     {
       WriteInstanceMetadata(writer, mode, cache, *i, studyInstanceUid, seriesInstanceUid, wadoBase);
     }
   }
 }
 
+void CacheSeriesMetadataInternal(std::string& serializedSeriesMetadata,
+                                 OrthancPlugins::DicomWebFormatter::HttpWriter& writer,
+                                 MainDicomTagsCache& cache,
+                                 const std::string& studyInstanceUid, 
+                                 const std::string& seriesInstanceUid, 
+                                 const std::string& seriesOrthancId)
+{
+  Orthanc::GzipCompressor compressor;
+  std::string compressedSeriesMetadata;
+  std::set<std::string> instancesIds;
+
+  // compute the series metadata with a placeholder WADO base url because, the base url might change (e.g if there are 2 Orthanc connected to the same DB)
+  RetrieveSeriesMetadataInternal(instancesIds, writer, cache, OrthancPlugins::MetadataMode_Full, false /* isXml */, seriesOrthancId, studyInstanceUid, seriesInstanceUid, WADO_BASE_PLACEHOLDER);
+  writer.CloseAndGetJsonOutput(serializedSeriesMetadata);
+
+  // save in attachments for future use
+  Orthanc::IBufferCompressor::Compress(compressedSeriesMetadata, compressor, serializedSeriesMetadata);
+  std::string instancesMd5;
+  Orthanc::Toolbox::ComputeMD5(instancesMd5, instancesIds);
+
+  std::string cacheContent = "2;" + instancesMd5 + ";" + compressedSeriesMetadata; 
+
+  Json::Value putResult;
+  std::string attachmentUrl = "/series/" + seriesOrthancId + "/attachments/" + SERIES_METADATA_ATTACHMENT_ID;
+  if (!OrthancPlugins::RestApiPut(putResult, attachmentUrl, cacheContent, false))
+  {
+    LOG(WARNING) << "DicomWEB: failed to write series metadata attachment";
+  }
+
+}
+
+void CacheSeriesMetadata(const std::string& seriesOrthancId)
+{
+  if (!OrthancPlugins::Configuration::IsMetadataCacheEnabled())
+  {
+    return;
+  }
+
+  LOG(INFO) << "DicomWEB: pre-computing the WADO-RS series metadata for series " << seriesOrthancId;
+
+  std::string studyInstanceUid, seriesInstanceUid;
+  
+  Json::Value result;
+  if (OrthancPlugins::RestApiGet(result, "/series/" + seriesOrthancId, false))
+  {
+    seriesInstanceUid = result[MAIN_DICOM_TAGS]["SeriesInstanceUID"].asString();
+    if (OrthancPlugins::RestApiGet(result, "/studies/" + result["ParentStudy"].asString(), false))
+    {
+      studyInstanceUid = result[MAIN_DICOM_TAGS]["StudyInstanceUID"].asString();
+
+      MainDicomTagsCache cache;
+      OrthancPlugins::DicomWebFormatter::HttpWriter writer(NULL /* output */, false /* isXml */);  // we cache only the JSON format -> no need for an HttpOutput
+
+      std::string serializedSeriesMetadataNotUsed;
+      CacheSeriesMetadataInternal(serializedSeriesMetadataNotUsed, writer, cache, studyInstanceUid, seriesInstanceUid, seriesOrthancId);
+    }
+  }
+}
+
+void UpdateSeriesMetadataCache(OrthancPluginRestOutput* output,
+                               const char* /*url*/,
+                               const OrthancPluginHttpRequest* request)
+{
+  if (request->method != OrthancPluginHttpMethod_Post)
+  {
+    OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), output, "POST");
+    return;
+  }
+
+  if (request->groupsCount != 1)
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest);
+  }
+
+  if (!OrthancPlugins::Configuration::IsMetadataCacheEnabled())
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest, "The metadata cache is disabled in the Orthanc configuration.");
+  }
+
+  std::string studyId(request->groups[0]);
+
+  LOG(INFO) << "DicomWEB: updating the series metadata cache for study " << studyId;
+
+  Json::Value study;
+
+  if (OrthancPlugins::RestApiGet(study, "/studies/" + studyId, false) && study.type() == Json::objectValue)
+  {
+    for (Json::ArrayIndex i = 0; i < study["Series"].size(); ++i)
+    {
+      CacheSeriesMetadata(study["Series"][i].asString());
+    }
+  }
+
+  std::string answer = "{}"; 
+  OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, answer.c_str(), answer.size(), "application/json");
+}
+
+
+
+void RetrieveSeriesMetadataInternalWithCache(OrthancPlugins::DicomWebFormatter::HttpWriter& writer,
+                                             MainDicomTagsCache& cache,
+                                             const OrthancPlugins::MetadataMode& mode,
+                                             bool isXml,
+                                             const std::string& seriesOrthancId,
+                                             const std::string& studyInstanceUid,
+                                             const std::string& seriesInstanceUid,
+                                             const std::string& wadoBase)
+{
+  if (OrthancPlugins::Configuration::IsMetadataCacheEnabled() &&
+      mode == OrthancPlugins::MetadataMode_Full && 
+      !isXml)
+  {
+    // check if we already have computed the series metadata and saved them in an attachment
+    std::string serializedSeriesMetadata;
+    std::string cacheContent;
+    bool hasBeenReadFromCache = false;
+    Orthanc::GzipCompressor compressor;
+
+    std::string attachmentUrl = "/series/" + seriesOrthancId + "/attachments/" + SERIES_METADATA_ATTACHMENT_ID;
+
+    if (OrthancPlugins::RestApiGetString(cacheContent, attachmentUrl + "/data", false))
+    {
+      if (boost::starts_with(cacheContent, "2;"))  // version 2, cacheContent is "2;sorted-instances-list-md5;compressedSeriesMetadata"
+      {
+        // check that the instances count have not changed since we have saved the data in cache 
+        // StableSeries event will always overwrite it but this is usefull if retrieving the metadata while
+        // the instances are being received
+        // Note: we can not use Toolbox::SplitString because the compressed metadata contain a lot of ";"
+        const char* secondSemiColon = strchr(&cacheContent[2], ';');
+        std::string instancesMd5InCache(&cacheContent[2], secondSemiColon - &cacheContent[2]);
+        std::string compressedSeriesMetadata(secondSemiColon + 1, cacheContent.size() - (secondSemiColon+1 - cacheContent.c_str()));
+        
+        Json::Value seriesInfo;
+
+        if (!OrthancPlugins::RestApiGet(seriesInfo, "/series/" + seriesOrthancId, false))
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
+        }
+        std::set<std::string> currentInstancesIds;
+        Orthanc::SerializationToolbox::ReadSetOfStrings(currentInstancesIds, seriesInfo, "Instances");
+        std::string currentInstancesMd5;
+        Orthanc::Toolbox::ComputeMD5(currentInstancesMd5, currentInstancesIds);
+
+        if (currentInstancesMd5 == instancesMd5InCache)
+        {
+          Orthanc::IBufferCompressor::Uncompress(serializedSeriesMetadata, compressor, compressedSeriesMetadata);
+
+          hasBeenReadFromCache = true;
+        }
+      }
+    }
+
+    if (!hasBeenReadFromCache)  // regenerate and overwrite current cache
+    {
+      MainDicomTagsCache tmpCache;
+      OrthancPlugins::DicomWebFormatter::HttpWriter tmpWriter(NULL /* output */, false /* isXml */);  // we cache only the JSON format -> no need for an HttpOutput
+
+      CacheSeriesMetadataInternal(serializedSeriesMetadata, tmpWriter, tmpCache, studyInstanceUid, seriesInstanceUid, seriesOrthancId);
+    }
+
+    boost::replace_all(serializedSeriesMetadata, WADO_BASE_PLACEHOLDER, wadoBase);
+
+    writer.AddDicomWebSeriesSerializedJson(serializedSeriesMetadata.c_str(), serializedSeriesMetadata.size());
+  }
+  else
+  {
+    std::set<std::string> instancesIdsNotUsed;
+    RetrieveSeriesMetadataInternal(instancesIdsNotUsed, writer, cache, mode, isXml, seriesOrthancId, studyInstanceUid, seriesInstanceUid, wadoBase);
+  }
+
+}
+
 
 void RetrieveSeriesMetadata(OrthancPluginRestOutput* output,
                             const char* /*url*/,
@@ -1389,7 +1570,7 @@ void RetrieveSeriesMetadata(OrthancPluginRestOutput* output,
   if (LocateSeries(output, seriesOrthancId, studyInstanceUid, seriesInstanceUid, request))
   {
     std::string wadoBase = OrthancPlugins::Configuration::GetBasePublicUrl(request);
-    RetrieveSeriesMetadataInternal(output, writer, cache, mode, isXml, seriesOrthancId, studyInstanceUid, seriesInstanceUid, wadoBase);
+    RetrieveSeriesMetadataInternalWithCache(writer, cache, mode, isXml, seriesOrthancId, studyInstanceUid, seriesInstanceUid, wadoBase);
   }
 
   writer.Send();
@@ -1415,17 +1596,17 @@ void RetrieveStudyMetadata(OrthancPluginRestOutput* output,
 
     std::string wadoBase = OrthancPlugins::Configuration::GetBasePublicUrl(request);
     
-    std::list<std::string> series;
+    std::set<std::string> series;
     std::string studyDicomUid;
     GetChildrenIdentifiers(series, studyDicomUid, Orthanc::ResourceType_Study, studyOrthancId);
 
-    for (std::list<std::string>::const_iterator s = series.begin(); s != series.end(); ++s)
+    for (std::set<std::string>::const_iterator s = series.begin(); s != series.end(); ++s)
     {
-      std::list<std::string> instances;
+      std::set<std::string> instances;
       std::string seriesDicomUid;
       GetChildrenIdentifiers(instances, seriesDicomUid, Orthanc::ResourceType_Series, *s);
 
-      RetrieveSeriesMetadataInternal(output, writer, cache, mode, isXml, *s, studyDicomUid, seriesDicomUid, wadoBase);
+      RetrieveSeriesMetadataInternalWithCache(writer, cache, mode, isXml, *s, studyDicomUid, seriesDicomUid, wadoBase);
     }
 
     writer.Send();


=====================================
Plugin/WadoRs.h
=====================================
@@ -63,6 +63,12 @@ void RetrieveSeriesMetadata(OrthancPluginRestOutput* output,
                             const char* url,
                             const OrthancPluginHttpRequest* request);
 
+void UpdateSeriesMetadataCache(OrthancPluginRestOutput* output,
+                               const char* url,
+                               const OrthancPluginHttpRequest* request);
+
+void CacheSeriesMetadata(const std::string& seriesOrthancId);
+
 void RetrieveInstanceMetadata(OrthancPluginRestOutput* output,
                               const char* url,
                               const OrthancPluginHttpRequest* request);


=====================================
README
=====================================
@@ -39,6 +39,14 @@ Build and usage instructions are available in the Orthanc Book:
 http://book.orthanc-server.com/plugins/dicomweb.html
 
 
+Contributing
+------------
+
+Instructions for contributing to the Orthanc project are included in
+the Orthanc Book:
+https://book.orthanc-server.com/developers/repositories.html
+
+
 Licensing: AGPL
 ---------------
 


=====================================
Resources/CMake/JavaScriptLibraries.cmake
=====================================
@@ -18,7 +18,7 @@
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 
 
-set(BASE_URL "https://orthanc.uclouvain.be/third-party-downloads/dicom-web")
+set(BASE_URL "http://orthanc.osimis.io/ThirdPartyDownloads/dicom-web")
 
 DownloadPackage(
   "da0189f7c33bf9f652ea65401e0a3dc9"


=====================================
Resources/Orthanc/CMake/DownloadOrthancFramework.cmake
=====================================
@@ -153,11 +153,9 @@ if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.2")
         set(ORTHANC_FRAMEWORK_MD5 "ede3de356493a8868545f8cb4b8bc8b5")
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.11.3")
-        set(ORTHANC_FRAMEWORK_MD5 "f941c0f5771db7616e7b7961026a60e2")
+        set(ORTHANC_FRAMEWORK_MD5 "5c1b11009d782f248739919db6bf7f7a")
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.0")
         set(ORTHANC_FRAMEWORK_MD5 "d32a0cde03b6eb603d8dd2b33d38bf1b")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.1")
-        set(ORTHANC_FRAMEWORK_MD5 "8a435140efc8ff4a01d8242f092f21de")
 
       # Below this point are development snapshots that were used to
       # release some plugin, before an official release of the Orthanc
@@ -181,6 +179,9 @@ if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "b2e08d83e21d")
         # WSI 1.1 (framework pre-1.10.0), to remove "-std=c++11"
         set(ORTHANC_FRAMEWORK_MD5 "2eaa073cbb4b44ffba199ad93393b2b1")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "daf4807631c5")
+        # DICOMweb 1.15 (framework pre-1.12.2)
+        set(ORTHANC_FRAMEWORK_MD5 "c644aff2817306b3207c98c92e43f35f")
       endif()
     endif()
   endif()


=====================================
debian/changelog
=====================================
@@ -1,3 +1,15 @@
+orthanc-dicomweb (1.15+dfsg-1) UNRELEASED; urgency=medium
+
+  * New upstream version
+  * debhelper-compat 13 (routine-update)
+  * Remove trailing whitespace in debian/copyright (routine-update)
+  * Add salsa-ci file (routine-update)
+  * Rules-Requires-Root: no (routine-update)
+  * watch file standard 4 (routine-update)
+  * Build-Depends: pybuild-plugin-pyproject
+
+ -- Andreas Tille <tille at debian.org>  Sun, 29 Oct 2023 20:52:03 +0100
+
 orthanc-dicomweb (1.14+dfsg-2) unstable; urgency=medium
 
   * Remove autogenerated file from source directory. Closes: #1047523


=====================================
debian/compat deleted
=====================================
@@ -1 +0,0 @@
-10


=====================================
debian/control
=====================================
@@ -5,14 +5,15 @@ Uploaders: Sebastien Jodogne <s.jodogne at gmail.com>,
 Section: science
 Priority: optional
 Build-Depends: cmake,
-               debhelper (>= 10),
-	       fonts-font-awesome,
-	       libjs-bootstrap4,
+               debhelper-compat (= 13),
+               pybuild-plugin-pyproject,
+               fonts-font-awesome,
+               libjs-bootstrap4,
                libgtest-dev,
                libjs-jquery,
                liborthancframework-dev,
-	       node-axios,
-               orthanc-dev (>= 1.9.2),
+               node-axios,
+               orthanc-dev,
                unzip,
                uuid-dev,
                yui-compressor
@@ -20,6 +21,7 @@ Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/med-team/orthanc-dicomweb
 Vcs-Git: https://salsa.debian.org/med-team/orthanc-dicomweb.git
 Homepage: https://www.orthanc-server.com/static.php?page=dicomweb
+Rules-Requires-Root: no
 
 Package: orthanc-dicomweb
 Architecture: any


=====================================
debian/copyright
=====================================
@@ -46,7 +46,7 @@ License: AGPL-3.0+
  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 package; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


=====================================
debian/salsa-ci.yml
=====================================
@@ -0,0 +1,4 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml


=====================================
debian/watch
=====================================
@@ -1,3 +1,3 @@
-version=3
+version=4
 opts="repacksuffix=+dfsg,dversionmangle=s/\+dfsg//g,downloadurlmangle=s/\/browse\.php\?path=//g,repack,compression=xz" \
 https://www.orthanc-server.com/browse.php?path=/plugin-dicom-web downloads/get\.php\?path=/plugin-dicom-web/OrthancDicomWeb-(\d\S*)\.tar\.gz



View it on GitLab: https://salsa.debian.org/med-team/orthanc-dicomweb/-/compare/f86f515ee57c1abb1bf5ecd421c9eb4222d7f1fd...c12b17a5c8a9e0487780923b586348b3c6a6b368

-- 
View it on GitLab: https://salsa.debian.org/med-team/orthanc-dicomweb/-/compare/f86f515ee57c1abb1bf5ecd421c9eb4222d7f1fd...c12b17a5c8a9e0487780923b586348b3c6a6b368
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20231029/53156901/attachment-0001.htm>


More information about the debian-med-commit mailing list