Mercurial > hg > orthanc-stone
changeset 1136:42581a6182c8 broker
reactivation of the cache of parsed DICOM files
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 06 Nov 2019 17:54:14 +0100 |
parents | a0a33e5ea5bb |
children | cc029987b6dc |
files | Framework/Oracle/GenericOracleRunner.cpp Framework/Toolbox/ParsedDicomFileCache.cpp Framework/Toolbox/ParsedDicomFileCache.h |
diffstat | 3 files changed, 147 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Oracle/GenericOracleRunner.cpp Wed Nov 06 17:34:58 2019 +0100 +++ b/Framework/Oracle/GenericOracleRunner.cpp Wed Nov 06 17:54:14 2019 +0100 @@ -238,64 +238,143 @@ #if ORTHANC_ENABLE_DCMTK == 1 - static void RunInternal(boost::weak_ptr<IObserver> receiver, - IMessageEmitter& emitter, - const std::string& root, - const ParseDicomFileCommand& command) + namespace { - std::string path = GetPath(root, command.GetPath()); - - if (!Orthanc::SystemToolbox::IsRegularFile(path)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentFile); - } - - uint64_t fileSize = Orthanc::SystemToolbox::GetFileSize(path); - - // Check for 32bit systems - if (fileSize != static_cast<uint64_t>(static_cast<size_t>(fileSize))) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); - } - - DcmFileFormat dicom; - bool ok; - - if (command.IsPixelDataIncluded()) - { - ok = dicom.loadFile(path.c_str()).good(); - } - else + class IDicomHandler : public boost::noncopyable { -#if DCMTK_VERSION_NUMBER >= 362 - // NB : We could stop at (0x3007, 0x0000) instead of - // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants + public: + virtual ~IDicomHandler() + { + } + + virtual void Handle(Orthanc::ParsedDicomFile* dicom, + const ParseDicomFileCommand& command, + uint64_t fileSize) = 0; + + static void Apply(IDicomHandler& handler, + const std::string& root, + const ParseDicomFileCommand& command) + { + std::string path = GetPath(root, command.GetPath()); - static const DcmTagKey STOP = DCM_PixelData; - //static const DcmTagKey STOP(0x3007, 0x0000); + if (!Orthanc::SystemToolbox::IsRegularFile(path)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentFile); + } + + uint64_t fileSize = Orthanc::SystemToolbox::GetFileSize(path); + + // Check for 32bit systems + if (fileSize != static_cast<uint64_t>(static_cast<size_t>(fileSize))) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); + } + + DcmFileFormat dicom; + bool ok; - ok = dicom.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange, - DCM_MaxReadLength, ERM_autoDetect, STOP).good(); + if (command.IsPixelDataIncluded()) + { + ok = dicom.loadFile(path.c_str()).good(); + } + else + { +#if DCMTK_VERSION_NUMBER >= 362 + // NB : We could stop at (0x3007, 0x0000) instead of + // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants + + static const DcmTagKey STOP = DCM_PixelData; + //static const DcmTagKey STOP(0x3007, 0x0000); + + ok = dicom.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange, + DCM_MaxReadLength, ERM_autoDetect, STOP).good(); #else - // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2 - ok = dicom.loadFile(path.c_str()).good(); + // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2 + ok = dicom.loadFile(path.c_str()).good(); #endif - } + } + + printf("Reading %s\n", path.c_str()); + + if (ok) + { + handler.Handle(new Orthanc::ParsedDicomFile(dicom), command, fileSize); + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, + "Cannot parse file: " + path); + } + } + }; + - printf("Reading %s\n", path.c_str()); + class DicomHandlerWithoutCache : public IDicomHandler + { + private: + boost::weak_ptr<IObserver> receiver_; + IMessageEmitter& emitter_; + + public: + DicomHandlerWithoutCache(boost::weak_ptr<IObserver> receiver, + IMessageEmitter& emitter) : + receiver_(receiver), + emitter_(emitter) + { + } + + virtual void Handle(Orthanc::ParsedDicomFile* dicom, + const ParseDicomFileCommand& command, + uint64_t fileSize) + { + std::auto_ptr<Orthanc::ParsedDicomFile> parsed(dicom); - if (ok) + ParseDicomFileCommand::SuccessMessage message + (command, *parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); + emitter_.EmitMessage(receiver_, message); + } + }; + + + class DicomHandlerWithCache : public IDicomHandler { - Orthanc::ParsedDicomFile parsed(dicom); - ParseDicomFileCommand::SuccessMessage message - (command, parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); - emitter.EmitMessage(receiver, message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, - "Cannot parse file: " + path); - } + private: + boost::weak_ptr<IObserver> receiver_; + IMessageEmitter& emitter_; + boost::shared_ptr<ParsedDicomFileCache> cache_; + + public: + DicomHandlerWithCache(boost::weak_ptr<IObserver> receiver, + IMessageEmitter& emitter, + boost::shared_ptr<ParsedDicomFileCache> cache) : + receiver_(receiver), + emitter_(emitter), + cache_(cache) + { + if (!cache) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + } + + virtual void Handle(Orthanc::ParsedDicomFile* dicom, + const ParseDicomFileCommand& command, + uint64_t fileSize) + { + std::auto_ptr<Orthanc::ParsedDicomFile> parsed(dicom); + + { + ParseDicomFileCommand::SuccessMessage message + (command, *parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); + emitter_.EmitMessage(receiver_, message); + } + + // Store it into the cache for future use + assert(cache_); + cache_->Acquire(command.GetPath(), parsed.release(), + static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); + } + }; } @@ -305,8 +384,7 @@ const std::string& root, const ParseDicomFileCommand& command) { -#if 0 - // The code to use the cache is buggy in multithreaded environments => TODO FIX +#if 1 if (cache.get()) { { @@ -316,30 +394,25 @@ reader.HasPixelData())) { // Reuse the DICOM file from the cache - return new ParseDicomFileCommand::SuccessMessage( + ParseDicomFileCommand::SuccessMessage message( command, reader.GetDicom(), reader.GetFileSize(), reader.HasPixelData()); emitter.EmitMessage(receiver, message); return; } } - // Not in the cache, first read and parse the DICOM file - std::auto_ptr<ParseDicomFileCommand::SuccessMessage> message(RunInternal(root, command)); - - // Secondly, store it into the cache for future use - assert(&message->GetOrigin() == &command); - cache->Acquire(message->GetOrigin().GetPath(), message->GetDicom(), - message->GetFileSize(), message->HasPixelData()); - - return message.release(); + DicomHandlerWithCache handler(receiver, emitter, cache); + IDicomHandler::Apply(handler, root, command); } else { // No cache available - return RunInternal(root, command); + DicomHandlerWithoutCache handler(receiver, emitter); + IDicomHandler::Apply(handler, root, command); } #else - return RunInternal(receiver, emitter, root, command); + DicomHandlerWithoutCache handler(receiver, emitter); + IDicomHandler::Apply(handler, root, command); #endif }
--- a/Framework/Toolbox/ParsedDicomFileCache.cpp Wed Nov 06 17:34:58 2019 +0100 +++ b/Framework/Toolbox/ParsedDicomFileCache.cpp Wed Nov 06 17:54:14 2019 +0100 @@ -26,13 +26,13 @@ class ParsedDicomFileCache::Item : public Orthanc::ICacheable { private: - boost::mutex mutex_; - boost::shared_ptr<Orthanc::ParsedDicomFile> dicom_; - size_t fileSize_; - bool hasPixelData_; + boost::mutex mutex_; + std::auto_ptr<Orthanc::ParsedDicomFile> dicom_; + size_t fileSize_; + bool hasPixelData_; public: - Item(boost::shared_ptr<Orthanc::ParsedDicomFile> dicom, + Item(Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData) : dicom_(dicom), @@ -55,10 +55,10 @@ return fileSize_; } - boost::shared_ptr<Orthanc::ParsedDicomFile> GetDicom() const + Orthanc::ParsedDicomFile& GetDicom() const { assert(dicom_.get() != NULL); - return dicom_; + return *dicom_; } bool HasPixelData() const @@ -69,7 +69,7 @@ void ParsedDicomFileCache::Acquire(const std::string& path, - boost::shared_ptr<Orthanc::ParsedDicomFile> dicom, + Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData) { @@ -114,7 +114,7 @@ } - boost::shared_ptr<Orthanc::ParsedDicomFile> ParsedDicomFileCache::Reader::GetDicom() const + Orthanc::ParsedDicomFile& ParsedDicomFileCache::Reader::GetDicom() const { if (item_ == NULL) {
--- a/Framework/Toolbox/ParsedDicomFileCache.h Wed Nov 06 17:34:58 2019 +0100 +++ b/Framework/Toolbox/ParsedDicomFileCache.h Wed Nov 06 17:54:14 2019 +0100 @@ -24,8 +24,6 @@ #include <Core/Cache/MemoryObjectCache.h> #include <Core/DicomParsing/ParsedDicomFile.h> -#include <boost/shared_ptr.hpp> - namespace OrthancStone { class ParsedDicomFileCache : public boost::noncopyable @@ -42,7 +40,7 @@ } void Acquire(const std::string& path, - boost::shared_ptr<Orthanc::ParsedDicomFile> dicom, + Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData); @@ -64,7 +62,7 @@ bool HasPixelData() const; - boost::shared_ptr<Orthanc::ParsedDicomFile> GetDicom() const; + Orthanc::ParsedDicomFile& GetDicom() const; size_t GetFileSize() const; };