# HG changeset patch # User Sebastien Jodogne # Date 1573059254 -3600 # Node ID 42581a6182c8fd75b6b4e171fb15760686119522 # Parent a0a33e5ea5bb82c5e2813e815d0ceb19cdbc6175 reactivation of the cache of parsed DICOM files diff -r a0a33e5ea5bb -r 42581a6182c8 Framework/Oracle/GenericOracleRunner.cpp --- 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 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(static_cast(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(static_cast(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 receiver_; + IMessageEmitter& emitter_; + + public: + DicomHandlerWithoutCache(boost::weak_ptr receiver, + IMessageEmitter& emitter) : + receiver_(receiver), + emitter_(emitter) + { + } + + virtual void Handle(Orthanc::ParsedDicomFile* dicom, + const ParseDicomFileCommand& command, + uint64_t fileSize) + { + std::auto_ptr parsed(dicom); - if (ok) + ParseDicomFileCommand::SuccessMessage message + (command, *parsed, static_cast(fileSize), command.IsPixelDataIncluded()); + emitter_.EmitMessage(receiver_, message); + } + }; + + + class DicomHandlerWithCache : public IDicomHandler { - Orthanc::ParsedDicomFile parsed(dicom); - ParseDicomFileCommand::SuccessMessage message - (command, parsed, static_cast(fileSize), command.IsPixelDataIncluded()); - emitter.EmitMessage(receiver, message); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, - "Cannot parse file: " + path); - } + private: + boost::weak_ptr receiver_; + IMessageEmitter& emitter_; + boost::shared_ptr cache_; + + public: + DicomHandlerWithCache(boost::weak_ptr receiver, + IMessageEmitter& emitter, + boost::shared_ptr 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 parsed(dicom); + + { + ParseDicomFileCommand::SuccessMessage message + (command, *parsed, static_cast(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(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 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 } diff -r a0a33e5ea5bb -r 42581a6182c8 Framework/Toolbox/ParsedDicomFileCache.cpp --- 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 dicom_; - size_t fileSize_; - bool hasPixelData_; + boost::mutex mutex_; + std::auto_ptr dicom_; + size_t fileSize_; + bool hasPixelData_; public: - Item(boost::shared_ptr dicom, + Item(Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData) : dicom_(dicom), @@ -55,10 +55,10 @@ return fileSize_; } - boost::shared_ptr 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 dicom, + Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData) { @@ -114,7 +114,7 @@ } - boost::shared_ptr ParsedDicomFileCache::Reader::GetDicom() const + Orthanc::ParsedDicomFile& ParsedDicomFileCache::Reader::GetDicom() const { if (item_ == NULL) { diff -r a0a33e5ea5bb -r 42581a6182c8 Framework/Toolbox/ParsedDicomFileCache.h --- 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 #include -#include - namespace OrthancStone { class ParsedDicomFileCache : public boost::noncopyable @@ -42,7 +40,7 @@ } void Acquire(const std::string& path, - boost::shared_ptr dicom, + Orthanc::ParsedDicomFile* dicom, size_t fileSize, bool hasPixelData); @@ -64,7 +62,7 @@ bool HasPixelData() const; - boost::shared_ptr GetDicom() const; + Orthanc::ParsedDicomFile& GetDicom() const; size_t GetFileSize() const; };