# HG changeset patch # User Sebastien Jodogne # Date 1730844415 -3600 # Node ID a8cf4c659e9c488a04a2364cd7c909ec762ac988 # Parent 35d211bbe1014cbcc255ecf6e58c4a37d7a8133b refactoring StatelessDatabaseOperations::LookupMetadata() diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -318,7 +318,8 @@ for (int i = 0; i < source.metadata().size(); i++) { - target.AddMetadata(level, static_cast(source.metadata(i).key()), source.metadata(i).value()); + target.AddMetadata(level, static_cast(source.metadata(i).key()), + source.metadata(i).value(), source.metadata(i).revision()); } } diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Plugins/Engine/OrthancPlugins.cpp --- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -4515,9 +4515,8 @@ PImpl::ServerContextReference lock(*pimpl_); std::string s; - int64_t revision; // unused if (lock.GetContext().GetIndex().LookupMetadata( - s, revision, params.instanceId, + s, params.instanceId, ResourceType_Instance, MetadataType_Instance_PixelDataVR)) { hasPixelData = true; @@ -4536,7 +4535,7 @@ } } else if (lock.GetContext().GetIndex().LookupMetadata( - s, revision, params.instanceId, + s, params.instanceId, ResourceType_Instance, MetadataType_Instance_PixelDataOffset)) { // This file was stored by an older version of Orthanc, diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto --- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Tue Nov 05 23:06:55 2024 +0100 @@ -926,6 +926,7 @@ message Metadata { int32 key = 1; string value = 2; + int64 revision = 3; } message MultipleTags { uint32 group = 1; diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/Compatibility/GenericFind.cpp --- a/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/Compatibility/GenericFind.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -445,7 +445,32 @@ if (request.IsRetrieveMetadata()) { - transaction_.GetAllMetadata(resource->GetMetadata(level), internalId); + std::map metadata; + transaction_.GetAllMetadata(metadata, internalId); + + for (std::map::const_iterator + it = metadata.begin(); it != metadata.end(); ++it) + { + if (request.IsRetrieveMetadataRevisions() && + capabilities.HasRevisionsSupport()) + { + std::string value; + int64_t revision; + if (transaction_.LookupMetadata(value, revision, internalId, it->first) && + value == it->second) + { + resource->AddMetadata(level, it->first, it->second, revision); + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + } + else + { + resource->AddMetadata(level, it->first, it->second, 0 /* revision not requested */); + } + } } { @@ -474,7 +499,14 @@ if (request.GetParentSpecification(currentLevel).IsRetrieveMetadata()) { - transaction_.GetAllMetadata(resource->GetMetadata(currentLevel), currentId); + std::map metadata; + transaction_.GetAllMetadata(metadata, currentId); + + for (std::map::const_iterator + it = metadata.begin(); it != metadata.end(); ++it) + { + resource->AddMetadata(currentLevel, it->first, it->second, 0 /* revision not request */); + } } } } diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/FindRequest.cpp --- a/OrthancServer/Sources/Database/FindRequest.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/FindRequest.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -90,6 +90,7 @@ labelsConstraint_(LabelsConstraint_All), retrieveMainDicomTags_(false), retrieveMetadata_(false), + retrieveMetadataRevisions_(false), retrieveLabels_(false), retrieveAttachments_(false), retrieveParentIdentifier_(false), diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/FindRequest.h --- a/OrthancServer/Sources/Database/FindRequest.h Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/FindRequest.h Tue Nov 05 23:06:55 2024 +0100 @@ -245,6 +245,7 @@ bool retrieveMainDicomTags_; bool retrieveMetadata_; + bool retrieveMetadataRevisions_; bool retrieveLabels_; bool retrieveAttachments_; bool retrieveParentIdentifier_; @@ -379,6 +380,16 @@ return retrieveMetadata_; } + void SetRetrieveMetadataRevisions(bool retrieve) + { + retrieveMetadataRevisions_ = retrieve; + } + + bool IsRetrieveMetadataRevisions() const + { + return retrieveMetadataRevisions_; + } + void SetRetrieveLabels(bool retrieve) { retrieveLabels_ = retrieve; diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/FindResponse.cpp --- a/OrthancServer/Sources/Database/FindResponse.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/FindResponse.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -333,9 +333,10 @@ void FindResponse::Resource::AddMetadata(ResourceType level, MetadataType metadata, - const std::string& value) + const std::string& value, + int64_t revision) { - std::map& m = GetMetadata(level); + std::map& m = GetMetadata(level); if (m.find(metadata) != m.end()) { @@ -343,12 +344,12 @@ } else { - m[metadata] = value; + m[metadata] = MetadataContent(value, revision); } } - std::map& FindResponse::Resource::GetMetadata(ResourceType level) + std::map& FindResponse::Resource::GetMetadata(ResourceType level) { if (!IsResourceLevelAboveOrEqual(level, level_)) { @@ -379,9 +380,9 @@ ResourceType level, MetadataType metadata) const { - const std::map& m = GetMetadata(level); + const std::map& m = GetMetadata(level); - std::map::const_iterator found = m.find(metadata); + std::map::const_iterator found = m.find(metadata); if (found == m.end()) { @@ -389,7 +390,29 @@ } else { - value = found->second; + value = found->second.GetValue(); + return true; + } + } + + + bool FindResponse::Resource::LookupMetadata(std::string& value, + int64_t& revision, + ResourceType level, + MetadataType metadata) const + { + const std::map& m = GetMetadata(level); + + std::map::const_iterator found = m.find(metadata); + + if (found == m.end()) + { + return false; + } + else + { + value = found->second.GetValue(); + revision = found->second.GetRevision(); return true; } } @@ -648,6 +671,18 @@ } + static void DebugMetadata(Json::Value& target, + const std::map& m) + { + target = Json::objectValue; + + for (std::map::const_iterator it = m.begin(); it != m.end(); ++it) + { + target[EnumerationToString(it->first)] = it->second.GetValue(); + } + } + + static void DebugAddAttachment(Json::Value& target, const FileInfo& info) { diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/FindResponse.h --- a/OrthancServer/Sources/Database/FindResponse.h Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/FindResponse.h Tue Nov 05 23:06:55 2024 +0100 @@ -101,6 +101,48 @@ public: + class MetadataContent + { + private: + std::string value_; + int64_t revision_; + + public: + MetadataContent() : + revision_(0) + { + } + + MetadataContent(const std::string& value, + int64_t revision) : + value_(value), + revision_(revision) + { + } + + MetadataContent(const std::string& value) : + value_(value), + revision_(0) + { + } + + const std::string& GetValue() const + { + return value_; + } + + int64_t GetRevision() const + { + return revision_; + } + + void SetRevision(int64_t revision) + { + revision_ = revision; + } + }; + + class Resource : public boost::noncopyable { private: @@ -114,10 +156,10 @@ MainDicomTagsAtLevel mainDicomTagsStudy_; MainDicomTagsAtLevel mainDicomTagsSeries_; MainDicomTagsAtLevel mainDicomTagsInstance_; - std::map metadataPatient_; - std::map metadataStudy_; - std::map metadataSeries_; - std::map metadataInstance_; + std::map metadataPatient_; + std::map metadataStudy_; + std::map metadataSeries_; + std::map metadataInstance_; ChildrenInformation childrenStudiesInformation_; ChildrenInformation childrenSeriesInformation_; ChildrenInformation childrenInstancesInformation_; @@ -200,11 +242,12 @@ void AddMetadata(ResourceType level, MetadataType metadata, - const std::string& value); + const std::string& value, + int64_t revision); - std::map& GetMetadata(ResourceType level); + std::map& GetMetadata(ResourceType level); - const std::map& GetMetadata(ResourceType level) const + const std::map& GetMetadata(ResourceType level) const { return const_cast(*this).GetMetadata(level); } @@ -213,6 +256,11 @@ ResourceType level, MetadataType metadata) const; + bool LookupMetadata(std::string& value, + int64_t& revision, + ResourceType level, + MetadataType metadata) const; + void AddChildIdentifier(ResourceType level, const std::string& childId) { diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp --- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -1038,7 +1038,7 @@ FindResponse::Resource& res = response.GetResourceByInternalId(internalId); res.AddMetadata(static_cast(requestLevel), static_cast(s.ColumnInt(C6_INT_1)), - s.ColumnString(C3_STRING_1)); + s.ColumnString(C3_STRING_1), 0 /* no support for revision */); }; break; case QUERY_PARENT_METADATA: @@ -1046,7 +1046,7 @@ FindResponse::Resource& res = response.GetResourceByInternalId(internalId); res.AddMetadata(static_cast(requestLevel - 1), static_cast(s.ColumnInt(C6_INT_1)), - s.ColumnString(C3_STRING_1)); + s.ColumnString(C3_STRING_1), 0 /* no support for revision */); }; break; case QUERY_GRAND_PARENT_METADATA: @@ -1054,7 +1054,7 @@ FindResponse::Resource& res = response.GetResourceByInternalId(internalId); res.AddMetadata(static_cast(requestLevel - 2), static_cast(s.ColumnInt(C6_INT_1)), - s.ColumnString(C3_STRING_1)); + s.ColumnString(C3_STRING_1), 0 /* no support for revision */); }; break; case QUERY_CHILDREN_METADATA: diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -605,7 +605,13 @@ } else { - target = response.GetResourceByIndex(0).GetMetadata(level); + std::map metadata = response.GetResourceByIndex(0).GetMetadata(level); + + target.clear(); + for (std::map::const_iterator it = metadata.begin(); it != metadata.end(); ++it) + { + target[it->first] = it->second.GetValue(); + } } } else @@ -1014,36 +1020,73 @@ bool StatelessDatabaseOperations::LookupMetadata(std::string& target, + const std::string& publicId, + ResourceType expectedType, + MetadataType type) + { + FindRequest request(expectedType); + request.SetOrthancId(expectedType, publicId); + request.SetRetrieveMetadata(true); + request.SetRetrieveMetadataRevisions(false); // No need to retrieve revisions + + FindResponse response; + ExecuteFind(response, request); + + if (response.GetSize() == 0) + { + throw OrthancException(ErrorCode_UnknownResource); + } + else if (response.GetSize() == 1) + { + if (response.GetResourceByIndex(0).GetLevel() != expectedType) + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + else + { + return response.GetResourceByIndex(0).LookupMetadata(target, expectedType, type); + } + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } + } + + + bool StatelessDatabaseOperations::LookupMetadata(std::string& target, int64_t& revision, const std::string& publicId, ResourceType expectedType, MetadataType type) { - class Operations : public ReadOnlyOperationsT6 + FindRequest request(expectedType); + request.SetOrthancId(expectedType, publicId); + request.SetRetrieveMetadata(true); + request.SetRetrieveMetadataRevisions(true); // We are asked to retrieve revisions + + FindResponse response; + ExecuteFind(response, request); + + if (response.GetSize() == 0) { - public: - virtual void ApplyTuple(ReadOnlyTransaction& transaction, - const Tuple& tuple) ORTHANC_OVERRIDE + throw OrthancException(ErrorCode_UnknownResource); + } + else if (response.GetSize() == 1) + { + if (response.GetResourceByIndex(0).GetLevel() != expectedType) { - ResourceType resourceType; - int64_t id; - if (!transaction.LookupResource(id, resourceType, tuple.get<3>()) || - resourceType != tuple.get<4>()) - { - throw OrthancException(ErrorCode_UnknownResource); - } - else - { - tuple.get<0>() = transaction.LookupMetadata(tuple.get<1>(), tuple.get<2>(), id, tuple.get<5>()); - } + throw OrthancException(ErrorCode_DatabasePlugin); + } + else + { + return response.GetResourceByIndex(0).LookupMetadata(target, revision, expectedType, type); } - }; - - bool found; - Operations operations; - operations.Apply(*this, found, target, revision, publicId, expectedType, type); - return found; + } + else + { + throw OrthancException(ErrorCode_DatabasePlugin); + } } diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/Database/StatelessDatabaseOperations.h --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Tue Nov 05 23:06:55 2024 +0100 @@ -576,6 +576,11 @@ const std::string& publicId); bool LookupMetadata(std::string& target, + const std::string& publicId, + ResourceType expectedType, + MetadataType type); + + bool LookupMetadata(std::string& target, int64_t& revision, const std::string& publicId, ResourceType expectedType, diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/OrthancFindRequestHandler.cpp --- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -30,7 +30,7 @@ #include "../../OrthancFramework/Sources/Lua/LuaFunctionCall.h" #include "../../OrthancFramework/Sources/MetricsRegistry.h" #include "OrthancConfiguration.h" -#include "ResourceFinder.cpp" +#include "ResourceFinder.h" #include "Search/DatabaseLookup.h" #include "ServerContext.h" #include "ServerToolbox.h" diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/OrthancWebDav.cpp --- a/OrthancServer/Sources/OrthancWebDav.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/OrthancWebDav.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -74,8 +74,7 @@ MetadataType metadata) { std::string value; - int64_t revision; // Ignored - if (context.GetIndex().LookupMetadata(value, revision, publicId, level, metadata)) + if (context.GetIndex().LookupMetadata(value, publicId, level, metadata)) { ParseTime(target, value); } diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/ResourceFinder.cpp --- a/OrthancServer/Sources/ResourceFinder.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/ResourceFinder.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -439,13 +439,13 @@ if (responseContent_ & ResponseContentFlags_Metadata) // new in Orthanc 1.12.4 { - const std::map& m = resource.GetMetadata(resource.GetLevel()); + const std::map& m = resource.GetMetadata(resource.GetLevel()); Json::Value metadata = Json::objectValue; - for (std::map::const_iterator it = m.begin(); it != m.end(); ++it) + for (std::map::const_iterator it = m.begin(); it != m.end(); ++it) { - metadata[EnumerationToString(it->first)] = it->second; + metadata[EnumerationToString(it->first)] = it->second.GetValue(); } target["Metadata"] = metadata; @@ -908,6 +908,19 @@ } + static void ConvertMetadata(std::map& converted, + const FindResponse::Resource& resource) + { + const std::map metadata = resource.GetMetadata(ResourceType_Instance); + + for (std::map::const_iterator + it = metadata.begin(); it != metadata.end(); ++it) + { + converted[it->first] = it->second.GetValue(); + } + } + + static void ReadMissingTagsFromStorageArea(DicomMap& requestedTags, ServerContext& context, const FindRequest& request, @@ -937,7 +950,10 @@ { LOG(INFO) << "Will retrieve missing DICOM tags from instance: " << resource.GetIdentifier(); - context.ReadDicomAsJson(tmpDicomAsJson, resource.GetIdentifier(), resource.GetMetadata(ResourceType_Instance), + std::map converted; + ConvertMetadata(converted, resource); + + context.ReadDicomAsJson(tmpDicomAsJson, resource.GetIdentifier(), converted, resource.GetAttachments(), missingTags /* ignoreTagLength */); } else if (request.GetLevel() != ResourceType_Instance && @@ -980,7 +996,10 @@ if (request.GetLevel() == ResourceType_Instance) { - context.ReadDicomAsJson(tmpDicomAsJson, response.GetIdentifier(), response.GetMetadata(ResourceType_Instance), + std::map converted; + ConvertMetadata(converted, resource); + + context.ReadDicomAsJson(tmpDicomAsJson, response.GetIdentifier(), converted, response.GetAttachments(), missingTags /* ignoreTagLength */); } else diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/ServerContext.cpp --- a/OrthancServer/Sources/ServerContext.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -1110,7 +1110,7 @@ } std::string s; - if (index_.LookupMetadata(s, revision, instancePublicId, ResourceType_Instance, + if (index_.LookupMetadata(s, instancePublicId, ResourceType_Instance, MetadataType_Instance_PixelDataOffset)) { metadata[MetadataType_Instance_PixelDataOffset] = s; @@ -1346,7 +1346,7 @@ std::string s; if (attachment.GetCompressionType() == CompressionType_None && - index_.LookupMetadata(s, revision, instancePublicId, ResourceType_Instance, + index_.LookupMetadata(s, instancePublicId, ResourceType_Instance, MetadataType_Instance_PixelDataOffset) && !s.empty()) { @@ -1638,8 +1638,7 @@ if (metadata == MetadataType_Instance_SopClassUid || metadata == MetadataType_Instance_TransferSyntax) { - int64_t revision; // Ignored - if (index_.LookupMetadata(target, revision, publicId, level, metadata)) + if (index_.LookupMetadata(target, publicId, level, metadata)) { return true; } @@ -1694,8 +1693,7 @@ else { // No backward - int64_t revision; // Ignored - return index_.LookupMetadata(target, revision, publicId, level, metadata); + return index_.LookupMetadata(target, publicId, level, metadata); } } diff -r 35d211bbe101 -r a8cf4c659e9c OrthancServer/Sources/SliceOrdering.cpp --- a/OrthancServer/Sources/SliceOrdering.cpp Tue Nov 05 19:22:16 2024 +0100 +++ b/OrthancServer/Sources/SliceOrdering.cpp Tue Nov 05 23:06:55 2024 +0100 @@ -198,8 +198,7 @@ try { - int64_t revision; // Ignored - if (index.LookupMetadata(s, revision, instanceId, ResourceType_Instance, MetadataType_Instance_IndexInSeries)) + if (index.LookupMetadata(s, instanceId, ResourceType_Instance, MetadataType_Instance_IndexInSeries)) { indexInSeries_ = boost::lexical_cast(Toolbox::StripSpaces(s)); hasIndexInSeries_ = true;