# HG changeset patch # User am@osimis.io # Date 1542746688 -3600 # Node ID 4fe42ae3653a060939230cc488311f8f15ca699a # Parent 8bf717c4e4975c3682565b91a54b831437b1f209 introduced a basic cache at OrthancApiClient level so it can be used with the RadiographyScene diff -r 8bf717c4e497 -r 4fe42ae3653a Framework/Toolbox/OrthancApiClient.cpp --- a/Framework/Toolbox/OrthancApiClient.cpp Mon Nov 19 12:45:37 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.cpp Tue Nov 20 21:44:48 2018 +0100 @@ -154,7 +154,7 @@ { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - } + } void HandleFailure(const IWebService::HttpRequestErrorMessage& message) const { @@ -163,7 +163,53 @@ failureHandler_->Apply(IWebService::HttpRequestErrorMessage (message.GetUri(), userPayload_.get())); } - } + } + }; + + + class OrthancApiClient::CachedHttpRequestSuccessMessage + { + protected: + const std::string& uri_; + void* answer_; + size_t answerSize_; + IWebService::HttpHeaders answerHeaders_; + + public: + CachedHttpRequestSuccessMessage(const IWebService::HttpRequestSuccessMessage& message) : + uri_(message.GetUri()), + answerSize_(message.GetAnswerSize()), + answerHeaders_(message.GetAnswerHttpHeaders()) + { + answer_ = malloc(answerSize_); + memcpy(answer_, message.GetAnswer(), answerSize_); + } + + ~CachedHttpRequestSuccessMessage() + { + free(answer_); + } + + const std::string& GetUri() const + { + return uri_; + } + + const void* GetAnswer() const + { + return answer_; + } + + size_t GetAnswerSize() const + { + return answerSize_; + } + + const IWebService::HttpHeaders& GetAnswerHttpHeaders() const + { + return answerHeaders_; + } + }; @@ -173,33 +219,44 @@ IObservable(broker), IObserver(broker), web_(web), - baseUrl_(baseUrl) + baseUrl_(baseUrl), + cacheEnabled_(true) { } void OrthancApiClient::GetJsonAsync( - const std::string& uri, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + const std::string& uri, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) { - web_.GetAsync(baseUrl_ + uri, - IWebService::HttpHeaders(), - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + IWebService::HttpHeaders emptyHeaders; + if (cacheEnabled_) + { + HandleFromCache(baseUrl_ + uri, + emptyHeaders, + new WebServicePayload(successCallback, failureCallback, payload)); + } + else + { + web_.GetAsync(baseUrl_ + uri, + emptyHeaders, + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); + } } void OrthancApiClient::GetBinaryAsync( - const std::string& uri, - const std::string& contentType, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + const std::string& uri, + const std::string& contentType, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) { IWebService::HttpHeaders headers; headers["Accept"] = contentType; @@ -207,30 +264,69 @@ } - void OrthancApiClient::GetBinaryAsync( - const std::string& uri, - const IWebService::HttpHeaders& headers, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + void OrthancApiClient::HandleFromCache(const std::string& uri, + const IWebService::HttpHeaders& headers, + Orthanc::IDynamicObject* payload // takes ownership + ) { - printf("GET [%s] [%s]\n", baseUrl_.c_str(), uri.c_str()); - - web_.GetAsync(baseUrl_ + uri, headers, - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + if (cache_.find(uri) == cache_.end()) + { + web_.GetAsync(uri, headers, + payload, // ownership is transfered + new Callable + (*this, &OrthancApiClient::CacheAndNotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); + } + else + { + std::auto_ptr payloadRaii(payload); // make sure payload is deleted whatever happens + + const OrthancApiClient::CachedHttpRequestSuccessMessage& cachedMessage = *(cache_[uri]); + IWebService::HttpRequestSuccessMessage successMessage(cachedMessage.GetUri(), + cachedMessage.GetAnswer(), + cachedMessage.GetAnswerSize(), + cachedMessage.GetAnswerHttpHeaders(), + payloadRaii.get()); + NotifyHttpSuccess(successMessage); + } + + } + + + void OrthancApiClient::GetBinaryAsync( + const std::string& uri, + const IWebService::HttpHeaders& headers, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) + { + // printf("GET [%s] [%s]\n", baseUrl_.c_str(), uri.c_str()); + + if (cacheEnabled_) + { + HandleFromCache(baseUrl_ + uri, + headers, + new WebServicePayload(successCallback, failureCallback, payload)); + } + else + { + web_.GetAsync(baseUrl_ + uri, headers, + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); + } } void OrthancApiClient::PostBinaryAsyncExpectJson( - const std::string& uri, - const std::string& body, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + const std::string& uri, + const std::string& body, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) { web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, new WebServicePayload(successCallback, failureCallback, payload), @@ -243,11 +339,11 @@ void OrthancApiClient::PostJsonAsyncExpectJson( - const std::string& uri, - const Json::Value& data, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + const std::string& uri, + const Json::Value& data, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) { std::string body; MessagingToolbox::JsonToString(body, data); @@ -256,10 +352,10 @@ void OrthancApiClient::DeleteAsync( - const std::string& uri, - MessageHandler* successCallback, - MessageHandler* failureCallback, - Orthanc::IDynamicObject* payload) + const std::string& uri, + MessageHandler* successCallback, + MessageHandler* failureCallback, + Orthanc::IDynamicObject* payload) { web_.DeleteAsync(baseUrl_ + uri, IWebService::HttpHeaders(), new WebServicePayload(successCallback, failureCallback, payload), @@ -282,7 +378,12 @@ } } - + void OrthancApiClient::CacheAndNotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message) + { + cache_[message.GetUri()] = boost::shared_ptr(new CachedHttpRequestSuccessMessage(message)); + NotifyHttpSuccess(message); + } + void OrthancApiClient::NotifyHttpError(const IWebService::HttpRequestErrorMessage& message) { if (message.HasPayload()) @@ -293,5 +394,5 @@ { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - } + } } diff -r 8bf717c4e497 -r 4fe42ae3653a Framework/Toolbox/OrthancApiClient.h --- a/Framework/Toolbox/OrthancApiClient.h Mon Nov 19 12:45:37 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.h Tue Nov 20 21:44:48 2018 +0100 @@ -31,12 +31,12 @@ namespace OrthancStone { class OrthancApiClient : - public IObservable, - public IObserver + public IObservable, + public IObserver { public: class JsonResponseReadyMessage : - public BaseMessage + public BaseMessage { private: const std::string& uri_; @@ -73,7 +73,7 @@ class BinaryResponseReadyMessage : - public BaseMessage + public BaseMessage { private: const std::string& uri_; @@ -118,7 +118,7 @@ class EmptyResponseReadyMessage : - public BaseMessage + public BaseMessage { private: const std::string& uri_; @@ -149,11 +149,14 @@ private: class WebServicePayload; - + class CachedHttpRequestSuccessMessage; + protected: IWebService& web_; std::string baseUrl_; + std::map> cache_; // TODO: this is currently an infinite cache ! + bool cacheEnabled_; public: OrthancApiClient(MessageBroker& broker, IWebService& web, @@ -163,6 +166,11 @@ { } + void EnableCache(bool enable) + { + cacheEnabled_ = enable; + } + // schedule a GET request expecting a JSON response. void GetJsonAsync(const std::string& uri, MessageHandler* successCallback, @@ -206,5 +214,12 @@ void NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message); void NotifyHttpError(const IWebService::HttpRequestErrorMessage& message); + + void CacheAndNotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message); + + private: + void HandleFromCache(const std::string& uri, + const IWebService::HttpHeaders& headers, + Orthanc::IDynamicObject* payload /* takes ownership */); }; }