Mercurial > hg > orthanc
changeset 4900:ea5f1c6ed07e
fix cache of storage area
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sun, 20 Feb 2022 16:29:33 +0100 |
parents | 181e67f9d129 |
children | 0bb73ef7cf07 |
files | OrthancFramework/Sources/FileStorage/StorageAccessor.cpp OrthancFramework/Sources/FileStorage/StorageAccessor.h OrthancFramework/Sources/FileStorage/StorageCache.cpp OrthancFramework/Sources/FileStorage/StorageCache.h OrthancServer/Sources/ServerContext.cpp |
diffstat | 5 files changed, 97 insertions(+), 160 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/FileStorage/StorageAccessor.cpp Sun Feb 20 12:00:14 2022 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageAccessor.cpp Sun Feb 20 16:29:33 2022 +0100 @@ -133,7 +133,7 @@ } } - cache_.Add(uuid, type, data, size); + cache_.Add(uuid, type, compressed); return FileInfo(uuid, type, size, md5, CompressionType_ZlibWithSize, compressed.size(), compressedMD5); } @@ -156,23 +156,17 @@ void StorageAccessor::Read(std::string& content, const FileInfo& info) { - if (cache_.Fetch(content, info.GetUuid(), info.GetContentType())) - { - LOG(INFO) << "Read attachment \"" << info.GetUuid() << "\" " - << "content type from cache"; - return; - } - switch (info.GetCompressionType()) { case CompressionType_None: { - MetricsTimer timer(*this, METRICS_READ); + if (!cache_.Fetch(content, info.GetUuid(), info.GetContentType())) + { + MetricsTimer timer(*this, METRICS_READ); + std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); + buffer->MoveToString(content); + } - std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); - buffer->MoveToString(content); - - cache_.Add(info.GetUuid(), info.GetContentType(), content); break; } @@ -180,16 +174,23 @@ { ZlibCompressor zlib; - std::unique_ptr<IMemoryBuffer> compressed; - + std::string cached; + if (cache_.Fetch(cached, info.GetUuid(), info.GetContentType())) + { + zlib.Uncompress(content, cached.empty() ? NULL : cached.c_str(), cached.size()); + } + else { - MetricsTimer timer(*this, METRICS_READ); - compressed.reset(area_.Read(info.GetUuid(), info.GetContentType())); + std::unique_ptr<IMemoryBuffer> compressed; + + { + MetricsTimer timer(*this, METRICS_READ); + compressed.reset(area_.Read(info.GetUuid(), info.GetContentType())); + } + + zlib.Uncompress(content, compressed->GetData(), compressed->GetSize()); } - zlib.Uncompress(content, compressed->GetData(), compressed->GetSize()); - - cache_.Add(info.GetUuid(), info.GetContentType(), content); break; } @@ -206,63 +207,56 @@ void StorageAccessor::ReadRaw(std::string& content, const FileInfo& info) { - MetricsTimer timer(*this, METRICS_READ); - - std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); - buffer->MoveToString(content); + if (!cache_.Fetch(content, info.GetUuid(), info.GetContentType())) + { + MetricsTimer timer(*this, METRICS_READ); + std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); + buffer->MoveToString(content); + } } void StorageAccessor::Remove(const std::string& fileUuid, FileContentType type) { - MetricsTimer timer(*this, METRICS_REMOVE); - area_.Remove(fileUuid, type); + cache_.Invalidate(fileUuid, type); - cache_.Invalidate(fileUuid, type); - - // in ReadStartRange, we might have cached only the start of the file -> try to remove it - if (type == FileContentType_Dicom) { - cache_.Invalidate(fileUuid, FileContentType_DicomUntilPixelData); + MetricsTimer timer(*this, METRICS_REMOVE); + area_.Remove(fileUuid, type); } } + void StorageAccessor::Remove(const FileInfo &info) { Remove(info.GetUuid(), info.GetContentType()); } - IMemoryBuffer* StorageAccessor::ReadStartRange(const std::string& fileUuid, - FileContentType contentType, - uint64_t end /* exclusive */, - FileContentType startFileContentType) + + void StorageAccessor::ReadStartRange(std::string& target, + const std::string& fileUuid, + FileContentType contentType, + uint64_t end /* exclusive */) { - std::string content; - if (cache_.Fetch(content, fileUuid, contentType)) + if (cache_.Fetch(target, fileUuid, contentType)) { - LOG(INFO) << "Read attachment \"" << fileUuid << "\" " - << "(range from " << 0 << " to " << end << ") from cache"; - - return StringMemoryBuffer::CreateFromCopy(content, 0, end); + if (target.size() < end) + { + throw OrthancException(ErrorCode_CorruptedFile); + } + else + { + target.resize(end); + } } - - if (cache_.Fetch(content, fileUuid, startFileContentType)) + else { - LOG(INFO) << "Read attachment \"" << fileUuid << "\" " - << "(range from " << 0 << " to " << end << ") from cache"; - - assert(content.size() == end); - return StringMemoryBuffer::CreateFromCopy(content); + MetricsTimer timer(*this, METRICS_READ); + std::unique_ptr<IMemoryBuffer> buffer(area_.ReadRange(fileUuid, contentType, 0, end)); + assert(buffer->GetSize() == end); + buffer->MoveToString(target); } - - std::unique_ptr<IMemoryBuffer> buffer(area_.ReadRange(fileUuid, contentType, 0, end)); - - // we've read only the first part of the file -> add an entry in the cache - // note the uuid is still the uuid of the full file but the type is the type of the start of the file ! - assert(buffer->GetSize() == end); - cache_.Add(fileUuid, startFileContentType, buffer->GetData(), buffer->GetSize()); - return buffer.release(); } @@ -271,18 +265,10 @@ const FileInfo& info, const std::string& mime) { - if (cache_.Fetch(sender.GetBuffer(), info.GetUuid(), info.GetContentType())) - { - LOG(INFO) << "Read attachment \"" << info.GetUuid() << "\" " - << "content type from cache"; - } - else { MetricsTimer timer(*this, METRICS_READ); std::unique_ptr<IMemoryBuffer> buffer(area_.Read(info.GetUuid(), info.GetContentType())); buffer->MoveToString(sender.GetBuffer()); - - cache_.Add(info.GetUuid(), info.GetContentType(), sender.GetBuffer()); } sender.SetContentType(mime);
--- a/OrthancFramework/Sources/FileStorage/StorageAccessor.h Sun Feb 20 12:00:14 2022 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageAccessor.h Sun Feb 20 16:29:33 2022 +0100 @@ -102,10 +102,10 @@ void ReadRaw(std::string& content, const FileInfo& info); - IMemoryBuffer* ReadStartRange(const std::string& fileUuid, - FileContentType fullFileContentType, - uint64_t end /* exclusive */, - FileContentType startFileContentType); + void ReadStartRange(std::string& target, + const std::string& fileUuid, + FileContentType fullFileContentType, + uint64_t end /* exclusive */); void Remove(const std::string& fileUuid, FileContentType type);
--- a/OrthancFramework/Sources/FileStorage/StorageCache.cpp Sun Feb 20 12:00:14 2022 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageCache.cpp Sun Feb 20 16:29:33 2022 +0100 @@ -25,114 +25,68 @@ #include "StorageCache.h" #include "../Compatibility.h" +#include "../Logging.h" #include "../OrthancException.h" +#include <boost/lexical_cast.hpp> namespace Orthanc { - bool IsAcceptedContentType(FileContentType contentType) - { - return contentType == FileContentType_Dicom || - contentType == FileContentType_DicomUntilPixelData || - contentType == FileContentType_DicomAsJson; - } - - const char* ToString(FileContentType contentType) + static std::string GetCacheKey(const std::string& uuid, + FileContentType contentType) { - switch (contentType) - { - case FileContentType_Dicom: - return "dicom"; - case FileContentType_DicomUntilPixelData: - return "dicom-header"; - case FileContentType_DicomAsJson: - return "dicom-json"; - default: - throw OrthancException(ErrorCode_InternalError, - "ContentType not supported in StorageCache"); - } + return uuid + ":" + boost::lexical_cast<std::string>(contentType); } - - bool GetCacheKey(std::string& key, const std::string& uuid, FileContentType contentType) - { - if (contentType == FileContentType_Unknown || contentType >= FileContentType_StartUser) - { - return false; - } - - key = uuid + ":" + std::string(ToString(contentType)); - - return true; - } + void StorageCache::SetMaximumSize(size_t size) { cache_.SetMaximumSize(size); } + void StorageCache::Add(const std::string& uuid, FileContentType contentType, const std::string& value) { - if (!IsAcceptedContentType(contentType)) - { - return; - } - - std::string key; - - if (GetCacheKey(key, uuid, contentType)) - { - cache_.Add(key, value); - } + const std::string key = GetCacheKey(uuid, contentType); + cache_.Add(key, value); } + void StorageCache::Add(const std::string& uuid, FileContentType contentType, const void* buffer, size_t size) { - if (!IsAcceptedContentType(contentType)) - { - return; - } - - std::string key; + const std::string key = GetCacheKey(uuid, contentType); + cache_.Add(key, buffer, size); + } + - if (GetCacheKey(key, uuid, contentType)) - { - cache_.Add(key, buffer, size); - } - } - - void StorageCache::Invalidate(const std::string& uuid, FileContentType contentType) + void StorageCache::Invalidate(const std::string& uuid, + FileContentType contentType) { - std::string key; - - if (GetCacheKey(key, uuid, contentType)) - { - cache_.Invalidate(key); - } + const std::string key = GetCacheKey(uuid, contentType); + cache_.Invalidate(key); } + bool StorageCache::Fetch(std::string& value, const std::string& uuid, FileContentType contentType) { - if (!IsAcceptedContentType(contentType)) + const std::string key = GetCacheKey(uuid, contentType); + if (cache_.Fetch(value, key)) + { + LOG(INFO) << "Read attachment \"" << uuid << "\" with content type " + << boost::lexical_cast<std::string>(contentType) << " from cache"; + return true; + } + else { return false; } - - std::string key; - if (GetCacheKey(key, uuid, contentType)) - { - return cache_.Fetch(value, key); - } - - return false; } - - -} \ No newline at end of file +}
--- a/OrthancFramework/Sources/FileStorage/StorageCache.h Sun Feb 20 12:00:14 2022 +0100 +++ b/OrthancFramework/Sources/FileStorage/StorageCache.h Sun Feb 20 16:29:33 2022 +0100 @@ -37,7 +37,9 @@ **/ class ORTHANC_PUBLIC StorageCache : public boost::noncopyable { + private: MemoryStringCache cache_; + public: void SetMaximumSize(size_t size); @@ -50,7 +52,8 @@ const void* buffer, size_t size); - void Invalidate(const std::string& uuid, FileContentType contentType); + void Invalidate(const std::string& uuid, + FileContentType contentType); bool Fetch(std::string& value, const std::string& uuid,
--- a/OrthancServer/Sources/ServerContext.cpp Sun Feb 20 12:00:14 2022 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Sun Feb 20 16:29:33 2022 +0100 @@ -953,23 +953,17 @@ * "true". **/ - std::unique_ptr<IMemoryBuffer> dicom; + std::string dicom; + { StorageAccessor accessor(area_, storageCache_, GetMetricsRegistry()); - dicom.reset(accessor.ReadStartRange(attachment.GetUuid(), FileContentType_Dicom, pixelDataOffset, FileContentType_DicomUntilPixelData)); - } - - if (dicom.get() == NULL) - { - throw OrthancException(ErrorCode_InternalError); + accessor.ReadStartRange(dicom, attachment.GetUuid(), FileContentType_Dicom, pixelDataOffset); } - else - { - assert(dicom->GetSize() == pixelDataOffset); - ParsedDicomFile parsed(dicom->GetData(), dicom->GetSize()); - OrthancConfiguration::DefaultDicomDatasetToJson(result, parsed, ignoreTagLength); - InjectEmptyPixelData(result); - } + + assert(dicom.size() == pixelDataOffset); + ParsedDicomFile parsed(dicom); + OrthancConfiguration::DefaultDicomDatasetToJson(result, parsed, ignoreTagLength); + InjectEmptyPixelData(result); } else if (ignoreTagLength.empty() && index_.LookupAttachment(attachment, revision, instancePublicId, FileContentType_DicomAsJson)) @@ -1093,9 +1087,9 @@ StorageAccessor accessor(area_, storageCache_, GetMetricsRegistry()); - std::unique_ptr<IMemoryBuffer> buffer( - accessor.ReadStartRange(attachment.GetUuid(), attachment.GetContentType(), pixelDataOffset, FileContentType_DicomUntilPixelData)); - buffer->MoveToString(dicom); + accessor.ReadStartRange(dicom, attachment.GetUuid(), attachment.GetContentType(), pixelDataOffset); + assert(dicom.size() == pixelDataOffset); + return true; // Success } catch (boost::bad_lexical_cast&)