Mercurial > hg > orthanc-wsi
changeset 554:3dc4b2e04615 annotations
added a cache for features
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Tue, 01 Sep 2026 14:28:04 +0200 |
| parents | 55b48abb2994 |
| children | 304d7b366580 |
| files | ViewerPlugin/Annotations/AnnotationsRestApi.cpp ViewerPlugin/ViewerConfiguration.cpp ViewerPlugin/ViewerConfiguration.h |
| diffstat | 3 files changed, 131 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/ViewerPlugin/Annotations/AnnotationsRestApi.cpp Tue Sep 01 11:42:14 2026 +0200 +++ b/ViewerPlugin/Annotations/AnnotationsRestApi.cpp Tue Sep 01 14:28:04 2026 +0200 @@ -1137,7 +1137,7 @@ class CachedAnnotations : public boost::noncopyable { private: - boost::shared_ptr<Orthanc::IDynamicObject> content_; + boost::shared_ptr<Orthanc::IDynamicObject> cached_; static Orthanc::SharedObjectCache& GetCache() { @@ -1161,26 +1161,18 @@ { const std::string key = id.GetKey(); - content_ = GetCache().GetCachedValue(key); + cached_ = GetCache().GetCachedValue(key); - if (content_.get() == NULL) + if (cached_.get() == NULL) { - content_.reset(new Annotations(id)); - GetCache().Store(key, content_, 1); + cached_.reset(new Annotations(id)); + GetCache().Store(key, cached_, 1); } } - - Annotations& GetContent() + Annotations& GetContent() const { - return dynamic_cast<Annotations&>(*content_); - } - - - static void Invalidate(const AnnotationsId& id) - { - const std::string key = id.GetKey(); - GetCache().Invalidate(key); + return dynamic_cast<Annotations&>(*cached_); } }; @@ -1234,22 +1226,12 @@ return *user_; } - bool IsRootUser() const - { - return GetUser().GetAnnotatingId().GetType() == UserId::Type_Root; - } - const AnnotationsId& GetAnnotationsId() const { assert(annotationsId_.get() != NULL); return *annotationsId_; } - std::string GetFeaturesKey() const - { - return ::OrthancWSI::GetFeaturesKey(GetAnnotationsId(), GetUser().GetAnnotatingId()); - } - std::string GetBodyString(const char* field) const { return Orthanc::SerializationToolbox::ReadString(body_, field); @@ -1395,23 +1377,19 @@ } - void LoadUserFeatures(OrthancPluginRestOutput* output, - const char* url, - const OrthancPluginHttpRequest* request) + class UserFeatures : public Orthanc::IDynamicObject { - if (request->method != OrthancPluginHttpMethod_Post) + private: + Orthanc::ReaderWriterLock mutex_; + std::string key_; + Json::Value content_; + + void Load() { - OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), output, "POST"); - } - else - { - AnnotationsCommandContext context(request); - - Json::Value answer; - answer[KEY_FEATURES] = Json::arrayValue; + content_ = Json::arrayValue; std::string compressed; - if (LookupKeyValueStore(compressed, context.GetFeaturesKey())) + if (LookupKeyValueStore(compressed, key_)) { std::string uncompressed; Orthanc::GzipCompressor compressor; @@ -1430,7 +1408,7 @@ if (version == ORTHANC_WSI_ANNOTATIONS_VERSION) { - answer[KEY_FEATURES] = unserialized[KEY_FEATURES]; + content_ = unserialized[KEY_FEATURES]; } else { @@ -1444,6 +1422,108 @@ } } } + } + + void Save() const + { + Json::Value unserialized; + unserialized[KEY_VERSION] = static_cast<unsigned int>(ORTHANC_WSI_ANNOTATIONS_VERSION); + unserialized[KEY_FEATURES] = content_; + + std::string serialized; + Orthanc::Toolbox::WriteFastJson(serialized, unserialized); + + std::string compressed; + Orthanc::GzipCompressor compressor; + Orthanc::IBufferCompressor::Compress(compressed, compressor, serialized); + + SetKeyValueStore(key_, compressed); + } + + public: + UserFeatures(const std::string& key) : + key_(key) + { + Load(); + } + + void GetContent(Json::Value& target) + { + Orthanc::ReaderWriterLock::ReadLock lock(mutex_); + target = content_; + } + + void SetContent(const Json::Value& content) + { + Orthanc::ReaderWriterLock::WriteLock lock(mutex_); + content_ = content; + Save(); + } + }; + + + class CachedUserFeatures : public boost::noncopyable + { + private: + boost::shared_ptr<Orthanc::IDynamicObject> cached_; + + static Orthanc::SharedObjectCache& GetCache() + { + static boost::mutex mutex; + static std::unique_ptr<Orthanc::SharedObjectCache> cache; + + { + boost::mutex::scoped_lock lock(mutex); + + if (cache.get() == NULL) + { + cache.reset(new Orthanc::SharedObjectCache(ViewerConfiguration::GetInstance().GetFeaturesCacheSize())); + } + + return *cache; + } + } + + public: + CachedUserFeatures(const AnnotationsId& annotations, + const UserId& user) + { + const std::string key = GetFeaturesKey(annotations, user); + + cached_ = GetCache().GetCachedValue(key); + + if (cached_.get() == NULL) + { + cached_.reset(new UserFeatures(key)); + GetCache().Store(key, cached_, 1); + } + } + + UserFeatures& GetFeatures() const + { + return dynamic_cast<UserFeatures&>(*cached_); + } + }; + + + void LoadUserFeatures(OrthancPluginRestOutput* output, + const char* url, + const OrthancPluginHttpRequest* request) + { + if (request->method != OrthancPluginHttpMethod_Post) + { + OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), output, "POST"); + } + else + { + AnnotationsCommandContext context(request); + + Json::Value answer; + + { + CachedUserFeatures cached(context.GetAnnotationsId(), context.GetUser().GetAnnotatingId()); + cached.GetFeatures().GetContent(answer[KEY_FEATURES]); + } ViewerToolbox::AnswerJson(output, answer); } @@ -1462,18 +1542,10 @@ { AnnotationsCommandContext context(request); - Json::Value content; - content[KEY_VERSION] = static_cast<unsigned int>(ORTHANC_WSI_ANNOTATIONS_VERSION); - content[KEY_FEATURES] = context.GetBodyField(KEY_FEATURES); - - std::string serialized; - Orthanc::Toolbox::WriteFastJson(serialized, content); - - std::string compressed; - Orthanc::GzipCompressor compressor; - Orthanc::IBufferCompressor::Compress(compressed, compressor, serialized); - - SetKeyValueStore(context.GetFeaturesKey(), compressed); + { + CachedUserFeatures cached(context.GetAnnotationsId(), context.GetUser().GetAnnotatingId()); + cached.GetFeatures().SetContent(context.GetBodyField(KEY_FEATURES)); + } ViewerToolbox::AnswerEmpty(output); }
--- a/ViewerPlugin/ViewerConfiguration.cpp Tue Sep 01 11:42:14 2026 +0200 +++ b/ViewerPlugin/ViewerConfiguration.cpp Tue Sep 01 14:28:04 2026 +0200 @@ -202,6 +202,12 @@ } + unsigned int ViewerConfiguration::GetFeaturesCacheSize() const + { + return 100; // TODO - Configuration option? + } + + bool ViewerConfiguration::IsAnnotationsSharingEnabled() const { return wsiConfiguration_.GetBooleanValue("EnableAnnotationsSharing", false);
--- a/ViewerPlugin/ViewerConfiguration.h Tue Sep 01 11:42:14 2026 +0200 +++ b/ViewerPlugin/ViewerConfiguration.h Tue Sep 01 14:28:04 2026 +0200 @@ -73,6 +73,8 @@ unsigned int GetAnnotationsCacheSize() const; + unsigned int GetFeaturesCacheSize() const; + bool IsAnnotationsSharingEnabled() const; }; }
