Mercurial > hg > orthanc-dicomweb
changeset 596:e1f219c7c302
added cache version number
author | Alain Mazy <am@osimis.io> |
---|---|
date | Wed, 23 Aug 2023 12:03:25 +0200 |
parents | f9d029c56ba4 |
children | f1f11bcabd08 |
files | Plugin/WadoRs.cpp |
diffstat | 1 files changed, 46 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/Plugin/WadoRs.cpp Tue Aug 22 10:31:34 2023 +0200 +++ b/Plugin/WadoRs.cpp Wed Aug 23 12:03:25 2023 +0200 @@ -35,6 +35,8 @@ #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$"; @@ -1281,7 +1283,8 @@ } } -void RetrieveSeriesMetadataInternal(OrthancPlugins::DicomWebFormatter::HttpWriter& writer, +void RetrieveSeriesMetadataInternal(size_t& instancesCount, + OrthancPlugins::DicomWebFormatter::HttpWriter& writer, MainDicomTagsCache& cache, const OrthancPlugins::MetadataMode& mode, bool isXml, @@ -1301,10 +1304,12 @@ if (oneLargeQuery) { GetChildrenMainDicomTags(instancesDicomMaps, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId); + instancesCount = instancesDicomMaps.size(); } else { GetChildrenIdentifiers(instancesIds, seriesDicomUid, Orthanc::ResourceType_Series, seriesOrthancId); + instancesCount = instancesIds.size(); } if (workersCount > 1 && mode == OrthancPlugins::MetadataMode_Full) @@ -1381,17 +1386,20 @@ { Orthanc::GzipCompressor compressor; std::string compressedSeriesMetadata; + size_t instancesCount; // 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(writer, cache, OrthancPlugins::MetadataMode_Full, false /* isXml */, seriesOrthancId, studyInstanceUid, seriesInstanceUid, WADO_BASE_PLACEHOLDER); + RetrieveSeriesMetadataInternal(instancesCount, 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 cacheContent = "1;" + boost::lexical_cast<std::string>(instancesCount) + ";" + compressedSeriesMetadata; + Json::Value putResult; std::string attachmentUrl = "/series/" + seriesOrthancId + "/attachments/" + SERIES_METADATA_ATTACHMENT_ID; - if (!OrthancPlugins::RestApiPut(putResult, attachmentUrl, compressedSeriesMetadata, false)) + if (!OrthancPlugins::RestApiPut(putResult, attachmentUrl, cacheContent, false)) { LOG(WARNING) << "DicomWEB: failed to write series metadata attachment"; } @@ -1469,30 +1477,57 @@ { // check if we already have computed the series metadata and saved them in an attachment std::string serializedSeriesMetadata; - std::string compressedSeriesMetadata; + std::string cacheContent; + bool hasBeenReadFromCache = false; Orthanc::GzipCompressor compressor; std::string attachmentUrl = "/series/" + seriesOrthancId + "/attachments/" + SERIES_METADATA_ATTACHMENT_ID; - if (!OrthancPlugins::RestApiGetString(compressedSeriesMetadata, attachmentUrl + "/data", false)) + if (OrthancPlugins::RestApiGetString(cacheContent, attachmentUrl + "/data", false)) + { + if (boost::starts_with(cacheContent, "1;")) // version 1, cacheContent is "1;instancesCount;compressedSeriesMetadata" + { + // check that the instances count has 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 lengthString(&cacheContent[2], secondSemiColon - &cacheContent[2]); + std::string compressedSeriesMetadata(secondSemiColon + 1, cacheContent.size() - (secondSemiColon+1 - cacheContent.c_str())); + size_t instancesCountInCache = boost::lexical_cast<size_t>(lengthString); + + Json::Value seriesInfo; + + if (!OrthancPlugins::RestApiGet(seriesInfo, "/series/" + seriesOrthancId, false)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); + } + + if (seriesInfo["Instances"].size() == instancesCountInCache) + { + 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); } - else - { - Orthanc::IBufferCompressor::Uncompress(serializedSeriesMetadata, compressor, compressedSeriesMetadata); - } - + boost::replace_all(serializedSeriesMetadata, WADO_BASE_PLACEHOLDER, wadoBase); writer.AddDicomWebSeriesSerializedJson(serializedSeriesMetadata.c_str(), serializedSeriesMetadata.size()); } else { - RetrieveSeriesMetadataInternal(writer, cache, mode, isXml, seriesOrthancId, studyInstanceUid, seriesInstanceUid, wadoBase); + size_t instancesCountNotUsed; + RetrieveSeriesMetadataInternal(instancesCountNotUsed, writer, cache, mode, isXml, seriesOrthancId, studyInstanceUid, seriesInstanceUid, wadoBase); writer.Send(); }