Mercurial > hg > orthanc
comparison OrthancServer/Sources/ResourceFinder.cpp @ 5688:d0a264b803f1 find-refactoring
first implementation of database paging
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 09 Jul 2024 15:36:28 +0200 |
parents | 11575590e493 |
children | c14776d25491 |
comparison
equal
deleted
inserted
replaced
5686:11575590e493 | 5688:d0a264b803f1 |
---|---|
420 target["Metadata"] = metadata; | 420 target["Metadata"] = metadata; |
421 } | 421 } |
422 } | 422 } |
423 | 423 |
424 | 424 |
425 void ResourceFinder::UpdateRequestLimits() | |
426 { | |
427 // TODO-FIND: Check this | |
428 | |
429 if (lookup_.get() == NULL || | |
430 lookup_->HasOnlyMainDicomTags()) | |
431 { | |
432 isDatabasePaging_ = true; | |
433 | |
434 if (hasLimits_) | |
435 { | |
436 request_.SetLimits(limitsSince_, limitsCount_); | |
437 } | |
438 } | |
439 else if (databaseLimits_ != 0) | |
440 { | |
441 // The "+ 1" below is used to test the completeness of the response | |
442 request_.SetLimits(0, databaseLimits_ + 1); | |
443 isDatabasePaging_ = false; | |
444 } | |
445 else | |
446 { | |
447 isDatabasePaging_ = false; | |
448 } | |
449 } | |
450 | |
451 | |
425 ResourceFinder::ResourceFinder(ResourceType level, | 452 ResourceFinder::ResourceFinder(ResourceType level, |
426 bool expand) : | 453 bool expand) : |
427 request_(level), | 454 request_(level), |
455 databaseLimits_(0), | |
456 isDatabasePaging_(true), | |
457 hasLimits_(false), | |
458 limitsSince_(0), | |
459 limitsCount_(0), | |
428 expand_(expand), | 460 expand_(expand), |
429 format_(DicomToJsonFormat_Human), | 461 format_(DicomToJsonFormat_Human), |
430 allowStorageAccess_(true), | 462 allowStorageAccess_(true), |
431 hasRequestedTags_(false), | 463 hasRequestedTags_(false), |
432 includeAllMetadata_(false) | 464 includeAllMetadata_(false) |
433 { | 465 { |
466 UpdateRequestLimits(); | |
467 | |
434 if (expand) | 468 if (expand) |
435 { | 469 { |
436 request_.SetRetrieveMainDicomTags(true); | 470 request_.SetRetrieveMainDicomTags(true); |
437 request_.SetRetrieveMetadata(true); | 471 request_.SetRetrieveMetadata(true); |
438 request_.SetRetrieveLabels(true); | 472 request_.SetRetrieveLabels(true); |
464 } | 498 } |
465 } | 499 } |
466 } | 500 } |
467 | 501 |
468 | 502 |
503 void ResourceFinder::SetDatabaseLimits(uint64_t limits) | |
504 { | |
505 databaseLimits_ = limits; | |
506 UpdateRequestLimits(); | |
507 } | |
508 | |
509 | |
510 void ResourceFinder::SetLimits(uint64_t since, | |
511 uint64_t count) | |
512 { | |
513 if (hasLimits_) | |
514 { | |
515 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
516 } | |
517 else | |
518 { | |
519 hasLimits_ = true; | |
520 limitsSince_ = since; | |
521 limitsCount_ = count; | |
522 UpdateRequestLimits(); | |
523 } | |
524 } | |
525 | |
526 | |
469 void ResourceFinder::SetDatabaseLookup(const DatabaseLookup& lookup) | 527 void ResourceFinder::SetDatabaseLookup(const DatabaseLookup& lookup) |
470 { | 528 { |
471 lookup_.reset(lookup.Clone()); | 529 lookup_.reset(lookup.Clone()); |
530 UpdateRequestLimits(); | |
472 | 531 |
473 for (size_t i = 0; i < lookup.GetConstraintsCount(); i++) | 532 for (size_t i = 0; i < lookup.GetConstraintsCount(); i++) |
474 { | 533 { |
475 DicomTag tag = lookup.GetConstraint(i).GetTag(); | 534 DicomTag tag = lookup.GetConstraint(i).GetTag(); |
476 if (IsComputedTag(tag)) | 535 if (IsComputedTag(tag)) |
746 { | 805 { |
747 index.ExecuteFind(response, request_); | 806 index.ExecuteFind(response, request_); |
748 } | 807 } |
749 | 808 |
750 | 809 |
751 void ResourceFinder::Execute(Json::Value& target, | 810 void ResourceFinder::Execute(IVisitor& visitor, |
752 ServerContext& context) const | 811 ServerContext& context) const |
753 { | 812 { |
754 FindResponse response; | 813 FindResponse response; |
755 context.GetIndex().ExecuteFind(response, request_); | 814 context.GetIndex().ExecuteFind(response, request_); |
756 | 815 |
757 target = Json::arrayValue; | 816 bool complete; |
817 if (isDatabasePaging_) | |
818 { | |
819 complete = true; | |
820 } | |
821 else | |
822 { | |
823 complete = (databaseLimits_ == 0 || | |
824 response.GetSize() <= databaseLimits_); | |
825 } | |
826 | |
827 if (lookup_.get() != NULL && | |
828 !lookup_->HasOnlyMainDicomTags()) | |
829 { | |
830 LOG(INFO) << "Number of candidate resources after fast DB filtering on main DICOM tags: " << response.GetSize(); | |
831 } | |
832 | |
833 size_t countResults = 0; | |
834 size_t skipped = 0; | |
758 | 835 |
759 for (size_t i = 0; i < response.GetSize(); i++) | 836 for (size_t i = 0; i < response.GetSize(); i++) |
760 { | 837 { |
761 const FindResponse::Resource& resource = response.GetResourceByIndex(i); | 838 const FindResponse::Resource& resource = response.GetResourceByIndex(i); |
762 | 839 |
796 match = lookup_->IsMatch(tags); | 873 match = lookup_->IsMatch(tags); |
797 } | 874 } |
798 | 875 |
799 if (match) | 876 if (match) |
800 { | 877 { |
801 if (expand_) | 878 if (isDatabasePaging_) |
879 { | |
880 visitor.Apply(resource, hasRequestedTags_, requestedTags); | |
881 } | |
882 else | |
883 { | |
884 if (hasLimits_ && | |
885 skipped < limitsSince_) | |
886 { | |
887 skipped++; | |
888 } | |
889 else if (hasLimits_ && | |
890 countResults >= limitsCount_) | |
891 { | |
892 // Too many results, don't mark as complete | |
893 complete = false; | |
894 break; | |
895 } | |
896 else | |
897 { | |
898 visitor.Apply(resource, hasRequestedTags_, requestedTags); | |
899 countResults++; | |
900 } | |
901 } | |
902 } | |
903 } | |
904 | |
905 if (complete) | |
906 { | |
907 visitor.MarkAsComplete(); | |
908 } | |
909 } | |
910 | |
911 | |
912 void ResourceFinder::Execute(Json::Value& target, | |
913 ServerContext& context) const | |
914 { | |
915 class Visitor : public IVisitor | |
916 { | |
917 private: | |
918 const ResourceFinder& that_; | |
919 ServerIndex& index_; | |
920 Json::Value& target_; | |
921 | |
922 public: | |
923 Visitor(const ResourceFinder& that, | |
924 ServerIndex& index, | |
925 Json::Value& target) : | |
926 that_(that), | |
927 index_(index), | |
928 target_(target) | |
929 { | |
930 } | |
931 | |
932 virtual void Apply(const FindResponse::Resource& resource, | |
933 bool hasRequestedTags, | |
934 const DicomMap& requestedTags) ORTHANC_OVERRIDE | |
935 { | |
936 if (that_.expand_) | |
802 { | 937 { |
803 Json::Value item; | 938 Json::Value item; |
804 Expand(item, resource, context.GetIndex()); | 939 that_.Expand(item, resource, index_); |
805 | 940 |
806 if (hasRequestedTags_) | 941 if (hasRequestedTags) |
807 { | 942 { |
808 static const char* const REQUESTED_TAGS = "RequestedTags"; | 943 static const char* const REQUESTED_TAGS = "RequestedTags"; |
809 item[REQUESTED_TAGS] = Json::objectValue; | 944 item[REQUESTED_TAGS] = Json::objectValue; |
810 FromDcmtkBridge::ToJson(item[REQUESTED_TAGS], requestedTags, format_); | 945 FromDcmtkBridge::ToJson(item[REQUESTED_TAGS], requestedTags, that_.format_); |
811 } | 946 } |
812 | 947 |
813 target.append(item); | 948 target_.append(item); |
814 } | 949 } |
815 else | 950 else |
816 { | 951 { |
817 target.append(resource.GetIdentifier()); | 952 target_.append(resource.GetIdentifier()); |
818 } | 953 } |
819 } | 954 } |
820 } | 955 |
956 virtual void MarkAsComplete() ORTHANC_OVERRIDE | |
957 { | |
958 } | |
959 }; | |
960 | |
961 target = Json::arrayValue; | |
962 | |
963 Visitor visitor(*this, context.GetIndex(), target); | |
964 Execute(visitor, context); | |
821 } | 965 } |
822 | 966 |
823 | 967 |
824 bool ResourceFinder::ExecuteOneResource(Json::Value& target, | 968 bool ResourceFinder::ExecuteOneResource(Json::Value& target, |
825 ServerContext& context) const | 969 ServerContext& context) const |