# HG changeset patch # User am@osimis.io # Date 1539636182 -7200 # Node ID a902a07769d4872dbe5aef92d932f7e90876a96c # Parent 56b2e47d3c0c7dd6ddeb912e188635d1a4c57e22 wip: preload slice diff -r 56b2e47d3c0c -r a902a07769d4 Framework/SmartLoader.cpp --- a/Framework/SmartLoader.cpp Fri Oct 12 14:53:38 2018 +0200 +++ b/Framework/SmartLoader.cpp Mon Oct 15 22:43:02 2018 +0200 @@ -31,8 +31,9 @@ { enum CachedSliceStatus { - CachedSliceStatus_Loading, - CachedSliceStatus_Loaded + CachedSliceStatus_ScheduledToLoad, + CachedSliceStatus_GeometryLoaded, + CachedSliceStatus_ImageLoaded }; class SmartLoader::CachedSlice : public LayerSourceBase @@ -103,10 +104,11 @@ // in both cases, we must be carefull about objects lifecycle !!! std::auto_ptr layerSource; + std::string sliceKeyId = instanceId + ":" + std::to_string(frame); - if (cachedSlices_.find(instanceId) != cachedSlices_.end() && cachedSlices_[instanceId]->status_ == CachedSliceStatus_Loaded) + if (cachedSlices_.find(sliceKeyId) != cachedSlices_.end()) // && cachedSlices_[sliceKeyId]->status_ == CachedSliceStatus_Loaded) { - layerSource.reset(cachedSlices_[instanceId]->Clone()); + layerSource.reset(cachedSlices_[sliceKeyId]->Clone()); } else { @@ -140,36 +142,56 @@ } + void SmartLoader::PreloadSlice(const std::string instanceId, unsigned int frame) + { + // TODO: check if it is already in the cache - void SmartLoader::LoadStudyList() - { - // orthancApiClient_.ScheduleGetJsonRequest("/studies"); + // create the slice in the cache with "empty" data + boost::shared_ptr cachedSlice(new CachedSlice(IObserver::broker_)); + cachedSlice->slice_.reset(new Slice(instanceId, frame)); + cachedSlice->status_ = CachedSliceStatus_ScheduledToLoad; + std::string sliceKeyId = instanceId + ":" + std::to_string(frame); + + cachedSlices_[sliceKeyId] = boost::shared_ptr(cachedSlice); + + std::auto_ptr layerSource(new OrthancFrameLayerSource(IObserver::broker_, orthancApiClient_)); + + dynamic_cast(layerSource.get())->SetImageQuality(imageQuality_); + layerSource->RegisterObserverCallback(new Callable(*this, &SmartLoader::OnLayerGeometryReady)); + layerSource->RegisterObserverCallback(new Callable(*this, &SmartLoader::OnImageReady)); + layerSource->RegisterObserverCallback(new Callable(*this, &SmartLoader::OnLayerReady)); + dynamic_cast(layerSource.get())->LoadFrame(instanceId, frame); + + // keep a ref to the LayerSource until the slice is fully loaded and saved to cache + preloadingInstances_[sliceKeyId] = boost::shared_ptr(layerSource.release()); } - void PreloadStudy(const std::string studyId) - { - /* TODO */ - } - void PreloadSeries(const std::string seriesId) - { - /* TODO */ - } +// void PreloadStudy(const std::string studyId) +// { +// /* TODO */ +// } + +// void PreloadSeries(const std::string seriesId) +// { +// /* TODO */ +// } void SmartLoader::OnLayerGeometryReady(const ILayerSource::GeometryReadyMessage& message) { OrthancFrameLayerSource& source = dynamic_cast(message.origin_); - // save the slice + + // save/replace the slice in cache const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() - std::string instanceId = slice.GetOrthancInstanceId(); + std::string sliceKeyId = slice.GetOrthancInstanceId() + ":" + std::to_string(slice.GetFrame()); - CachedSlice* cachedSlice = new CachedSlice(IObserver::broker_); + boost::shared_ptr cachedSlice(new CachedSlice(IObserver::broker_)); cachedSlice->slice_.reset(slice.Clone()); cachedSlice->effectiveQuality_ = source.GetImageQuality(); - cachedSlice->status_ = CachedSliceStatus_Loading; + cachedSlice->status_ = CachedSliceStatus_GeometryLoaded; - cachedSlices_[instanceId] = boost::shared_ptr(cachedSlice); + cachedSlices_[sliceKeyId] = boost::shared_ptr(cachedSlice); // re-emit original Layer message to observers EmitMessage(message); @@ -179,17 +201,17 @@ { OrthancFrameLayerSource& source = dynamic_cast(message.origin_); - // save the slice + // save/replace the slice in cache const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? - std::string instanceId = slice.GetOrthancInstanceId(); + std::string sliceKeyId = slice.GetOrthancInstanceId() + ":" + std::to_string(slice.GetFrame()); boost::shared_ptr cachedSlice(new CachedSlice(IObserver::broker_)); cachedSlice->image_ = message.image_; cachedSlice->effectiveQuality_ = message.imageQuality_; cachedSlice->slice_.reset(message.slice_.Clone()); - cachedSlice->status_ = CachedSliceStatus_Loaded; + cachedSlice->status_ = CachedSliceStatus_ImageLoaded; - cachedSlices_[instanceId] = cachedSlice; + cachedSlices_[sliceKeyId] = cachedSlice; // re-emit original Layer message to observers EmitMessage(message); @@ -197,6 +219,16 @@ void SmartLoader::OnLayerReady(const ILayerSource::LayerReadyMessage& message) { + OrthancFrameLayerSource& source = dynamic_cast(message.origin_); + const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? + std::string sliceKeyId = slice.GetOrthancInstanceId() + ":" + std::to_string(slice.GetFrame()); + + // remove the slice from the preloading slices now that it has been fully loaded and it is referenced in the cache + if (preloadingInstances_.find(sliceKeyId) != preloadingInstances_.end()) + { + preloadingInstances_.erase(sliceKeyId); + } + // re-emit original Layer message to observers EmitMessage(message); } diff -r 56b2e47d3c0c -r a902a07769d4 Framework/SmartLoader.h --- a/Framework/SmartLoader.h Fri Oct 12 14:53:38 2018 +0200 +++ b/Framework/SmartLoader.h Mon Oct 15 22:43:02 2018 +0200 @@ -38,17 +38,18 @@ typedef std::map> CachedSlices; CachedSlices cachedSlices_; + typedef std::map> PreloadingInstances; + PreloadingInstances preloadingInstances_; + SliceImageQuality imageQuality_; OrthancApiClient& orthancApiClient_; - int studyListRequest_; - public: SmartLoader(MessageBroker& broker, OrthancApiClient& orthancApiClient); // TODO: add maxPreloadStorageSizeInBytes - void PreloadStudy(const std::string studyId); - void PreloadSeries(const std::string seriesId); - void LoadStudyList(); +// void PreloadStudy(const std::string studyId); +// void PreloadSeries(const std::string seriesId); + void PreloadSlice(const std::string instanceId, unsigned int frame); void SetImageQuality(SliceImageQuality imageQuality) { imageQuality_ = imageQuality; } diff -r 56b2e47d3c0c -r a902a07769d4 Framework/Toolbox/Slice.h --- a/Framework/Toolbox/Slice.h Fri Oct 12 14:53:38 2018 +0200 +++ b/Framework/Toolbox/Slice.h Mon Oct 15 22:43:02 2018 +0200 @@ -61,6 +61,16 @@ public: Slice() : type_(Type_Invalid) + { + } + + + // this constructor is used to reference, i.e, a slice that is being loaded + Slice(const std::string& orthancInstanceId, + unsigned int frame) : + type_(Type_Invalid), + orthancInstanceId_(orthancInstanceId), + frame_(frame) { } diff -r 56b2e47d3c0c -r a902a07769d4 Platforms/Wasm/WasmPlatformApplicationAdapter.cpp --- a/Platforms/Wasm/WasmPlatformApplicationAdapter.cpp Fri Oct 12 14:53:38 2018 +0200 +++ b/Platforms/Wasm/WasmPlatformApplicationAdapter.cpp Mon Oct 15 22:43:02 2018 +0200 @@ -38,9 +38,14 @@ void WasmPlatformApplicationAdapter::NotifyStatusUpdateFromCppToWeb(const std::string& statusUpdateMessage) { - printf("NotifyStatusUpdateFromCppToWeb (TODO)\n"); - UpdateStoneApplicationStatusFromCpp(statusUpdateMessage.c_str()); - printf("NotifyStatusUpdateFromCppToWeb (DONE)\n"); + try + { + UpdateStoneApplicationStatusFromCpp(statusUpdateMessage.c_str()); + } + catch (...) + { + printf("Error while handling message to web\n"); + } } } \ No newline at end of file