# HG changeset patch # User Sebastien Jodogne # Date 1654163128 -7200 # Node ID 3daecfa5791c3763d54da53a9aaeee28f61e3151 # Parent a601b8abc1cb731b4b79c4d876c0e50f95f8b95b rendering plugin: caching multiple rt-struct in memory diff -r a601b8abc1cb -r 3daecfa5791c RenderingPlugin/Sources/Plugin.cpp --- a/RenderingPlugin/Sources/Plugin.cpp Thu Jun 02 10:52:47 2022 +0200 +++ b/RenderingPlugin/Sources/Plugin.cpp Thu Jun 02 11:45:28 2022 +0200 @@ -27,11 +27,9 @@ #include "../../OrthancStone/Sources/Toolbox/DicomInstanceParameters.h" #include "../../OrthancStone/Sources/Toolbox/DicomStructureSet.h" -#include - +#include #include #include -#include #include #include #include @@ -49,9 +47,33 @@ class DicomStructureCache : public boost::noncopyable { private: - boost::mutex mutex_; - std::string instanceId_; - std::unique_ptr rtstruct_; + class Item : public Orthanc::ICacheable + { + private: + std::unique_ptr rtstruct_; + + public: + Item(OrthancStone::DicomStructureSet* rtstruct) : + rtstruct_(rtstruct) + { + if (rtstruct == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + } + + virtual size_t GetMemoryUsage() const + { + return 1; + } + + OrthancStone::DicomStructureSet& GetRtStruct() const + { + return *rtstruct_; + } + }; + + Orthanc::MemoryObjectCache cache_; DicomStructureCache() // Singleton design pattern { @@ -60,12 +82,12 @@ public: void Invalidate(const std::string& instanceId) { - boost::mutex::scoped_lock lock(mutex_); + cache_.Invalidate(instanceId); + } - if (instanceId_ == instanceId) - { - rtstruct_.reset(NULL); - } + void SetMaximumNumberOfItems(size_t items) + { + cache_.SetMaximumSize(items); } static DicomStructureCache& GetSingleton() @@ -77,34 +99,39 @@ class Accessor : public boost::noncopyable { private: - boost::mutex::scoped_lock lock_; - std::string instanceId_; - OrthancStone::DicomStructureSet* rtstruct_; + DicomStructureCache& that_; + std::string instanceId_; + Orthanc::MemoryObjectCache::Accessor lock_; + std::unique_ptr notCached_; public: Accessor(DicomStructureCache& that, const std::string& instanceId) : - lock_(that.mutex_), + that_(that), instanceId_(instanceId), - rtstruct_(NULL) + lock_(that.cache_, instanceId, true /* unique, as "GetRtStruct()" is mutable */) { - if (that.instanceId_ == instanceId && - that.rtstruct_.get() != NULL) + if (!lock_.IsValid()) { - rtstruct_ = that.rtstruct_.get(); + OrthancStone::OrthancPluginConnection connection; + OrthancStone::FullOrthancDataset dataset(connection, "/instances/" + instanceId + "/tags?ignore-length=3006-0050"); + notCached_.reset(new OrthancStone::DicomStructureSet(dataset)); } - else + } + + ~Accessor() + { + if (!lock_.IsValid()) { + assert(notCached_.get() != NULL); + try { - OrthancStone::OrthancPluginConnection connection; - OrthancStone::FullOrthancDataset dataset(connection, "/instances/" + instanceId + "/tags?ignore-length=3006-0050"); - that.rtstruct_.reset(new OrthancStone::DicomStructureSet(dataset)); - that.instanceId_ = instanceId; - rtstruct_ = that.rtstruct_.get(); + that_.cache_.Acquire(instanceId_, new Item(notCached_.release())); } - catch (Orthanc::OrthancException&) + catch (Orthanc::OrthancException& e) { + LOG(ERROR) << "Cannot insert RT-STRUCT into cache: " << e.What(); } } } @@ -114,20 +141,16 @@ return instanceId_; } - bool IsValid() const - { - return rtstruct_ != NULL; - } - OrthancStone::DicomStructureSet& GetRtStruct() const { - if (IsValid()) + if (lock_.IsValid()) { - return *rtstruct_; + return dynamic_cast(lock_.GetValue()).GetRtStruct(); } else { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + assert(notCached_.get() != NULL); + return *notCached_; } } }; @@ -298,6 +321,7 @@ targetWidth_ = 0; targetHeight_ = 0; hasInterpolation_ = false; + interpolation_ = OrthancStone::ImageInterpolation_Nearest; } @@ -635,11 +659,6 @@ { DicomStructureCache::Accessor accessor(DicomStructureCache::GetSingleton(), request->groups[0]); - if (!accessor.IsValid()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); - } - Json::Value answer; answer[STRUCTURES] = Json::arrayValue; @@ -671,7 +690,7 @@ s.ToString(t); answer[INSTANCES].append(t); - } + } std::string s = answer.toStyledString(); OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), output, s.c_str(), s.size(), "application/json"); @@ -773,11 +792,6 @@ { DicomStructureCache::Accessor accessor(DicomStructureCache::GetSingleton(), request->groups[0]); - if (!accessor.IsValid()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem); - } - size_t structureIndex; bool found = false; for (size_t i = 0; i < accessor.GetRtStruct().GetStructuresCount(); i++) @@ -889,6 +903,8 @@ try { + DicomStructureCache::GetSingleton().SetMaximumNumberOfItems(1024); // Cache up to 1024 RT-STRUCT instances + OrthancPlugins::RegisterRestCallback("/stone/instances/([^/]+)/frames/([0-9]+)/numpy", true); OrthancPlugins::RegisterRestCallback("/stone/rt-struct", true); OrthancPlugins::RegisterRestCallback("/stone/rt-struct/([^/]+)/info", true);