comparison OrthancServer/ServerContext.cpp @ 3015:abe49ca61cd5

On C-FIND, avoid accessing the storage area whenever possible
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 14 Dec 2018 12:10:03 +0100
parents af1530b45290
children 2cbafb5d5a62
comparison
equal deleted inserted replaced
3014:b9f0b0c0b36f 3015:abe49ca61cd5
776 void ServerContext::Apply(LookupResource::IVisitor& visitor, 776 void ServerContext::Apply(LookupResource::IVisitor& visitor,
777 const ::Orthanc::LookupResource& lookup, 777 const ::Orthanc::LookupResource& lookup,
778 size_t since, 778 size_t since,
779 size_t limit) 779 size_t limit)
780 { 780 {
781 LookupMode mode;
782
783 {
784 // New configuration option in 1.5.1
785 OrthancConfiguration::ReaderLock lock;
786
787 std::string value = lock.GetConfiguration().GetStringParameter("StorageAccessOnFind", "Always");
788
789 if (value == "Always")
790 {
791 mode = LookupMode_DiskOnLookupAndAnswer;
792 }
793 else if (value == "Never")
794 {
795 mode = LookupMode_DatabaseOnly;
796 }
797 else if (value == "Answers")
798 {
799 mode = LookupMode_DiskOnAnswer;
800 }
801 else
802 {
803 throw OrthancException(ErrorCode_ParameterOutOfRange,
804 "Configuration option \"StorageAccessOnFind\" "
805 "should be \"Always\", \"Never\" or \"Answers\": " + value);
806 }
807 }
808
809
781 std::vector<std::string> resources, instances; 810 std::vector<std::string> resources, instances;
782 GetIndex().FindCandidates(resources, instances, lookup); 811 GetIndex().FindCandidates(resources, instances, lookup);
783 812
784 LOG(INFO) << "Number of candidate resources after fast DB filtering on main DICOM tags: " << resources.size(); 813 LOG(INFO) << "Number of candidate resources after fast DB filtering on main DICOM tags: " << resources.size();
785 814
786 assert(resources.size() == instances.size()); 815 assert(resources.size() == instances.size());
787 816
788 size_t countResults = 0; 817 size_t countResults = 0;
789 size_t skipped = 0; 818 size_t skipped = 0;
790 bool complete = true; 819 bool complete = true;
820
821 const bool isDicomAsJsonNeeded = visitor.IsDicomAsJsonNeeded();
791 822
792 for (size_t i = 0; i < instances.size(); i++) 823 for (size_t i = 0; i < instances.size(); i++)
793 { 824 {
794 // Optimization in Orthanc 1.5.1 - Don't read the full JSON from 825 // Optimization in Orthanc 1.5.1 - Don't read the full JSON from
795 // the disk if only "main DICOM tags" are to be returned 826 // the disk if only "main DICOM tags" are to be returned
797 std::auto_ptr<Json::Value> dicomAsJson; 828 std::auto_ptr<Json::Value> dicomAsJson;
798 829
799 bool hasOnlyMainDicomTags; 830 bool hasOnlyMainDicomTags;
800 DicomMap dicom; 831 DicomMap dicom;
801 832
802 if (lookup.HasOnlyMainDicomTags() && 833 if (mode == LookupMode_DatabaseOnly ||
803 GetIndex().GetAllMainDicomTags(dicom, instances[i])) 834 mode == LookupMode_DiskOnAnswer ||
835 lookup.HasOnlyMainDicomTags())
804 { 836 {
805 // Case (1): The main DICOM tags, as stored in the database, 837 // Case (1): The main DICOM tags, as stored in the database,
806 // are sufficient to look for match 838 // are sufficient to look for match
839
840 if (!GetIndex().GetAllMainDicomTags(dicom, instances[i]))
841 {
842 // The instance has been removed during the execution of the
843 // lookup, ignore it
844 continue;
845 }
846
807 hasOnlyMainDicomTags = true; 847 hasOnlyMainDicomTags = true;
808 } 848 }
809 else 849 else
810 { 850 {
811 // Case (2): Need to read the "DICOM-as-JSON" attachment from 851 // Case (2): Need to read the "DICOM-as-JSON" attachment from
832 complete = false; 872 complete = false;
833 break; 873 break;
834 } 874 }
835 else 875 else
836 { 876 {
837 if (dicomAsJson.get() == NULL && 877 if ((mode == LookupMode_DiskOnLookupAndAnswer ||
838 visitor.IsDicomAsJsonNeeded()) 878 mode == LookupMode_DiskOnAnswer) &&
879 dicomAsJson.get() == NULL &&
880 isDicomAsJsonNeeded)
839 { 881 {
840 dicomAsJson.reset(new Json::Value); 882 dicomAsJson.reset(new Json::Value);
841 ReadDicomAsJson(*dicomAsJson, instances[i]); 883 ReadDicomAsJson(*dicomAsJson, instances[i]);
842 } 884 }
843 885
868 910
869 LOG(INFO) << "Number of matching resources: " << countResults; 911 LOG(INFO) << "Number of matching resources: " << countResults;
870 } 912 }
871 913
872 914
915 bool ServerContext::LookupOrReconstructMetadata(std::string& target,
916 const std::string& publicId,
917 MetadataType metadata)
918 {
919 // This is a backwards-compatibility function, that can
920 // reconstruct metadata that were not generated by an older
921 // release of Orthanc
922
923 if (metadata == MetadataType_Instance_SopClassUid ||
924 metadata == MetadataType_Instance_TransferSyntax)
925 {
926 if (index_.LookupMetadata(target, publicId, metadata))
927 {
928 return true;
929 }
930 else
931 {
932 // These metadata are mandatory in DICOM instances, and were
933 // introduced in Orthanc 1.2.0. The fact that
934 // "LookupMetadata()" has failed indicates that this database
935 // comes from an older release of Orthanc.
936
937 DicomTag tag(0, 0);
938
939 switch (metadata)
940 {
941 case MetadataType_Instance_SopClassUid:
942 tag = DICOM_TAG_SOP_CLASS_UID;
943 break;
944
945 case MetadataType_Instance_TransferSyntax:
946 tag = DICOM_TAG_TRANSFER_SYNTAX_UID;
947 break;
948
949 default:
950 throw OrthancException(ErrorCode_InternalError);
951 }
952
953 Json::Value dicomAsJson;
954 ReadDicomAsJson(dicomAsJson, publicId);
955
956 DicomMap tags;
957 tags.FromDicomAsJson(dicomAsJson);
958
959 const DicomValue* value = tags.TestAndGetValue(tag);
960
961 if (value != NULL &&
962 !value->IsNull() &&
963 !value->IsBinary())
964 {
965 target = value->GetContent();
966
967 // Store for reuse
968 index_.SetMetadata(publicId, metadata, target);
969 return true;
970 }
971 else
972 {
973 // Should never happen
974 return false;
975 }
976 }
977 }
978 else
979 {
980 // No backward
981 return index_.LookupMetadata(target, publicId, metadata);
982 }
983 }
984
985
873 void ServerContext::AddChildInstances(SetOfInstancesJob& job, 986 void ServerContext::AddChildInstances(SetOfInstancesJob& job,
874 const std::string& publicId) 987 const std::string& publicId)
875 { 988 {
876 std::list<std::string> instances; 989 std::list<std::string> instances;
877 GetIndex().GetChildInstances(instances, publicId); 990 GetIndex().GetChildInstances(instances, publicId);