Mercurial > hg > orthanc
changeset 5427:111e21b4f8bc
fix transcoded instance caching
author | Alain Mazy <am@osimis.io> |
---|---|
date | Fri, 17 Nov 2023 08:22:17 +0100 |
parents | c65e036d649b |
children | 8174e45f48d8 |
files | OrthancFramework/Sources/Cache/MemoryStringCache.cpp OrthancFramework/Sources/Cache/MemoryStringCache.h OrthancFramework/Sources/FileStorage/StorageCache.cpp OrthancFramework/Sources/FileStorage/StorageCache.h OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h |
diffstat | 7 files changed, 68 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/Cache/MemoryStringCache.cpp Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancFramework/Sources/Cache/MemoryStringCache.cpp Fri Nov 17 08:22:17 2023 +0100 @@ -206,24 +206,6 @@ } - void MemoryStringCache::InvalidateByPrefix(const std::string& keyPrefix) - { - std::vector<std::string> allKeys; - - { - boost::mutex::scoped_lock cacheLock(cacheMutex_); - content_.GetAllKeys(allKeys); - } - - for (std::vector<std::string>::const_iterator it = allKeys.begin(); it != allKeys.end(); ++it) - { - if (it->find(keyPrefix) == 0) - { - Invalidate(*it); - } - } - } - bool MemoryStringCache::Fetch(std::string& value, const std::string& key) {
--- a/OrthancFramework/Sources/Cache/MemoryStringCache.h Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancFramework/Sources/Cache/MemoryStringCache.h Fri Nov 17 08:22:17 2023 +0100 @@ -50,9 +50,14 @@ public: class Accessor : public boost::noncopyable { + protected: MemoryStringCache& cache_; + + private: bool shouldAdd_; // when this accessor is the one who should load and add the data std::string keyToAdd_; + + public: Accessor(MemoryStringCache& cache); ~Accessor(); @@ -86,8 +91,6 @@ void Invalidate(const std::string& key); - void InvalidateByPrefix(const std::string& keyPrefix); - private: void Add(const std::string& key, const std::string& value);
--- a/OrthancFramework/Sources/FileStorage/StorageCache.cpp Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageCache.cpp Fri Nov 17 08:22:17 2023 +0100 @@ -50,7 +50,7 @@ static std::string GetCacheKeyTranscodedInstance(const std::string& uuid, DicomTransferSyntax transferSyntax) { - return uuid + ":" + GetTransferSyntaxUid(transferSyntax) + ":1"; + return uuid + ":ts:" + GetTransferSyntaxUid(transferSyntax); } @@ -63,13 +63,31 @@ void StorageCache::Invalidate(const std::string& uuid, FileContentType contentType) { + std::set<DicomTransferSyntax> transferSyntaxes; + + { + boost::mutex::scoped_lock lock(subKeysMutex_); + transferSyntaxes = subKeysTransferSyntax_; + } + // invalidate full file, start range file and possible transcoded instances - cache_.InvalidateByPrefix(uuid); + const std::string keyFullFile = GetCacheKeyFullFile(uuid, contentType); + cache_.Invalidate(keyFullFile); + + const std::string keyPartialFile = GetCacheKeyStartRange(uuid, contentType); + cache_.Invalidate(keyPartialFile); + + for (std::set<DicomTransferSyntax>::const_iterator it = transferSyntaxes.begin(); it != transferSyntaxes.end(); ++it) + { + const std::string keyTransferSyntax = GetCacheKeyTranscodedInstance(uuid, *it); + cache_.Invalidate(keyTransferSyntax); + } } StorageCache::Accessor::Accessor(StorageCache& cache) - : MemoryStringCache::Accessor(cache.cache_) + : MemoryStringCache::Accessor(cache.cache_), + storageCache_(cache) { } @@ -138,6 +156,11 @@ const void* buffer, size_t size) { + { + boost::mutex::scoped_lock lock(storageCache_.subKeysMutex_); + storageCache_.subKeysTransferSyntax_.insert(targetSyntax); + } + const std::string key = GetCacheKeyTranscodedInstance(uuid, targetSyntax); MemoryStringCache::Accessor::Add(key, reinterpret_cast<const char*>(buffer), size); }
--- a/OrthancFramework/Sources/FileStorage/StorageCache.h Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageCache.h Fri Nov 17 08:22:17 2023 +0100 @@ -46,6 +46,7 @@ // the same file. class Accessor : public MemoryStringCache::Accessor { + StorageCache& storageCache_; public: Accessor(StorageCache& cache); @@ -82,8 +83,10 @@ }; private: - MemoryStringCache cache_; - + MemoryStringCache cache_; + std::set<DicomTransferSyntax> subKeysTransferSyntax_; + boost::mutex subKeysMutex_; + public: void SetMaximumSize(size_t size);
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Nov 17 08:22:17 2023 +0100 @@ -425,10 +425,11 @@ if (call.HasArgument(TRANSCODE)) { std::string source; + std::string attachmentId; std::string transcoded; - context.ReadDicom(source, publicId); - - if (context.TranscodeWithCache(transcoded, source, publicId, GetTransferSyntax(call.GetArgument(TRANSCODE, "")))) + context.ReadDicom(source, attachmentId, publicId); + + if (context.TranscodeWithCache(transcoded, source, publicId, attachmentId, GetTransferSyntax(call.GetArgument(TRANSCODE, "")))) { call.GetOutput().AnswerBuffer(transcoded, MimeType_Dicom); } @@ -2328,8 +2329,9 @@ { // Return the raw data (possibly compressed), as stored on the filesystem std::string content; + std::string attachmentId; int64_t revision; - context.ReadAttachment(content, revision, publicId, type, false, true /* skipCache when you absolutely need the compressed data */); + context.ReadAttachment(content, revision, attachmentId, publicId, type, false, true /* skipCache when you absolutely need the compressed data */); int64_t userRevision; std::string userMD5; @@ -2511,7 +2513,9 @@ // First check whether the compressed data is correctly stored in the disk std::string data; - context.ReadAttachment(data, revision, publicId, StringToContentType(name), false, true /* skipCache when you absolutely need the compressed data */); + std::string attachmentId; + + context.ReadAttachment(data, revision, attachmentId, publicId, StringToContentType(name), false, true /* skipCache when you absolutely need the compressed data */); std::string actualMD5; Toolbox::ComputeMD5(actualMD5, data); @@ -2526,7 +2530,7 @@ } else { - context.ReadAttachment(data, revision, publicId, StringToContentType(name), true, true /* skipCache when you absolutely need the compressed data */); + context.ReadAttachment(data, revision, attachmentId, publicId, StringToContentType(name), true, true /* skipCache when you absolutely need the compressed data */); Toolbox::ComputeMD5(actualMD5, data); ok = (actualMD5 == info.GetUncompressedMD5()); }
--- a/OrthancServer/Sources/ServerContext.cpp Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Fri Nov 17 08:22:17 2023 +0100 @@ -1165,10 +1165,19 @@ void ServerContext::ReadDicom(std::string& dicom, + std::string& attachmentId, const std::string& instancePublicId) { int64_t revision; - ReadAttachment(dicom, revision, instancePublicId, FileContentType_Dicom, true /* uncompress */); + ReadAttachment(dicom, revision, attachmentId, instancePublicId, FileContentType_Dicom, true /* uncompress */); + } + + + void ServerContext::ReadDicom(std::string& dicom, + const std::string& instancePublicId) + { + std::string attachmentId; + ReadDicom(dicom, attachmentId, instancePublicId); } void ServerContext::ReadDicomForHeader(std::string& dicom, @@ -1236,6 +1245,7 @@ void ServerContext::ReadAttachment(std::string& result, int64_t& revision, + std::string& attachmentId, const std::string& instancePublicId, FileContentType content, bool uncompressIfNeeded, @@ -1250,7 +1260,8 @@ } assert(attachment.GetContentType() == content); - + attachmentId = attachment.GetUuid(); + { std::unique_ptr<StorageAccessor> accessor; @@ -1951,11 +1962,12 @@ bool ServerContext::TranscodeWithCache(std::string& target, const std::string& source, const std::string& sourceInstanceId, + const std::string& attachmentId, DicomTransferSyntax targetSyntax) { StorageCache::Accessor cacheAccessor(storageCache_); - if (!cacheAccessor.FetchTranscodedInstance(target, sourceInstanceId, targetSyntax)) + if (!cacheAccessor.FetchTranscodedInstance(target, attachmentId, targetSyntax)) { IDicomTranscoder::DicomImage sourceDicom; sourceDicom.SetExternalBuffer(source); @@ -1966,7 +1978,7 @@ if (Transcode(targetDicom, sourceDicom, syntaxes, true)) { - cacheAccessor.AddTranscodedInstance(sourceInstanceId, targetSyntax, reinterpret_cast<const char*>(targetDicom.GetBufferData()), targetDicom.GetBufferSize()); + cacheAccessor.AddTranscodedInstance(attachmentId, targetSyntax, reinterpret_cast<const char*>(targetDicom.GetBufferData()), targetDicom.GetBufferSize()); target = std::string(reinterpret_cast<const char*>(targetDicom.GetBufferData()), targetDicom.GetBufferSize()); return true; }
--- a/OrthancServer/Sources/ServerContext.h Thu Nov 16 16:09:04 2023 +0100 +++ b/OrthancServer/Sources/ServerContext.h Fri Nov 17 08:22:17 2023 +0100 @@ -379,6 +379,10 @@ void ReadDicom(std::string& dicom, const std::string& instancePublicId); + void ReadDicom(std::string& dicom, + std::string& attachmentId, + const std::string& instancePublicId); + void ReadDicomForHeader(std::string& dicom, const std::string& instancePublicId); @@ -388,6 +392,7 @@ // This method is for low-level operations on "/instances/.../attachments/..." void ReadAttachment(std::string& result, int64_t& revision, + std::string& attachmentId, const std::string& instancePublicId, FileContentType content, bool uncompressIfNeeded, @@ -559,6 +564,7 @@ virtual bool TranscodeWithCache(std::string& target, const std::string& source, const std::string& sourceInstanceId, + const std::string& attachmentId, // for the storage cache DicomTransferSyntax targetSyntax); bool IsTranscodeDicomProtocol() const