Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerIndex.cpp @ 4562:e19f11e08226 db-changes
cont
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 05 Mar 2021 15:37:53 +0100 |
parents | 02510325d869 |
children | bb1c365f9e44 |
comparison
equal
deleted
inserted
replaced
4561:02510325d869 | 4562:e19f11e08226 |
---|---|
1488 db_.ClearExportedResources(); | 1488 db_.ClearExportedResources(); |
1489 transaction.Commit(0); | 1489 transaction.Commit(0); |
1490 } | 1490 } |
1491 | 1491 |
1492 | 1492 |
1493 void ServerIndex::GetResourceStatistics(/* out */ ResourceType& type, | |
1494 /* out */ uint64_t& diskSize, | |
1495 /* out */ uint64_t& uncompressedSize, | |
1496 /* out */ unsigned int& countStudies, | |
1497 /* out */ unsigned int& countSeries, | |
1498 /* out */ unsigned int& countInstances, | |
1499 /* out */ uint64_t& dicomDiskSize, | |
1500 /* out */ uint64_t& dicomUncompressedSize, | |
1501 const std::string& publicId) | |
1502 { | |
1503 boost::mutex::scoped_lock lock(mutex_); | |
1504 | |
1505 int64_t top; | |
1506 if (!db_.LookupResource(top, type, publicId)) | |
1507 { | |
1508 throw OrthancException(ErrorCode_UnknownResource); | |
1509 } | |
1510 | |
1511 std::stack<int64_t> toExplore; | |
1512 toExplore.push(top); | |
1513 | |
1514 countInstances = 0; | |
1515 countSeries = 0; | |
1516 countStudies = 0; | |
1517 diskSize = 0; | |
1518 uncompressedSize = 0; | |
1519 dicomDiskSize = 0; | |
1520 dicomUncompressedSize = 0; | |
1521 | |
1522 while (!toExplore.empty()) | |
1523 { | |
1524 // Get the internal ID of the current resource | |
1525 int64_t resource = toExplore.top(); | |
1526 toExplore.pop(); | |
1527 | |
1528 ResourceType thisType = db_.GetResourceType(resource); | |
1529 | |
1530 std::set<FileContentType> f; | |
1531 db_.ListAvailableAttachments(f, resource); | |
1532 | |
1533 for (std::set<FileContentType>::const_iterator | |
1534 it = f.begin(); it != f.end(); ++it) | |
1535 { | |
1536 FileInfo attachment; | |
1537 if (db_.LookupAttachment(attachment, resource, *it)) | |
1538 { | |
1539 if (attachment.GetContentType() == FileContentType_Dicom) | |
1540 { | |
1541 dicomDiskSize += attachment.GetCompressedSize(); | |
1542 dicomUncompressedSize += attachment.GetUncompressedSize(); | |
1543 } | |
1544 | |
1545 diskSize += attachment.GetCompressedSize(); | |
1546 uncompressedSize += attachment.GetUncompressedSize(); | |
1547 } | |
1548 } | |
1549 | |
1550 if (thisType == ResourceType_Instance) | |
1551 { | |
1552 countInstances++; | |
1553 } | |
1554 else | |
1555 { | |
1556 switch (thisType) | |
1557 { | |
1558 case ResourceType_Study: | |
1559 countStudies++; | |
1560 break; | |
1561 | |
1562 case ResourceType_Series: | |
1563 countSeries++; | |
1564 break; | |
1565 | |
1566 default: | |
1567 break; | |
1568 } | |
1569 | |
1570 // Tag all the children of this resource as to be explored | |
1571 std::list<int64_t> tmp; | |
1572 db_.GetChildrenInternalId(tmp, resource); | |
1573 for (std::list<int64_t>::const_iterator | |
1574 it = tmp.begin(); it != tmp.end(); ++it) | |
1575 { | |
1576 toExplore.push(*it); | |
1577 } | |
1578 } | |
1579 } | |
1580 | |
1581 if (countStudies == 0) | |
1582 { | |
1583 countStudies = 1; | |
1584 } | |
1585 | |
1586 if (countSeries == 0) | |
1587 { | |
1588 countSeries = 1; | |
1589 } | |
1590 } | |
1591 | |
1592 | |
1593 void ServerIndex::UnstableResourcesMonitorThread(ServerIndex* that, | 1493 void ServerIndex::UnstableResourcesMonitorThread(ServerIndex* that, |
1594 unsigned int threadSleep) | 1494 unsigned int threadSleep) |
1595 { | 1495 { |
1596 int stableAge; | 1496 int stableAge; |
1597 | 1497 |
1670 LogChange(id, ChangeType_NewChildInstance, type, publicId); | 1570 LogChange(id, ChangeType_NewChildInstance, type, publicId); |
1671 } | 1571 } |
1672 | 1572 |
1673 | 1573 |
1674 | 1574 |
1675 void ServerIndex::LookupIdentifierExact(std::vector<std::string>& result, | |
1676 ResourceType level, | |
1677 const DicomTag& tag, | |
1678 const std::string& value) | |
1679 { | |
1680 assert((level == ResourceType_Patient && tag == DICOM_TAG_PATIENT_ID) || | |
1681 (level == ResourceType_Study && tag == DICOM_TAG_STUDY_INSTANCE_UID) || | |
1682 (level == ResourceType_Study && tag == DICOM_TAG_ACCESSION_NUMBER) || | |
1683 (level == ResourceType_Series && tag == DICOM_TAG_SERIES_INSTANCE_UID) || | |
1684 (level == ResourceType_Instance && tag == DICOM_TAG_SOP_INSTANCE_UID)); | |
1685 | |
1686 result.clear(); | |
1687 | |
1688 DicomTagConstraint c(tag, ConstraintType_Equal, value, true, true); | |
1689 | |
1690 std::vector<DatabaseConstraint> query; | |
1691 query.push_back(c.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); | |
1692 | |
1693 std::list<std::string> tmp; | |
1694 | |
1695 { | |
1696 boost::mutex::scoped_lock lock(mutex_); | |
1697 db_.ApplyLookupResources(tmp, NULL, query, level, 0); | |
1698 } | |
1699 | |
1700 CopyListToVector(result, tmp); | |
1701 } | |
1702 | |
1703 | |
1704 StoreStatus ServerIndex::AddAttachment(const FileInfo& attachment, | 1575 StoreStatus ServerIndex::AddAttachment(const FileInfo& attachment, |
1705 const std::string& publicId) | 1576 const std::string& publicId) |
1706 { | 1577 { |
1707 boost::mutex::scoped_lock lock(mutex_); | 1578 boost::mutex::scoped_lock lock(mutex_); |
1708 | 1579 |
1785 db_.SetGlobalProperty(property, value); | 1656 db_.SetGlobalProperty(property, value); |
1786 transaction.Commit(0); | 1657 transaction.Commit(0); |
1787 } | 1658 } |
1788 | 1659 |
1789 | 1660 |
1790 bool ServerIndex::LookupGlobalProperty(std::string& value, | |
1791 GlobalProperty property) | |
1792 { | |
1793 boost::mutex::scoped_lock lock(mutex_); | |
1794 return db_.LookupGlobalProperty(value, property); | |
1795 } | |
1796 | |
1797 | |
1798 std::string ServerIndex::GetGlobalProperty(GlobalProperty property, | |
1799 const std::string& defaultValue) | |
1800 { | |
1801 std::string value; | |
1802 | |
1803 if (LookupGlobalProperty(value, property)) | |
1804 { | |
1805 return value; | |
1806 } | |
1807 else | |
1808 { | |
1809 return defaultValue; | |
1810 } | |
1811 } | |
1812 | |
1813 | |
1814 bool ServerIndex::GetMainDicomTags(DicomMap& result, | |
1815 const std::string& publicId, | |
1816 ResourceType expectedType, | |
1817 ResourceType levelOfInterest) | |
1818 { | |
1819 // Yes, the following test could be shortened, but we wish to make it as clear as possible | |
1820 if (!(expectedType == ResourceType_Patient && levelOfInterest == ResourceType_Patient) && | |
1821 !(expectedType == ResourceType_Study && levelOfInterest == ResourceType_Patient) && | |
1822 !(expectedType == ResourceType_Study && levelOfInterest == ResourceType_Study) && | |
1823 !(expectedType == ResourceType_Series && levelOfInterest == ResourceType_Series) && | |
1824 !(expectedType == ResourceType_Instance && levelOfInterest == ResourceType_Instance)) | |
1825 { | |
1826 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
1827 } | |
1828 | |
1829 result.Clear(); | |
1830 | |
1831 boost::mutex::scoped_lock lock(mutex_); | |
1832 | |
1833 // Lookup for the requested resource | |
1834 int64_t id; | |
1835 ResourceType type; | |
1836 if (!db_.LookupResource(id, type, publicId) || | |
1837 type != expectedType) | |
1838 { | |
1839 return false; | |
1840 } | |
1841 | |
1842 if (type == ResourceType_Study) | |
1843 { | |
1844 DicomMap tmp; | |
1845 db_.GetMainDicomTags(tmp, id); | |
1846 | |
1847 switch (levelOfInterest) | |
1848 { | |
1849 case ResourceType_Patient: | |
1850 tmp.ExtractPatientInformation(result); | |
1851 return true; | |
1852 | |
1853 case ResourceType_Study: | |
1854 tmp.ExtractStudyInformation(result); | |
1855 return true; | |
1856 | |
1857 default: | |
1858 throw OrthancException(ErrorCode_InternalError); | |
1859 } | |
1860 } | |
1861 else | |
1862 { | |
1863 db_.GetMainDicomTags(result, id); | |
1864 return true; | |
1865 } | |
1866 } | |
1867 | 1661 |
1868 | 1662 |
1869 bool ServerIndex::GetAllMainDicomTags(DicomMap& result, | 1663 bool ServerIndex::GetAllMainDicomTags(DicomMap& result, |
1870 const std::string& instancePublicId) | 1664 const std::string& instancePublicId) |
1871 { | 1665 { |
2344 | 2138 |
2345 Transaction transaction(*this); // TODO - Only if "TransactionType_SingleStatement" | 2139 Transaction transaction(*this); // TODO - Only if "TransactionType_SingleStatement" |
2346 | 2140 |
2347 if (readOperations != NULL) | 2141 if (readOperations != NULL) |
2348 { | 2142 { |
2349 ReadOnlyTransaction transaction(db_); | 2143 ReadOnlyTransaction t(db_); |
2350 readOperations->Apply(transaction); | 2144 readOperations->Apply(t); |
2351 } | 2145 } |
2352 else | 2146 else |
2353 { | 2147 { |
2354 assert(writeOperations != NULL); | 2148 assert(writeOperations != NULL); |
2355 ReadWriteTransaction transaction(db_); | 2149 ReadWriteTransaction t(db_); |
2356 writeOperations->Apply(transaction); | 2150 writeOperations->Apply(t); |
2357 } | 2151 } |
2358 | 2152 |
2359 transaction.Commit(0); | 2153 transaction.Commit(0); |
2360 | 2154 |
2361 return; // Success | 2155 return; // Success |
2409 | 2203 |
2410 bool ServerIndex::ExpandResource(Json::Value& target, | 2204 bool ServerIndex::ExpandResource(Json::Value& target, |
2411 const std::string& publicId, | 2205 const std::string& publicId, |
2412 ResourceType level) | 2206 ResourceType level) |
2413 { | 2207 { |
2414 class Operations : public ReadOnlyOperationsT3<Json::Value*, std::string, ResourceType> | 2208 class Operations : public ReadOnlyOperationsT4<bool*, Json::Value*, std::string, ResourceType> |
2415 { | 2209 { |
2416 private: | 2210 private: |
2417 ServerIndex& index_; | 2211 ServerIndex& index_; |
2418 bool found_; | |
2419 | 2212 |
2420 public: | 2213 public: |
2421 Operations(ServerIndex& index) : | 2214 explicit Operations(ServerIndex& index) : |
2422 index_(index), | 2215 index_(index) |
2423 found_(false) | |
2424 { | 2216 { |
2425 } | 2217 } |
2426 | 2218 |
2427 bool HasFound() const | |
2428 { | |
2429 return found_; | |
2430 } | |
2431 | |
2432 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 2219 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
2433 const Tuple& tuple) ORTHANC_OVERRIDE | 2220 const Tuple& tuple) ORTHANC_OVERRIDE |
2434 { | 2221 { |
2435 Json::Value& target = *tuple.get<0>(); | |
2436 | |
2437 // Lookup for the requested resource | 2222 // Lookup for the requested resource |
2438 int64_t internalId; // unused | 2223 int64_t internalId; // unused |
2439 ResourceType type; | 2224 ResourceType type; |
2440 std::string parent; | 2225 std::string parent; |
2441 if (!transaction.LookupResourceAndParent(internalId, type, parent, tuple.get<1>()) || | 2226 if (!transaction.LookupResourceAndParent(internalId, type, parent, tuple.get<2>()) || |
2442 type != tuple.get<2>()) | 2227 type != tuple.get<3>()) |
2443 { | 2228 { |
2444 found_ = false; | 2229 *tuple.get<0>() = false; |
2445 } | 2230 } |
2446 else | 2231 else |
2447 { | 2232 { |
2233 Json::Value& target = *tuple.get<1>(); | |
2448 target = Json::objectValue; | 2234 target = Json::objectValue; |
2449 | 2235 |
2450 // Set information about the parent resource (if it exists) | 2236 // Set information about the parent resource (if it exists) |
2451 if (type == ResourceType_Patient) | 2237 if (type == ResourceType_Patient) |
2452 { | 2238 { |
2577 default: | 2363 default: |
2578 throw OrthancException(ErrorCode_InternalError); | 2364 throw OrthancException(ErrorCode_InternalError); |
2579 } | 2365 } |
2580 | 2366 |
2581 // Record the remaining information | 2367 // Record the remaining information |
2582 target["ID"] = tuple.get<1>(); | 2368 target["ID"] = tuple.get<2>(); |
2583 transaction.MainDicomTagsToJson(target, internalId, type); | 2369 transaction.MainDicomTagsToJson(target, internalId, type); |
2584 | 2370 |
2585 std::string tmp; | 2371 std::string tmp; |
2586 | 2372 |
2587 if (LookupStringMetadata(tmp, metadata, MetadataType_AnonymizedFrom)) | 2373 if (LookupStringMetadata(tmp, metadata, MetadataType_AnonymizedFrom)) |
2604 { | 2390 { |
2605 target["LastUpdate"] = tmp; | 2391 target["LastUpdate"] = tmp; |
2606 } | 2392 } |
2607 } | 2393 } |
2608 | 2394 |
2609 found_ = true; | 2395 *tuple.get<0>() = true; |
2610 } | 2396 } |
2611 } | 2397 } |
2612 }; | 2398 }; |
2613 | 2399 |
2400 bool found; | |
2614 Operations operations(*this); | 2401 Operations operations(*this); |
2615 operations.Apply(*this, &target, publicId, level); | 2402 operations.Apply(*this, &found, &target, publicId, level); |
2616 return operations.HasFound(); | 2403 return found; |
2617 } | 2404 } |
2618 | 2405 |
2619 | 2406 |
2620 void ServerIndex::GetAllMetadata(std::map<MetadataType, std::string>& target, | 2407 void ServerIndex::GetAllMetadata(std::map<MetadataType, std::string>& target, |
2621 const std::string& publicId, | 2408 const std::string& publicId, |
2648 | 2435 |
2649 bool ServerIndex::LookupAttachment(FileInfo& attachment, | 2436 bool ServerIndex::LookupAttachment(FileInfo& attachment, |
2650 const std::string& instancePublicId, | 2437 const std::string& instancePublicId, |
2651 FileContentType contentType) | 2438 FileContentType contentType) |
2652 { | 2439 { |
2653 class Operations : public ReadOnlyOperationsT3<FileInfo*, std::string, FileContentType> | 2440 class Operations : public ReadOnlyOperationsT4<bool*, FileInfo*, std::string, FileContentType> |
2654 { | 2441 { |
2655 private: | |
2656 bool found_; | |
2657 | |
2658 public: | 2442 public: |
2659 Operations() : | |
2660 found_(false) | |
2661 { | |
2662 } | |
2663 | |
2664 bool HasFound() const | |
2665 { | |
2666 return found_; | |
2667 } | |
2668 | |
2669 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 2443 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
2670 const Tuple& tuple) ORTHANC_OVERRIDE | 2444 const Tuple& tuple) ORTHANC_OVERRIDE |
2671 { | 2445 { |
2672 int64_t internalId; | 2446 int64_t internalId; |
2673 ResourceType type; | 2447 ResourceType type; |
2674 if (!transaction.LookupResource(internalId, type, tuple.get<1>())) | 2448 if (!transaction.LookupResource(internalId, type, tuple.get<2>())) |
2675 { | 2449 { |
2676 throw OrthancException(ErrorCode_UnknownResource); | 2450 throw OrthancException(ErrorCode_UnknownResource); |
2677 } | 2451 } |
2678 else if (transaction.LookupAttachment(*tuple.get<0>(), internalId, tuple.get<2>())) | 2452 else if (transaction.LookupAttachment(*tuple.get<1>(), internalId, tuple.get<3>())) |
2679 { | 2453 { |
2680 assert(tuple.get<0>()->GetContentType() == tuple.get<2>()); | 2454 assert(tuple.get<1>()->GetContentType() == tuple.get<3>()); |
2681 found_ = true; | 2455 *tuple.get<0>() = true; |
2682 } | 2456 } |
2683 else | 2457 else |
2684 { | 2458 { |
2685 found_ = false; | 2459 *tuple.get<0>() = false; |
2686 } | 2460 } |
2687 } | 2461 } |
2688 }; | 2462 }; |
2689 | 2463 |
2464 bool found; | |
2690 Operations operations; | 2465 Operations operations; |
2691 operations.Apply(*this, &attachment, instancePublicId, contentType); | 2466 operations.Apply(*this, &found, &attachment, instancePublicId, contentType); |
2692 return operations.HasFound(); | 2467 return found; |
2693 } | 2468 } |
2694 | 2469 |
2695 | 2470 |
2696 void ServerIndex::GetAllUuids(std::list<std::string>& target, | 2471 void ServerIndex::GetAllUuids(std::list<std::string>& target, |
2697 ResourceType resourceType) | 2472 ResourceType resourceType) |
2878 } | 2653 } |
2879 | 2654 |
2880 | 2655 |
2881 bool ServerIndex::IsProtectedPatient(const std::string& publicId) | 2656 bool ServerIndex::IsProtectedPatient(const std::string& publicId) |
2882 { | 2657 { |
2883 class Operations : public ReadOnlyOperationsT1<std::string> | 2658 class Operations : public ReadOnlyOperationsT2<bool*, std::string> |
2884 { | 2659 { |
2885 private: | |
2886 bool protected_; | |
2887 | |
2888 public: | 2660 public: |
2889 Operations() : | |
2890 protected_(false) | |
2891 { | |
2892 } | |
2893 | |
2894 bool IsProtected() const | |
2895 { | |
2896 return protected_; | |
2897 } | |
2898 | |
2899 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 2661 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
2900 const Tuple& tuple) ORTHANC_OVERRIDE | 2662 const Tuple& tuple) ORTHANC_OVERRIDE |
2901 { | 2663 { |
2902 // Lookup for the requested resource | 2664 // Lookup for the requested resource |
2903 int64_t id; | 2665 int64_t id; |
2904 ResourceType type; | 2666 ResourceType type; |
2905 if (!transaction.LookupResource(id, type, tuple.get<0>()) || | 2667 if (!transaction.LookupResource(id, type, tuple.get<1>()) || |
2906 type != ResourceType_Patient) | 2668 type != ResourceType_Patient) |
2907 { | 2669 { |
2908 throw OrthancException(ErrorCode_ParameterOutOfRange); | 2670 throw OrthancException(ErrorCode_ParameterOutOfRange); |
2909 } | 2671 } |
2910 else | 2672 else |
2911 { | 2673 { |
2912 protected_ = transaction.IsProtectedPatient(id); | 2674 *tuple.get<0>() = transaction.IsProtectedPatient(id); |
2913 } | 2675 } |
2914 } | 2676 } |
2915 }; | 2677 }; |
2916 | 2678 |
2679 bool isProtected; | |
2917 Operations operations; | 2680 Operations operations; |
2918 operations.Apply(*this, publicId); | 2681 operations.Apply(*this, &isProtected, publicId); |
2919 return operations.IsProtected(); | 2682 return isProtected; |
2920 } | 2683 } |
2921 | 2684 |
2922 | 2685 |
2923 void ServerIndex::GetChildren(std::list<std::string>& result, | 2686 void ServerIndex::GetChildren(std::list<std::string>& result, |
2924 const std::string& publicId) | 2687 const std::string& publicId) |
3025 bool ServerIndex::LookupMetadata(std::string& target, | 2788 bool ServerIndex::LookupMetadata(std::string& target, |
3026 const std::string& publicId, | 2789 const std::string& publicId, |
3027 ResourceType expectedType, | 2790 ResourceType expectedType, |
3028 MetadataType type) | 2791 MetadataType type) |
3029 { | 2792 { |
3030 class Operations : public ReadOnlyOperationsT4<std::string*, std::string, ResourceType, MetadataType> | 2793 class Operations : public ReadOnlyOperationsT5<bool*, std::string*, std::string, ResourceType, MetadataType> |
3031 { | 2794 { |
3032 private: | |
3033 bool found_; | |
3034 | |
3035 public: | 2795 public: |
3036 Operations() : | |
3037 found_(false) | |
3038 { | |
3039 } | |
3040 | |
3041 bool HasFound() | |
3042 { | |
3043 return found_; | |
3044 } | |
3045 | |
3046 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 2796 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
3047 const Tuple& tuple) ORTHANC_OVERRIDE | 2797 const Tuple& tuple) ORTHANC_OVERRIDE |
3048 { | 2798 { |
3049 ResourceType rtype; | 2799 ResourceType rtype; |
3050 int64_t id; | 2800 int64_t id; |
3051 if (!transaction.LookupResource(id, rtype, tuple.get<1>()) || | 2801 if (!transaction.LookupResource(id, rtype, tuple.get<2>()) || |
3052 rtype != tuple.get<2>()) | 2802 rtype != tuple.get<3>()) |
3053 { | 2803 { |
3054 throw OrthancException(ErrorCode_UnknownResource); | 2804 throw OrthancException(ErrorCode_UnknownResource); |
3055 } | 2805 } |
3056 else | 2806 else |
3057 { | 2807 { |
3058 found_ = transaction.LookupMetadata(*tuple.get<0>(), id, tuple.get<3>()); | 2808 *tuple.get<0>() = transaction.LookupMetadata(*tuple.get<1>(), id, tuple.get<4>()); |
3059 } | 2809 } |
3060 } | 2810 } |
3061 }; | 2811 }; |
3062 | 2812 |
2813 bool found; | |
3063 Operations operations; | 2814 Operations operations; |
3064 operations.Apply(*this, &target, publicId, expectedType, type); | 2815 operations.Apply(*this, &found, &target, publicId, expectedType, type); |
3065 return operations.HasFound(); | 2816 return found; |
3066 } | 2817 } |
3067 | 2818 |
3068 | 2819 |
3069 void ServerIndex::ListAvailableAttachments(std::set<FileContentType>& target, | 2820 void ServerIndex::ListAvailableAttachments(std::set<FileContentType>& target, |
3070 const std::string& publicId, | 2821 const std::string& publicId, |
3096 | 2847 |
3097 | 2848 |
3098 bool ServerIndex::LookupParent(std::string& target, | 2849 bool ServerIndex::LookupParent(std::string& target, |
3099 const std::string& publicId) | 2850 const std::string& publicId) |
3100 { | 2851 { |
3101 class Operations : public ReadOnlyOperationsT2<std::string*, std::string> | 2852 class Operations : public ReadOnlyOperationsT3<bool*, std::string*, std::string> |
2853 { | |
2854 public: | |
2855 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | |
2856 const Tuple& tuple) ORTHANC_OVERRIDE | |
2857 { | |
2858 ResourceType type; | |
2859 int64_t id; | |
2860 if (!transaction.LookupResource(id, type, tuple.get<2>())) | |
2861 { | |
2862 throw OrthancException(ErrorCode_UnknownResource); | |
2863 } | |
2864 else | |
2865 { | |
2866 int64_t parentId; | |
2867 if (transaction.LookupParent(parentId, id)) | |
2868 { | |
2869 *tuple.get<1>() = transaction.GetPublicId(parentId); | |
2870 *tuple.get<0>() = true; | |
2871 } | |
2872 else | |
2873 { | |
2874 *tuple.get<0>() = false; | |
2875 } | |
2876 } | |
2877 } | |
2878 }; | |
2879 | |
2880 bool found; | |
2881 Operations operations; | |
2882 operations.Apply(*this, &found, &target, publicId); | |
2883 return found; | |
2884 } | |
2885 | |
2886 | |
2887 void ServerIndex::GetResourceStatistics(/* out */ ResourceType& type, | |
2888 /* out */ uint64_t& diskSize, | |
2889 /* out */ uint64_t& uncompressedSize, | |
2890 /* out */ unsigned int& countStudies, | |
2891 /* out */ unsigned int& countSeries, | |
2892 /* out */ unsigned int& countInstances, | |
2893 /* out */ uint64_t& dicomDiskSize, | |
2894 /* out */ uint64_t& dicomUncompressedSize, | |
2895 const std::string& publicId) | |
2896 { | |
2897 class Operations : public ServerIndex::IReadOnlyOperations | |
3102 { | 2898 { |
3103 private: | 2899 private: |
3104 bool found_; | 2900 ResourceType& type_; |
2901 uint64_t& diskSize_; | |
2902 uint64_t& uncompressedSize_; | |
2903 unsigned int& countStudies_; | |
2904 unsigned int& countSeries_; | |
2905 unsigned int& countInstances_; | |
2906 uint64_t& dicomDiskSize_; | |
2907 uint64_t& dicomUncompressedSize_; | |
2908 const std::string& publicId_; | |
2909 | |
2910 public: | |
2911 explicit Operations(ResourceType& type, | |
2912 uint64_t& diskSize, | |
2913 uint64_t& uncompressedSize, | |
2914 unsigned int& countStudies, | |
2915 unsigned int& countSeries, | |
2916 unsigned int& countInstances, | |
2917 uint64_t& dicomDiskSize, | |
2918 uint64_t& dicomUncompressedSize, | |
2919 const std::string& publicId) : | |
2920 type_(type), | |
2921 diskSize_(diskSize), | |
2922 uncompressedSize_(uncompressedSize), | |
2923 countStudies_(countStudies), | |
2924 countSeries_(countSeries), | |
2925 countInstances_(countInstances), | |
2926 dicomDiskSize_(dicomDiskSize), | |
2927 dicomUncompressedSize_(dicomUncompressedSize), | |
2928 publicId_(publicId) | |
2929 { | |
2930 } | |
2931 | |
2932 virtual void Apply(ServerIndex::ReadOnlyTransaction& transaction) ORTHANC_OVERRIDE | |
2933 { | |
2934 int64_t top; | |
2935 if (!transaction.LookupResource(top, type_, publicId_)) | |
2936 { | |
2937 throw OrthancException(ErrorCode_UnknownResource); | |
2938 } | |
2939 else | |
2940 { | |
2941 countInstances_ = 0; | |
2942 countSeries_ = 0; | |
2943 countStudies_ = 0; | |
2944 diskSize_ = 0; | |
2945 uncompressedSize_ = 0; | |
2946 dicomDiskSize_ = 0; | |
2947 dicomUncompressedSize_ = 0; | |
2948 | |
2949 std::stack<int64_t> toExplore; | |
2950 toExplore.push(top); | |
2951 | |
2952 while (!toExplore.empty()) | |
2953 { | |
2954 // Get the internal ID of the current resource | |
2955 int64_t resource = toExplore.top(); | |
2956 toExplore.pop(); | |
2957 | |
2958 ResourceType thisType = transaction.GetResourceType(resource); | |
2959 | |
2960 std::set<FileContentType> f; | |
2961 transaction.ListAvailableAttachments(f, resource); | |
2962 | |
2963 for (std::set<FileContentType>::const_iterator | |
2964 it = f.begin(); it != f.end(); ++it) | |
2965 { | |
2966 FileInfo attachment; | |
2967 if (transaction.LookupAttachment(attachment, resource, *it)) | |
2968 { | |
2969 if (attachment.GetContentType() == FileContentType_Dicom) | |
2970 { | |
2971 dicomDiskSize_ += attachment.GetCompressedSize(); | |
2972 dicomUncompressedSize_ += attachment.GetUncompressedSize(); | |
2973 } | |
2974 | |
2975 diskSize_ += attachment.GetCompressedSize(); | |
2976 uncompressedSize_ += attachment.GetUncompressedSize(); | |
2977 } | |
2978 } | |
2979 | |
2980 if (thisType == ResourceType_Instance) | |
2981 { | |
2982 countInstances_++; | |
2983 } | |
2984 else | |
2985 { | |
2986 switch (thisType) | |
2987 { | |
2988 case ResourceType_Study: | |
2989 countStudies_++; | |
2990 break; | |
2991 | |
2992 case ResourceType_Series: | |
2993 countSeries_++; | |
2994 break; | |
2995 | |
2996 default: | |
2997 break; | |
2998 } | |
2999 | |
3000 // Tag all the children of this resource as to be explored | |
3001 std::list<int64_t> tmp; | |
3002 transaction.GetChildrenInternalId(tmp, resource); | |
3003 for (std::list<int64_t>::const_iterator | |
3004 it = tmp.begin(); it != tmp.end(); ++it) | |
3005 { | |
3006 toExplore.push(*it); | |
3007 } | |
3008 } | |
3009 } | |
3010 | |
3011 if (countStudies_ == 0) | |
3012 { | |
3013 countStudies_ = 1; | |
3014 } | |
3015 | |
3016 if (countSeries_ == 0) | |
3017 { | |
3018 countSeries_ = 1; | |
3019 } | |
3020 } | |
3021 } | |
3022 }; | |
3023 | |
3024 Operations operations(type, diskSize, uncompressedSize, countStudies, countSeries, | |
3025 countInstances, dicomDiskSize, dicomUncompressedSize, publicId); | |
3026 Apply(operations); | |
3027 } | |
3028 | |
3029 | |
3030 void ServerIndex::LookupIdentifierExact(std::vector<std::string>& result, | |
3031 ResourceType level, | |
3032 const DicomTag& tag, | |
3033 const std::string& value) | |
3034 { | |
3035 assert((level == ResourceType_Patient && tag == DICOM_TAG_PATIENT_ID) || | |
3036 (level == ResourceType_Study && tag == DICOM_TAG_STUDY_INSTANCE_UID) || | |
3037 (level == ResourceType_Study && tag == DICOM_TAG_ACCESSION_NUMBER) || | |
3038 (level == ResourceType_Series && tag == DICOM_TAG_SERIES_INSTANCE_UID) || | |
3039 (level == ResourceType_Instance && tag == DICOM_TAG_SOP_INSTANCE_UID)); | |
3040 | |
3041 result.clear(); | |
3042 | |
3043 DicomTagConstraint c(tag, ConstraintType_Equal, value, true, true); | |
3044 | |
3045 std::vector<DatabaseConstraint> query; | |
3046 query.push_back(c.ConvertToDatabaseConstraint(level, DicomTagType_Identifier)); | |
3047 | |
3048 | |
3049 class Operations : public ServerIndex::IReadOnlyOperations | |
3050 { | |
3051 private: | |
3052 std::vector<std::string>& result_; | |
3053 const std::vector<DatabaseConstraint>& query_; | |
3054 ResourceType level_; | |
3105 | 3055 |
3106 public: | 3056 public: |
3107 Operations() : | 3057 Operations(std::vector<std::string>& result, |
3108 found_(false) | 3058 const std::vector<DatabaseConstraint>& query, |
3109 { | 3059 ResourceType level) : |
3110 } | 3060 result_(result), |
3111 | 3061 query_(query), |
3112 bool HasFound() | 3062 level_(level) |
3113 { | 3063 { |
3114 return found_; | 3064 } |
3115 } | 3065 |
3116 | 3066 virtual void Apply(ReadOnlyTransaction& transaction) ORTHANC_OVERRIDE |
3067 { | |
3068 std::list<std::string> tmp; | |
3069 transaction.ApplyLookupResources(tmp, NULL, query_, level_, 0); | |
3070 CopyListToVector(result_, tmp); | |
3071 } | |
3072 }; | |
3073 | |
3074 Operations operations(result, query, level); | |
3075 Apply(operations); | |
3076 } | |
3077 | |
3078 | |
3079 bool ServerIndex::LookupGlobalProperty(std::string& value, | |
3080 GlobalProperty property) | |
3081 { | |
3082 class Operations : public ReadOnlyOperationsT3<bool*, std::string*, GlobalProperty> | |
3083 { | |
3084 public: | |
3117 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | 3085 virtual void ApplyTuple(ReadOnlyTransaction& transaction, |
3118 const Tuple& tuple) ORTHANC_OVERRIDE | 3086 const Tuple& tuple) ORTHANC_OVERRIDE |
3119 { | 3087 { |
3088 *tuple.get<0>() = transaction.LookupGlobalProperty(*tuple.get<1>(), tuple.get<2>()); | |
3089 } | |
3090 }; | |
3091 | |
3092 bool found; | |
3093 Operations operations; | |
3094 operations.Apply(*this, &found, &value, property); | |
3095 return found; | |
3096 } | |
3097 | |
3098 | |
3099 std::string ServerIndex::GetGlobalProperty(GlobalProperty property, | |
3100 const std::string& defaultValue) | |
3101 { | |
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; | |
3116 Operations operations; | |
3117 operations.Apply(*this, &s, property, defaultValue); | |
3118 return s; | |
3119 } | |
3120 | |
3121 | |
3122 bool ServerIndex::GetMainDicomTags(DicomMap& result, | |
3123 const std::string& publicId, | |
3124 ResourceType expectedType, | |
3125 ResourceType levelOfInterest) | |
3126 { | |
3127 // Yes, the following test could be shortened, but we wish to make it as clear as possible | |
3128 if (!(expectedType == ResourceType_Patient && levelOfInterest == ResourceType_Patient) && | |
3129 !(expectedType == ResourceType_Study && levelOfInterest == ResourceType_Patient) && | |
3130 !(expectedType == ResourceType_Study && levelOfInterest == ResourceType_Study) && | |
3131 !(expectedType == ResourceType_Series && levelOfInterest == ResourceType_Series) && | |
3132 !(expectedType == ResourceType_Instance && levelOfInterest == ResourceType_Instance)) | |
3133 { | |
3134 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
3135 } | |
3136 | |
3137 | |
3138 class Operations : public ReadOnlyOperationsT5<bool*, DicomMap*, std::string, ResourceType, ResourceType> | |
3139 { | |
3140 public: | |
3141 virtual void ApplyTuple(ReadOnlyTransaction& transaction, | |
3142 const Tuple& tuple) ORTHANC_OVERRIDE | |
3143 { | |
3144 // Lookup for the requested resource | |
3145 int64_t id; | |
3120 ResourceType type; | 3146 ResourceType type; |
3121 int64_t id; | 3147 if (!transaction.LookupResource(id, type, tuple.get<2>()) || |
3122 if (!transaction.LookupResource(id, type, tuple.get<1>())) | 3148 type != tuple.get<3>()) |
3123 { | 3149 { |
3124 throw OrthancException(ErrorCode_UnknownResource); | 3150 *tuple.get<0>() = false; |
3151 } | |
3152 else if (type == ResourceType_Study) | |
3153 { | |
3154 DicomMap tmp; | |
3155 transaction.GetMainDicomTags(tmp, id); | |
3156 | |
3157 switch (tuple.get<4>()) | |
3158 { | |
3159 case ResourceType_Patient: | |
3160 tmp.ExtractPatientInformation(*tuple.get<1>()); | |
3161 *tuple.get<0>() = true; | |
3162 break; | |
3163 | |
3164 case ResourceType_Study: | |
3165 tmp.ExtractStudyInformation(*tuple.get<1>()); | |
3166 *tuple.get<0>() = true; | |
3167 break; | |
3168 | |
3169 default: | |
3170 throw OrthancException(ErrorCode_InternalError); | |
3171 } | |
3125 } | 3172 } |
3126 else | 3173 else |
3127 { | 3174 { |
3128 int64_t parentId; | 3175 transaction.GetMainDicomTags(*tuple.get<1>(), id); |
3129 if (transaction.LookupParent(parentId, id)) | 3176 *tuple.get<0>() = true; |
3130 { | 3177 } |
3131 *tuple.get<0>() = transaction.GetPublicId(parentId); | |
3132 found_ = true; | |
3133 } | |
3134 } | |
3135 } | 3178 } |
3136 }; | 3179 }; |
3137 | 3180 |
3181 result.Clear(); | |
3182 | |
3183 bool found; | |
3138 Operations operations; | 3184 Operations operations; |
3139 operations.Apply(*this, &target, publicId); | 3185 operations.Apply(*this, &found, &result, publicId, expectedType, levelOfInterest); |
3140 return operations.HasFound(); | 3186 return found; |
3141 } | 3187 } |
3142 } | 3188 } |