# HG changeset patch # User Alain Mazy # Date 1702656943 -3600 # Node ID dceed5e3d6a9226eaf9d366b3c46f291a7bb2bce # Parent 2829889bfa577927f6dc59ff8070e05a0ac878d9 new DB plugin primitive: UpdateAndGetStatistics diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp Fri Dec 15 17:15:43 2023 +0100 @@ -1478,7 +1478,7 @@ activeTransaction_(NULL), fastGetTotalSize_(false), currentDiskSize_(0), - dbCapabilities_(false, false, false, false) + dbCapabilities_(false, false, false, false, false) { static const char* const MISSING = " Missing extension in database index plugin: "; diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp Fri Dec 15 17:15:43 2023 +0100 @@ -1088,7 +1088,11 @@ errorDictionary_(errorDictionary), database_(database), serverIdentifier_(serverIdentifier), - dbCapabilities_(false, false /* revision support is updated in open() */, false, false) + dbCapabilities_(false, /* hasFlushToDisk */ + false, /* revision support is updated in open() */ + false, /* hasLabelsSupport */ + false, /* hasAtomicIncrementGlobalProperty */ + false /* hasUpdateAndGetStatistics */) { CLOG(INFO, PLUGINS) << "Identifier of this Orthanc server for the global properties " << "of the custom database: \"" << serverIdentifier << "\""; diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp --- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp Fri Dec 15 17:15:43 2023 +0100 @@ -791,7 +791,25 @@ return response.increment_global_property().new_value(); } - + + virtual void UpdateAndGetStatistics(int64_t& patientsCount, + int64_t& studiesCount, + int64_t& seriesCount, + int64_t& instancesCount, + int64_t& compressedSize, + int64_t& uncompressedSize) ORTHANC_OVERRIDE + { + DatabasePluginMessages::TransactionResponse response; + ExecuteTransaction(response, DatabasePluginMessages::OPERATION_UPDATE_AND_GET_STATISTICS); + + patientsCount = response.update_and_get_statistics().patients_count(); + studiesCount = response.update_and_get_statistics().studies_count(); + seriesCount = response.update_and_get_statistics().series_count(); + instancesCount = response.update_and_get_statistics().instances_count(); + compressedSize = response.update_and_get_statistics().total_compressed_size(); + uncompressedSize = response.update_and_get_statistics().total_uncompressed_size(); + } + virtual bool LookupMetadata(std::string& target, int64_t& revision, int64_t id, @@ -1275,7 +1293,7 @@ serverIdentifier_(serverIdentifier), open_(false), databaseVersion_(0), - dbCapabilities_(false, false, false, false) // updated in Open() + dbCapabilities_(false, false, false, false, false) // updated in Open() { CLOG(INFO, PLUGINS) << "Identifier of this Orthanc server for the global properties " << "of the custom database: \"" << serverIdentifier << "\""; @@ -1349,6 +1367,7 @@ dbCapabilities_.hasRevisionsSupport_ = systemInfo.supports_revisions(); dbCapabilities_.hasLabelsSupport_ = systemInfo.supports_labels(); dbCapabilities_.hasAtomicIncrementGlobalProperty_ = systemInfo.supports_increment_global_property(); + dbCapabilities_.hasUpdateAndGetStatistics_ = systemInfo.has_update_and_get_statistics(); } open_ = true; diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto --- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto Fri Dec 15 17:15:43 2023 +0100 @@ -137,6 +137,7 @@ bool supports_revisions = 3; bool supports_labels = 4; bool supports_increment_global_property = 5; + bool has_update_and_get_statistics = 6; } } @@ -277,6 +278,7 @@ OPERATION_REMOVE_LABEL = 46; // New in Orthanc 1.12.0 OPERATION_LIST_LABELS = 47; // New in Orthanc 1.12.0 OPERATION_INCREMENT_GLOBAL_PROPERTY = 48; // New in Orthanc 1.12.X + OPERATION_UPDATE_AND_GET_STATISTICS = 49; // New in Orthanc 1.12.X } message Rollback { @@ -641,6 +643,19 @@ } } +message UpdateAndGetStatistics { + message Request { + } + message Response { + int64 patients_count = 1; + int64 studies_count = 2; + int64 series_count = 3; + int64 instances_count = 4; + int64 total_compressed_size = 5; + int64 total_uncompressed_size = 6; + } +} + message ClearMainDicomTags { message Request { int64 id = 1; @@ -848,6 +863,7 @@ RemoveLabel.Request remove_label = 146; ListLabels.Request list_labels = 147; IncrementGlobalProperty.Request increment_global_property = 148; + UpdateAndGetStatistics.Request update_and_get_statistics = 149; } message TransactionResponse { @@ -900,6 +916,7 @@ RemoveLabel.Response remove_label = 146; ListLabels.Response list_labels = 147; IncrementGlobalProperty.Response increment_global_property = 148; + UpdateAndGetStatistics.Response update_and_get_statistics = 149; } enum RequestType { diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Sources/Database/BaseDatabaseWrapper.h --- a/OrthancServer/Sources/Database/BaseDatabaseWrapper.h Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Sources/Database/BaseDatabaseWrapper.h Fri Dec 15 17:15:43 2023 +0100 @@ -42,6 +42,17 @@ { throw OrthancException(ErrorCode_NotImplemented); // Not supported } + + virtual void UpdateAndGetStatistics(int64_t& patientsCount, + int64_t& studiesCount, + int64_t& seriesCount, + int64_t& instancesCount, + int64_t& compressedSize, + int64_t& uncompressedSize) ORTHANC_OVERRIDE + { + throw OrthancException(ErrorCode_NotImplemented); // Not supported + } + }; }; diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Sources/Database/IDatabaseWrapper.h --- a/OrthancServer/Sources/Database/IDatabaseWrapper.h Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h Fri Dec 15 17:15:43 2023 +0100 @@ -56,16 +56,19 @@ bool hasRevisionsSupport_; bool hasLabelsSupport_; bool hasAtomicIncrementGlobalProperty_; + bool hasUpdateAndGetStatistics_; public: Capabilities(bool hasFlushToDisk, bool hasRevisionsSupport, bool hasLabelsSupport, - bool hasAtomicIncrementGlobalProperty) + bool hasAtomicIncrementGlobalProperty, + bool hasUpdateAndGetStatistics) : hasFlushToDisk_(hasFlushToDisk), hasRevisionsSupport_(hasRevisionsSupport), hasLabelsSupport_(hasLabelsSupport), - hasAtomicIncrementGlobalProperty_(hasAtomicIncrementGlobalProperty) + hasAtomicIncrementGlobalProperty_(hasAtomicIncrementGlobalProperty), + hasUpdateAndGetStatistics_(hasUpdateAndGetStatistics) { } @@ -88,6 +91,12 @@ { return hasAtomicIncrementGlobalProperty_; } + + bool HasUpdateAndGetStatistics() const + { + return hasUpdateAndGetStatistics_; + } + }; struct CreateInstanceResult : public boost::noncopyable @@ -310,6 +319,13 @@ virtual int64_t IncrementGlobalProperty(GlobalProperty property, int64_t increment, bool shared) = 0; + + virtual void UpdateAndGetStatistics(int64_t& patientsCount, + int64_t& studiesCount, + int64_t& seriesCount, + int64_t& instancesCount, + int64_t& compressedSize, + int64_t& uncompressedSize) = 0; }; diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp --- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Fri Dec 15 17:15:43 2023 +0100 @@ -1332,7 +1332,11 @@ activeTransaction_(NULL), signalRemainingAncestor_(NULL), version_(0), - dbCapabilities_(true, false /* TODO: implement revisions in SQLite */, true, false) + dbCapabilities_(true, /* hasFlushToDisk */ + false, /* hasRevisionsSupport TODO: implement revisions in SQLite */ + true, /* hasLabelsSupport */ + false, /* hasAtomicIncrementGlobalProperty */ + false /* hasUpdateAndGetStatistics */) { db_.Open(path); } @@ -1342,7 +1346,11 @@ activeTransaction_(NULL), signalRemainingAncestor_(NULL), version_(0), - dbCapabilities_(true, false /* TODO: implement revisions in SQLite */, true, false) + dbCapabilities_(true, /* hasFlushToDisk */ + false, /* hasRevisionsSupport TODO: implement revisions in SQLite */ + true, /* hasLabelsSupport */ + false, /* hasAtomicIncrementGlobalProperty */ + false /* hasUpdateAndGetStatistics */) { db_.OpenInMemory(); } diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Fri Dec 15 17:15:43 2023 +0100 @@ -1102,7 +1102,54 @@ /* out */ uint64_t& countSeries, /* out */ uint64_t& countInstances) { - class Operations : public ReadOnlyOperationsT6 + // new code that updates and gets all statistics. + // I.e, PostgreSQL now store "changes" to apply to the statistics to prevent row locking + // of the GlobalIntegers table while multiple clients are inserting/deleting new resources. + // Then, the statistics are updated when requested to make sure they are correct. + class Operations : public IReadWriteOperations + { + private: + int64_t diskSize_; + int64_t uncompressedSize_; + int64_t countPatients_; + int64_t countStudies_; + int64_t countSeries_; + int64_t countInstances_; + + public: + Operations() : + diskSize_(0), + uncompressedSize_(0), + countPatients_(0), + countStudies_(0), + countSeries_(0), + countInstances_(0) + { + } + + void GetValues(uint64_t& diskSize, + uint64_t& uncompressedSize, + uint64_t& countPatients, + uint64_t& countStudies, + uint64_t& countSeries, + uint64_t& countInstances) const + { + diskSize = static_cast(diskSize_); + uncompressedSize = static_cast(uncompressedSize_); + countPatients = static_cast(countPatients_); + countStudies = static_cast(countStudies_); + countSeries = static_cast(countSeries_); + countInstances = static_cast(countInstances_); + } + + virtual void Apply(ReadWriteTransaction& transaction) ORTHANC_OVERRIDE + { + transaction.UpdateAndGetStatistics(countPatients_, countStudies_, countSeries_, countInstances_, diskSize_, uncompressedSize_); + } + }; + + // legacy oprations that reads each entry individualy + class LegacyOperations : public ReadOnlyOperationsT6 { public: virtual void ApplyTuple(ReadOnlyTransaction& transaction, @@ -1116,10 +1163,20 @@ tuple.get<5>() = transaction.GetResourcesCount(ResourceType_Instance); } }; - - Operations operations; - operations.Apply(*this, diskSize, uncompressedSize, countPatients, - countStudies, countSeries, countInstances); + + if (GetDatabaseCapabilities().HasUpdateAndGetStatistics()) + { + Operations operations; + Apply(operations); + + operations.GetValues(diskSize, uncompressedSize, countPatients, countStudies, countSeries, countInstances); + } + else + { + LegacyOperations operations; + operations.Apply(*this, diskSize, uncompressedSize, countPatients, + countStudies, countSeries, countInstances); + } } diff -r 2829889bfa57 -r dceed5e3d6a9 OrthancServer/Sources/Database/StatelessDatabaseOperations.h --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Wed Dec 13 15:44:33 2023 +0100 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Fri Dec 15 17:15:43 2023 +0100 @@ -470,6 +470,16 @@ return transaction_.IncrementGlobalProperty(sequence, shared, increment); } + void UpdateAndGetStatistics(int64_t& patientsCount, + int64_t& studiesCount, + int64_t& seriesCount, + int64_t& instancesCount, + int64_t& compressedSize, + int64_t& uncompressedSize) + { + return transaction_.UpdateAndGetStatistics(patientsCount, studiesCount, seriesCount, instancesCount, compressedSize, uncompressedSize); + } + void SetMetadata(int64_t id, MetadataType type, const std::string& value,