# HG changeset patch # User Sebastien Jodogne # Date 1720726640 -7200 # Node ID 023787ecaff2eca11b390c2bc757638922c93a90 # Parent 7c11a71927a9c68632ca5f182872768c2367c332 cont diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp --- a/OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/Database/MainDicomTagsRegistry.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -98,10 +98,12 @@ } - void MainDicomTagsRegistry::NormalizeLookup(DatabaseConstraints& target, + bool MainDicomTagsRegistry::NormalizeLookup(DatabaseConstraints& target, const DatabaseLookup& source, ResourceType queryLevel) const { + bool isEquivalentLookup = true; + target.Clear(); for (size_t i = 0; i < source.GetConstraintsCount(); i++) @@ -121,8 +123,20 @@ level = ResourceType_Study; } - target.AddConstraint(source.GetConstraint(i).ConvertToDatabaseConstraint(level, type)); + bool isEquivalentConstraint; + target.AddConstraint(source.GetConstraint(i).ConvertToDatabaseConstraint(isEquivalentConstraint, level, type)); + + if (!isEquivalentConstraint) + { + isEquivalentLookup = false; + } + } + else + { + isEquivalentLookup = false; } } + + return isEquivalentLookup; } } diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/Database/MainDicomTagsRegistry.h --- a/OrthancServer/Sources/Database/MainDicomTagsRegistry.h Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/Database/MainDicomTagsRegistry.h Thu Jul 11 21:37:20 2024 +0200 @@ -75,7 +75,13 @@ DicomTagType& type, const DicomTag& tag) const; - void NormalizeLookup(DatabaseConstraints& target, + /** + * Returns "true" iff. the normalized lookup is the same as the + * original DatabaseLookup. If "false" is returned, the target + * constraints are less strict than the original DatabaseLookup, + * so more resources will match them. + **/ + bool NormalizeLookup(DatabaseConstraints& target, const DatabaseLookup& source, ResourceType queryLevel) const; }; diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -1552,7 +1552,8 @@ DicomTagConstraint c(tag, ConstraintType_Equal, value, true, true); DatabaseConstraints query; - query.AddConstraint(c.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); + bool isIdentical; // unused + query.AddConstraint(c.ConvertToDatabaseConstraint(isIdentical, level, DicomTagType_Identifier)); class Operations : public IReadOnlyOperations diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -265,7 +265,8 @@ uint64_t since = boost::lexical_cast(call.GetArgument("since", "")); uint64_t limit = boost::lexical_cast(call.GetArgument("limit", "")); - finder.SetLimits(since, limit); + finder.SetLimitsSince(since); + finder.SetLimitsCount(limit); } Json::Value answer; @@ -3347,36 +3348,32 @@ finder.SetDatabaseLimits(context.GetDatabaseLimits(level)); finder.SetFormat(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human)); - size_t limit = 0; if (request.isMember(KEY_LIMIT)) { - int tmp = request[KEY_LIMIT].asInt(); + int64_t tmp = request[KEY_LIMIT].asInt64(); if (tmp < 0) { throw OrthancException(ErrorCode_ParameterOutOfRange, "Field \"" + std::string(KEY_LIMIT) + "\" must be a positive integer"); } - - limit = static_cast(tmp); + else + { + finder.SetLimitsCount(static_cast(tmp)); + } } - size_t since = 0; if (request.isMember(KEY_SINCE)) { - int tmp = request[KEY_SINCE].asInt(); + int64_t tmp = request[KEY_SINCE].asInt64(); if (tmp < 0) { throw OrthancException(ErrorCode_ParameterOutOfRange, "Field \"" + std::string(KEY_SINCE) + "\" must be a positive integer"); } - - since = static_cast(tmp); - } - - if (request.isMember(KEY_LIMIT) || - request.isMember(KEY_SINCE)) - { - finder.SetLimits(since, limit); + else + { + finder.SetLimitsSince(static_cast(tmp)); + } } { diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/ResourceFinder.cpp --- a/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/ResourceFinder.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -425,7 +425,7 @@ void ResourceFinder::UpdateRequestLimits() { // By default, use manual paging - isDatabasePaging_ = false; + pagingMode_ = PagingMode_FullManual; if (databaseLimits_ != 0) { @@ -436,15 +436,34 @@ request_.ClearLimits(); } - if (hasLimits_) + if (lookup_.get() == NULL && + (hasLimitsSince_ || hasLimitsCount_)) { - if (lookup_.get() == NULL) + pagingMode_ = PagingMode_FullDatabase; + request_.SetLimits(limitsSince_, limitsCount_); + } + + if (lookup_.get() != NULL && + isSimpleLookup_ && + (hasLimitsSince_ || hasLimitsCount_)) + { + /** + * TODO-FIND: "IDatabaseWrapper::ApplyLookupResources()" only + * accept the "limit" argument. The "since" must be implemented + * manually. + **/ + + if (hasLimitsSince_ && + limitsSince_ != 0) { - isDatabasePaging_ = true; - request_.SetLimits(limitsSince_, limitsCount_); + pagingMode_ = PagingMode_ManualSkip; + request_.SetLimits(0, limitsCount_ + limitsSince_); } - - // TODO-FIND: enable database paging on "simple" lookups that involve no normalization + else + { + pagingMode_ = PagingMode_FullDatabase; + request_.SetLimits(0, limitsCount_); + } } // TODO-FIND: More cases could be added, depending on "GetDatabaseCapabilities()" @@ -455,8 +474,10 @@ bool expand) : request_(level), databaseLimits_(0), - isDatabasePaging_(true), - hasLimits_(false), + isSimpleLookup_(true), + pagingMode_(PagingMode_FullManual), + hasLimitsSince_(false), + hasLimitsCount_(false), limitsSince_(0), limitsCount_(0), expand_(expand), @@ -509,17 +530,30 @@ } - void ResourceFinder::SetLimits(uint64_t since, - uint64_t count) + void ResourceFinder::SetLimitsSince(uint64_t since) { - if (hasLimits_) + if (hasLimitsSince_) { throw OrthancException(ErrorCode_BadSequenceOfCalls); } else { - hasLimits_ = true; + hasLimitsSince_ = true; limitsSince_ = since; + UpdateRequestLimits(); + } + } + + + void ResourceFinder::SetLimitsCount(uint64_t count) + { + if (hasLimitsCount_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + hasLimitsCount_ = true; limitsCount_ = count; UpdateRequestLimits(); } @@ -540,7 +574,7 @@ } MainDicomTagsRegistry registry; - registry.NormalizeLookup(request_.GetDicomTagConstraints(), lookup, request_.GetLevel()); + isSimpleLookup_ = registry.NormalizeLookup(request_.GetDicomTagConstraints(), lookup, request_.GetLevel()); // "request_.GetDicomTagConstraints()" only contains constraints on main DICOM tags @@ -835,14 +869,21 @@ context.GetIndex().ExecuteFind(response, request_); bool complete; - if (isDatabasePaging_) + + switch (pagingMode_) { - complete = true; - } - else - { - complete = (databaseLimits_ == 0 || - response.GetSize() <= databaseLimits_); + case PagingMode_FullDatabase: + case PagingMode_ManualSkip: + complete = true; + break; + + case PagingMode_FullManual: + complete = (databaseLimits_ == 0 || + response.GetSize() <= databaseLimits_); + break; + + default: + throw OrthancException(ErrorCode_InternalError); } if (lookup_.get() != NULL) @@ -895,18 +936,18 @@ if (match) { - if (isDatabasePaging_) + if (pagingMode_ == PagingMode_FullDatabase) { visitor.Apply(resource, hasRequestedTags_, requestedTags); } else { - if (hasLimits_ && + if (hasLimitsSince_ && skipped < limitsSince_) { skipped++; } - else if (hasLimits_ && + else if (hasLimitsCount_ && countResults >= limitsCount_) { // Too many results, don't mark as complete diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/ResourceFinder.h --- a/OrthancServer/Sources/ResourceFinder.h Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/ResourceFinder.h Thu Jul 11 21:37:20 2024 +0200 @@ -50,11 +50,20 @@ }; private: + enum PagingMode + { + PagingMode_FullDatabase, + PagingMode_FullManual, + PagingMode_ManualSkip + }; + FindRequest request_; uint64_t databaseLimits_; std::unique_ptr lookup_; - bool isDatabasePaging_; - bool hasLimits_; + bool isSimpleLookup_; + PagingMode pagingMode_; + bool hasLimitsSince_; + bool hasLimitsCount_; uint64_t limitsSince_; uint64_t limitsCount_; bool expand_; @@ -122,8 +131,9 @@ format_ = format; } - void SetLimits(uint64_t since, - uint64_t count); + void SetLimitsSince(uint64_t since); + + void SetLimitsCount(uint64_t count); void SetDatabaseLookup(const DatabaseLookup& lookup); diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/Search/DicomTagConstraint.cpp --- a/OrthancServer/Sources/Search/DicomTagConstraint.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/Search/DicomTagConstraint.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -369,7 +369,8 @@ } - DatabaseConstraint* DicomTagConstraint::ConvertToDatabaseConstraint(ResourceType level, + DatabaseConstraint* DicomTagConstraint::ConvertToDatabaseConstraint(bool& isIdentical, + ResourceType level, DicomTagType tagType) const { bool isIdentifier, caseSensitive; @@ -392,13 +393,21 @@ std::vector values; values.reserve(values_.size()); - + + isIdentical = true; + for (std::set::const_iterator it = values_.begin(); it != values_.end(); ++it) { if (isIdentifier) { - values.push_back(ServerToolbox::NormalizeIdentifier(*it)); + std::string normalized = ServerToolbox::NormalizeIdentifier(*it); + values.push_back(normalized); + + if (normalized != *it) + { + isIdentical = false; + } } else { diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/Sources/Search/DicomTagConstraint.h --- a/OrthancServer/Sources/Search/DicomTagConstraint.h Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/Sources/Search/DicomTagConstraint.h Thu Jul 11 21:37:20 2024 +0200 @@ -109,7 +109,8 @@ std::string Format() const; - DatabaseConstraint* ConvertToDatabaseConstraint(ResourceType level, + DatabaseConstraint* ConvertToDatabaseConstraint(bool& isIdentical /* out */, + ResourceType level, DicomTagType tagType) const; }; } diff -r 7c11a71927a9 -r 023787ecaff2 OrthancServer/UnitTestsSources/ServerIndexTests.cpp --- a/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Thu Jul 11 20:20:50 2024 +0200 +++ b/OrthancServer/UnitTestsSources/ServerIndexTests.cpp Thu Jul 11 21:37:20 2024 +0200 @@ -167,7 +167,8 @@ DicomTagConstraint c(tag, type, value, true, true); DatabaseConstraints lookup; - lookup.AddConstraint(c.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); + bool isEquivalent; // unused + lookup.AddConstraint(c.ConvertToDatabaseConstraint(isEquivalent, level, DicomTagType_Identifier)); std::set noLabel; transaction_->ApplyLookupResources(result, NULL, lookup, level, noLabel, LabelsConstraint_All, 0 /* no limit */); @@ -187,8 +188,9 @@ DicomTagConstraint c2(tag, type2, value2, true, true); DatabaseConstraints lookup; - lookup.AddConstraint(c1.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); - lookup.AddConstraint(c2.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); + bool isEquivalent; // unused + lookup.AddConstraint(c1.ConvertToDatabaseConstraint(isEquivalent, level, DicomTagType_Identifier)); + lookup.AddConstraint(c2.ConvertToDatabaseConstraint(isEquivalent, level, DicomTagType_Identifier)); std::set noLabel; transaction_->ApplyLookupResources(result, NULL, lookup, level, noLabel, LabelsConstraint_All, 0 /* no limit */);