Mercurial > hg > orthanc
changeset 6914:689d73b259f1 streaming
optimization: store attachments into the cache after their creation
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Tue, 02 Jun 2026 18:31:10 +0200 |
| parents | a66b5e2dfb6e |
| children | ff30e25e081e |
| files | OrthancFramework/Sources/Cache/SharedObjectCache.cpp OrthancFramework/Sources/Cache/SharedObjectCache.h OrthancFramework/Sources/DataSource/DataSourceReader.cpp OrthancFramework/Sources/DataSource/DataSourceReader.h OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp OrthancFramework/Sources/DataSource/StorageAreaDataSource.h OrthancServer/Sources/ServerContext.cpp |
| diffstat | 7 files changed, 112 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/Cache/SharedObjectCache.cpp Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/Cache/SharedObjectCache.cpp Tue Jun 02 18:31:10 2026 +0200 @@ -191,12 +191,10 @@ } - void SharedObjectCache::GetStatistics(size_t& capacity, - size_t& currentCount, + void SharedObjectCache::GetStatistics(size_t& currentCount, size_t& currentSize) { Mutex::ScopedLock lock(mutex_); - capacity = capacity_; currentCount = lru_.GetSize(); currentSize = currentSize_; }
--- a/OrthancFramework/Sources/Cache/SharedObjectCache.h Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/Cache/SharedObjectCache.h Tue Jun 02 18:31:10 2026 +0200 @@ -43,7 +43,7 @@ Mutex mutex_; LeastRecentlyUsedIndex<std::string> lru_; Content content_; - size_t capacity_; + const size_t capacity_; size_t currentSize_; void MakeRoom(size_t newObjectSize); @@ -70,8 +70,12 @@ void Invalidate(const std::string& id); - void GetStatistics(size_t& capacity, - size_t& currentCount, + size_t GetCapacity() const + { + return capacity_; // This is a constant value, it can be read without the mutex + } + + void GetStatistics(size_t& currentCount, size_t& currentSize); }; }
--- a/OrthancFramework/Sources/DataSource/DataSourceReader.cpp Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/DataSourceReader.cpp Tue Jun 02 18:31:10 2026 +0200 @@ -75,8 +75,8 @@ { if (metrics_) { - size_t capacity, count, size; - cache.GetStatistics(capacity, count, size); + size_t count, size; + cache.GetStatistics(count, size); metrics_->SetFloatValue(cacheSizeMegabytesName_, static_cast<float>(size) / static_cast<float>(MEGABYTE)); metrics_->SetIntegerValue(cacheCountName_, count); @@ -322,4 +322,38 @@ budgetCopy->GetStatistics(tasksMaximumMemory, tasksCurrentMemory, tasksReservations); } } + + + size_t DataSourceReader::GetCacheCapacity() const + { + boost::shared_ptr<SharedObjectCache> lock(cache_); + + if (lock) + { + return lock->GetCapacity(); + } + else + { + return 0; + } + } + + + void DataSourceReader::StoreIntoCache(const std::string& key, + IDynamicObject* value /* takes ownership */) + { + boost::shared_ptr<IDynamicObject> protection(value); + + if (value == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + + if (cache_) + { + size_t size = source_->GetValueSize(*value); + cache_->Store(key, protection, size); + metricsConfiguration_.SetCacheStatistics(*cache_); + } + } }
--- a/OrthancFramework/Sources/DataSource/DataSourceReader.h Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/DataSourceReader.h Tue Jun 02 18:31:10 2026 +0200 @@ -77,6 +77,7 @@ boost::shared_ptr<IExecutorService> executor_; std::unique_ptr<IDataSource> source_; + size_t cacheSize_; boost::shared_ptr<SharedObjectCache> cache_; boost::shared_ptr<Internals::DataSourceMemoryBudget> budget_; MetricsConfiguration metricsConfiguration_; @@ -120,5 +121,10 @@ void GetStatistics(uint64_t& tasksMaximumMemory, uint64_t& tasksCurrentMemory, unsigned int& tasksReservations); + + size_t GetCacheCapacity() const; + + void StoreIntoCache(const std::string& key, + IDynamicObject* value /* takes ownership */); }; }
--- a/OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/StorageAreaDataSource.cpp Tue Jun 02 18:31:10 2026 +0200 @@ -26,6 +26,7 @@ #include "StorageAreaDataSource.h" #include "../Cache/SharedObjectCache.h" +#include "../Logging.h" #include "../MetricsRegistry.h" #include "../OrthancException.h" #include "../StringMemoryBuffer.h" @@ -56,6 +57,13 @@ boost::lexical_cast<std::string>(end)); } + + static std::string ComputeCacheKeyForWholeAttachment(const FileInfo& attachment) + { + return ComputeCacheKey(attachment.GetUuid(), attachment.GetContentType(), 0, attachment.GetCompressedSize()); + } + + class StorageAreaDataSource::Value : public IDynamicObject { private: @@ -527,7 +535,7 @@ // Using "SetWholeKey()" allows to extract a range if the whole attachment is already in the reader cache assert(attachment.GetCompressionType() == CompressionType_None); - id->SetWholeKey(ComputeCacheKey(attachment.GetUuid(), attachment.GetContentType(), 0, attachment.GetCompressedSize())); + id->SetWholeKey(ComputeCacheKeyForWholeAttachment(attachment)); return id.release(); } @@ -571,7 +579,7 @@ // Using "SetWholeKey()" allows to extract a range if the whole compressed attachment is already in the reader cache assert(!uncompress || attachment.GetCompressionType() == CompressionType_None); - id->SetWholeKey(ComputeCacheKey(attachment.GetUuid(), attachment.GetContentType(), 0, attachment.GetCompressedSize())); + id->SetWholeKey(ComputeCacheKeyForWholeAttachment(attachment)); return Execute(reader, id.release()); } @@ -591,4 +599,27 @@ return new Range(reader.ReadSingle(request)); } } + + + void StorageAreaDataSource::StoreIntoCache(DataSourceReader& reader, + const FileInfo& attachment, + const void* data, + size_t size) + { + if (size != attachment.GetCompressedSize()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + const size_t capacity = reader.GetCacheCapacity(); + + if (capacity != 0 && + size <= capacity) + { + const std::string key = ComputeCacheKeyForWholeAttachment(attachment); + std::unique_ptr<Value> value(new Value(StringMemoryBuffer::CreateFromBuffer(data, size), false /* no MD5 */)); + + reader.StoreIntoCache(key, value.release()); + } + } }
--- a/OrthancFramework/Sources/DataSource/StorageAreaDataSource.h Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancFramework/Sources/DataSource/StorageAreaDataSource.h Tue Jun 02 18:31:10 2026 +0200 @@ -120,5 +120,10 @@ const FileInfo& attachment, const StorageRange& range, bool uncompress); + + static void StoreIntoCache(DataSourceReader& reader, + const FileInfo& attachment, + const void* data, + size_t size); }; }
--- a/OrthancServer/Sources/ServerContext.cpp Tue Jun 02 18:06:22 2026 +0200 +++ b/OrthancServer/Sources/ServerContext.cpp Tue Jun 02 18:31:10 2026 +0200 @@ -168,6 +168,16 @@ info = FileInfo(uuid, type, size, md5); info.SetCustomData(customData); + + try + { + StorageAreaDataSource::StoreIntoCache(*storageAreaReader_, info, data, size); + } + catch (OrthancException& e) + { + LOG(WARNING) << "Unable to store a new attachment into the cache: " << e.What(); + } + return; } @@ -178,6 +188,8 @@ std::string compressed; zlib.Compress(compressed, data, size); + const void* compressedData = compressed.empty() ? NULL : compressed.c_str(); + std::string compressedMD5; if (storeMD5_) @@ -187,22 +199,23 @@ { MetricsRegistry::Timer timer(*metricsRegistry_, METRICS_STORAGE_AREA_CREATE_DURATION); - - if (compressed.size() > 0) - { - area_.Create(customData, uuid, &compressed[0], compressed.size(), type, compression, instance); - } - else - { - area_.Create(customData, uuid, NULL, 0, type, compression, instance); - } + area_.Create(customData, uuid, compressedData, compressed.size(), type, compression, instance); } metricsRegistry_->IncrementIntegerValue(METRICS_STORAGE_AREA_WRITTEN_BYTES, static_cast<int64_t>(compressed.size())); - info = FileInfo(uuid, type, size, md5, - CompressionType_ZlibWithSize, compressed.size(), compressedMD5); + info = FileInfo(uuid, type, size, md5, CompressionType_ZlibWithSize, compressed.size(), compressedMD5); info.SetCustomData(customData); + + try + { + StorageAreaDataSource::StoreIntoCache(*storageAreaReader_, info, compressedData, compressed.size()); + } + catch (OrthancException& e) + { + LOG(WARNING) << "Unable to store a new attachment into the cache: " << e.What(); + } + return; }
