comparison OrthancServer/Sources/ServerIndex.cpp @ 4563:bb1c365f9e44 db-changes

end of refactoring read-only transactions
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 05 Mar 2021 16:11:11 +0100
parents e19f11e08226
children 5a0adc1c19a9
comparison
equal deleted inserted replaced
4562:e19f11e08226 4563:bb1c365f9e44
1658 } 1658 }
1659 1659
1660 1660
1661 1661
1662 1662
1663 bool ServerIndex::GetAllMainDicomTags(DicomMap& result,
1664 const std::string& instancePublicId)
1665 {
1666 result.Clear();
1667
1668 boost::mutex::scoped_lock lock(mutex_);
1669
1670 // Lookup for the requested resource
1671 int64_t instance;
1672 ResourceType type;
1673 if (!db_.LookupResource(instance, type, instancePublicId) ||
1674 type != ResourceType_Instance)
1675 {
1676 return false;
1677 }
1678 else
1679 {
1680 DicomMap tmp;
1681
1682 db_.GetMainDicomTags(tmp, instance);
1683 result.Merge(tmp);
1684
1685 int64_t series;
1686 if (!db_.LookupParent(series, instance))
1687 {
1688 throw OrthancException(ErrorCode_InternalError);
1689 }
1690
1691 tmp.Clear();
1692 db_.GetMainDicomTags(tmp, series);
1693 result.Merge(tmp);
1694
1695 int64_t study;
1696 if (!db_.LookupParent(study, series))
1697 {
1698 throw OrthancException(ErrorCode_InternalError);
1699 }
1700
1701 tmp.Clear();
1702 db_.GetMainDicomTags(tmp, study);
1703 result.Merge(tmp);
1704
1705 #ifndef NDEBUG
1706 {
1707 // Sanity test to check that all the main DICOM tags from the
1708 // patient level are copied at the study level
1709
1710 int64_t patient;
1711 if (!db_.LookupParent(patient, study))
1712 {
1713 throw OrthancException(ErrorCode_InternalError);
1714 }
1715
1716 tmp.Clear();
1717 db_.GetMainDicomTags(tmp, study);
1718
1719 std::set<DicomTag> patientTags;
1720 tmp.GetTags(patientTags);
1721
1722 for (std::set<DicomTag>::const_iterator
1723 it = patientTags.begin(); it != patientTags.end(); ++it)
1724 {
1725 assert(result.HasTag(*it));
1726 }
1727 }
1728 #endif
1729
1730 return true;
1731 }
1732 }
1733
1734
1735 bool ServerIndex::LookupResourceType(ResourceType& type,
1736 const std::string& publicId)
1737 {
1738 boost::mutex::scoped_lock lock(mutex_);
1739
1740 int64_t id;
1741 return db_.LookupResource(id, type, publicId);
1742 }
1743
1744
1745 unsigned int ServerIndex::GetDatabaseVersion()
1746 {
1747 boost::mutex::scoped_lock lock(mutex_);
1748 return db_.GetDatabaseVersion();
1749 }
1750
1751
1752 bool ServerIndex::LookupParent(std::string& target,
1753 const std::string& publicId,
1754 ResourceType parentType)
1755 {
1756 boost::mutex::scoped_lock lock(mutex_);
1757
1758 ResourceType type;
1759 int64_t id;
1760 if (!db_.LookupResource(id, type, publicId))
1761 {
1762 throw OrthancException(ErrorCode_UnknownResource);
1763 }
1764
1765 while (type != parentType)
1766 {
1767 int64_t parentId;
1768
1769 if (type == ResourceType_Patient || // Cannot further go up in hierarchy
1770 !db_.LookupParent(parentId, id))
1771 {
1772 return false;
1773 }
1774
1775 id = parentId;
1776 type = GetParentResourceType(type);
1777 }
1778
1779 target = db_.GetPublicId(id);
1780 return true;
1781 }
1782
1783
1784 void ServerIndex::ReconstructInstance(const ParsedDicomFile& dicom) 1663 void ServerIndex::ReconstructInstance(const ParsedDicomFile& dicom)
1785 { 1664 {
1786 DicomMap summary; 1665 DicomMap summary;
1787 OrthancConfiguration::DefaultExtractDicomSummary(summary, dicom); 1666 OrthancConfiguration::DefaultExtractDicomSummary(summary, dicom);
1788 1667
1874 level = ResourceType_Study; 1753 level = ResourceType_Study;
1875 } 1754 }
1876 1755
1877 target.push_back(source.GetConstraint(i).ConvertToDatabaseConstraint(level, type)); 1756 target.push_back(source.GetConstraint(i).ConvertToDatabaseConstraint(level, type));
1878 } 1757 }
1879 }
1880 }
1881
1882
1883 void ServerIndex::ApplyLookupResources(std::vector<std::string>& resourcesId,
1884 std::vector<std::string>* instancesId,
1885 const DatabaseLookup& lookup,
1886 ResourceType queryLevel,
1887 size_t limit)
1888 {
1889 std::vector<DatabaseConstraint> normalized;
1890 NormalizeLookup(normalized, lookup, queryLevel);
1891
1892 std::list<std::string> resourcesList, instancesList;
1893
1894 {
1895 boost::mutex::scoped_lock lock(mutex_);
1896
1897 if (instancesId == NULL)
1898 {
1899 db_.ApplyLookupResources(resourcesList, NULL, normalized, queryLevel, limit);
1900 }
1901 else
1902 {
1903 db_.ApplyLookupResources(resourcesList, &instancesList, normalized, queryLevel, limit);
1904 }
1905 }
1906
1907 CopyListToVector(resourcesId, resourcesList);
1908
1909 if (instancesId != NULL)
1910 {
1911 CopyListToVector(*instancesId, instancesList);
1912 } 1758 }
1913 } 1759 }
1914 1760
1915 1761
1916 1762
3063 { 2909 {
3064 } 2910 }
3065 2911
3066 virtual void Apply(ReadOnlyTransaction& transaction) ORTHANC_OVERRIDE 2912 virtual void Apply(ReadOnlyTransaction& transaction) ORTHANC_OVERRIDE
3067 { 2913 {
2914 // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
3068 std::list<std::string> tmp; 2915 std::list<std::string> tmp;
3069 transaction.ApplyLookupResources(tmp, NULL, query_, level_, 0); 2916 transaction.ApplyLookupResources(tmp, NULL, query_, level_, 0);
3070 CopyListToVector(result_, tmp); 2917 CopyListToVector(result_, tmp);
3071 } 2918 }
3072 }; 2919 };
3083 { 2930 {
3084 public: 2931 public:
3085 virtual void ApplyTuple(ReadOnlyTransaction& transaction, 2932 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3086 const Tuple& tuple) ORTHANC_OVERRIDE 2933 const Tuple& tuple) ORTHANC_OVERRIDE
3087 { 2934 {
2935 // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
3088 *tuple.get<0>() = transaction.LookupGlobalProperty(*tuple.get<1>(), tuple.get<2>()); 2936 *tuple.get<0>() = transaction.LookupGlobalProperty(*tuple.get<1>(), tuple.get<2>());
3089 } 2937 }
3090 }; 2938 };
3091 2939
3092 bool found; 2940 bool found;
3097 2945
3098 2946
3099 std::string ServerIndex::GetGlobalProperty(GlobalProperty property, 2947 std::string ServerIndex::GetGlobalProperty(GlobalProperty property,
3100 const std::string& defaultValue) 2948 const std::string& defaultValue)
3101 { 2949 {
3102 class Operations : public ReadOnlyOperationsT3<std::string*, GlobalProperty, std::string>
3103 {
3104 public:
3105 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3106 const Tuple& tuple) ORTHANC_OVERRIDE
3107 {
3108 if (!transaction.LookupGlobalProperty(*tuple.get<0>(), tuple.get<1>()))
3109 {
3110 *tuple.get<0>() = tuple.get<2>(); // Default value
3111 }
3112 }
3113 };
3114
3115 std::string s; 2950 std::string s;
3116 Operations operations; 2951 if (LookupGlobalProperty(s, property))
3117 operations.Apply(*this, &s, property, defaultValue); 2952 {
3118 return s; 2953 return s;
2954 }
2955 else
2956 {
2957 return defaultValue;
2958 }
3119 } 2959 }
3120 2960
3121 2961
3122 bool ServerIndex::GetMainDicomTags(DicomMap& result, 2962 bool ServerIndex::GetMainDicomTags(DicomMap& result,
3123 const std::string& publicId, 2963 const std::string& publicId,
3183 bool found; 3023 bool found;
3184 Operations operations; 3024 Operations operations;
3185 operations.Apply(*this, &found, &result, publicId, expectedType, levelOfInterest); 3025 operations.Apply(*this, &found, &result, publicId, expectedType, levelOfInterest);
3186 return found; 3026 return found;
3187 } 3027 }
3028
3029
3030 bool ServerIndex::GetAllMainDicomTags(DicomMap& result,
3031 const std::string& instancePublicId)
3032 {
3033 class Operations : public ReadOnlyOperationsT3<bool*, DicomMap*, std::string>
3034 {
3035 public:
3036 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3037 const Tuple& tuple) ORTHANC_OVERRIDE
3038 {
3039 // Lookup for the requested resource
3040 int64_t instance;
3041 ResourceType type;
3042 if (!transaction.LookupResource(instance, type, tuple.get<2>()) ||
3043 type != ResourceType_Instance)
3044 {
3045 *tuple.get<0>() = false;
3046 }
3047 else
3048 {
3049 DicomMap tmp;
3050
3051 transaction.GetMainDicomTags(tmp, instance);
3052 tuple.get<1>()->Merge(tmp);
3053
3054 int64_t series;
3055 if (!transaction.LookupParent(series, instance))
3056 {
3057 throw OrthancException(ErrorCode_InternalError);
3058 }
3059
3060 tmp.Clear();
3061 transaction.GetMainDicomTags(tmp, series);
3062 tuple.get<1>()->Merge(tmp);
3063
3064 int64_t study;
3065 if (!transaction.LookupParent(study, series))
3066 {
3067 throw OrthancException(ErrorCode_InternalError);
3068 }
3069
3070 tmp.Clear();
3071 transaction.GetMainDicomTags(tmp, study);
3072 tuple.get<1>()->Merge(tmp);
3073
3074 #ifndef NDEBUG
3075 {
3076 // Sanity test to check that all the main DICOM tags from the
3077 // patient level are copied at the study level
3078
3079 int64_t patient;
3080 if (!transaction.LookupParent(patient, study))
3081 {
3082 throw OrthancException(ErrorCode_InternalError);
3083 }
3084
3085 tmp.Clear();
3086 transaction.GetMainDicomTags(tmp, study);
3087
3088 std::set<DicomTag> patientTags;
3089 tmp.GetTags(patientTags);
3090
3091 for (std::set<DicomTag>::const_iterator
3092 it = patientTags.begin(); it != patientTags.end(); ++it)
3093 {
3094 assert(tuple.get<1>()->HasTag(*it));
3095 }
3096 }
3097 #endif
3098
3099 *tuple.get<0>() = true;
3100 }
3101 }
3102 };
3103
3104 result.Clear();
3105
3106 bool found;
3107 Operations operations;
3108 operations.Apply(*this, &found, &result, instancePublicId);
3109 return found;
3110 }
3111
3112
3113 bool ServerIndex::LookupResourceType(ResourceType& type,
3114 const std::string& publicId)
3115 {
3116 class Operations : public ReadOnlyOperationsT3<bool*, ResourceType*, std::string>
3117 {
3118 public:
3119 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3120 const Tuple& tuple) ORTHANC_OVERRIDE
3121 {
3122 // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
3123 int64_t id;
3124 *tuple.get<0>() = transaction.LookupResource(id, *tuple.get<1>(), tuple.get<2>());
3125 }
3126 };
3127
3128 bool found;
3129 Operations operations;
3130 operations.Apply(*this, &found, &type, publicId);
3131 return found;
3132 }
3133
3134
3135 unsigned int ServerIndex::GetDatabaseVersion()
3136 {
3137 class Operations : public ReadOnlyOperationsT1<unsigned int *>
3138 {
3139 public:
3140 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3141 const Tuple& tuple) ORTHANC_OVERRIDE
3142 {
3143 // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
3144 *tuple.get<0>() = transaction.GetDatabaseVersion();
3145 }
3146 };
3147
3148 unsigned int version;
3149 Operations operations;
3150 operations.Apply(*this, &version);
3151 return version;
3152 }
3153
3154
3155 bool ServerIndex::LookupParent(std::string& target,
3156 const std::string& publicId,
3157 ResourceType parentType)
3158 {
3159 class Operations : public ReadOnlyOperationsT4<bool*, std::string*, std::string, ResourceType>
3160 {
3161 public:
3162 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3163 const Tuple& tuple) ORTHANC_OVERRIDE
3164 {
3165 ResourceType type;
3166 int64_t id;
3167 if (!transaction.LookupResource(id, type, tuple.get<2>()))
3168 {
3169 throw OrthancException(ErrorCode_UnknownResource);
3170 }
3171
3172 while (type != tuple.get<3>())
3173 {
3174 int64_t parentId;
3175
3176 if (type == ResourceType_Patient || // Cannot further go up in hierarchy
3177 !transaction.LookupParent(parentId, id))
3178 {
3179 *tuple.get<0>() = false;
3180 return;
3181 }
3182
3183 id = parentId;
3184 type = GetParentResourceType(type);
3185 }
3186
3187 *tuple.get<0>() = true;
3188 *tuple.get<1>() = transaction.GetPublicId(id);
3189 }
3190 };
3191
3192 bool found;
3193 Operations operations;
3194 operations.Apply(*this, &found, &target, publicId, parentType);
3195 return found;
3196 }
3197
3198
3199 void ServerIndex::ApplyLookupResources(std::vector<std::string>& resourcesId,
3200 std::vector<std::string>* instancesId,
3201 const DatabaseLookup& lookup,
3202 ResourceType queryLevel,
3203 size_t limit)
3204 {
3205 class Operations : public ReadOnlyOperationsT4<bool, std::vector<DatabaseConstraint>, ResourceType, size_t>
3206 {
3207 private:
3208 std::list<std::string> resourcesList_;
3209 std::list<std::string> instancesList_;
3210
3211 public:
3212 const std::list<std::string>& GetResourcesList() const
3213 {
3214 return resourcesList_;
3215 }
3216
3217 const std::list<std::string>& GetInstancesList() const
3218 {
3219 return instancesList_;
3220 }
3221
3222 virtual void ApplyTuple(ReadOnlyTransaction& transaction,
3223 const Tuple& tuple) ORTHANC_OVERRIDE
3224 {
3225 // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
3226 if (tuple.get<0>())
3227 {
3228 transaction.ApplyLookupResources(resourcesList_, &instancesList_, tuple.get<1>(), tuple.get<2>(), tuple.get<3>());
3229 }
3230 else
3231 {
3232 transaction.ApplyLookupResources(resourcesList_, NULL, tuple.get<1>(), tuple.get<2>(), tuple.get<3>());
3233 }
3234 }
3235 };
3236
3237
3238 std::vector<DatabaseConstraint> normalized;
3239 NormalizeLookup(normalized, lookup, queryLevel);
3240
3241 Operations operations;
3242 operations.Apply(*this, (instancesId != NULL), normalized, queryLevel, limit);
3243
3244 CopyListToVector(resourcesId, operations.GetResourcesList());
3245
3246 if (instancesId != NULL)
3247 {
3248 CopyListToVector(*instancesId, operations.GetInstancesList());
3249 }
3250 }
3188 } 3251 }